Skip to content

Commit a52db80

Browse files
authored
Fixed bug that causes bidirectional type inference to be skipped when the target of an assignment is a member access expression (base.member) and the base expression is a module. This addresses #10539. (#10577)
1 parent b23d4a2 commit a52db80

File tree

1 file changed

+23
-14
lines changed

1 file changed

+23
-14
lines changed

packages/pyright-internal/src/analyzer/typeEvaluator.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2795,7 +2795,7 @@ export function createTypeEvaluator(
27952795
case ParseNodeType.MemberAccess: {
27962796
const baseType = getTypeOfExpression(expression.d.leftExpr, EvalFlags.MemberAccessBaseDefaults).type;
27972797
const baseTypeConcrete = makeTopLevelTypeVarsConcrete(baseType);
2798-
let classMemberInfo: ClassMember | undefined;
2798+
const memberName = expression.d.member.d.value;
27992799

28002800
// Normally, baseTypeConcrete will not be a composite type (a union),
28012801
// but this can occur. In this case, it's not clear how to handle this
@@ -2805,29 +2805,42 @@ export function createTypeEvaluator(
28052805
baseTypeConcrete,
28062806
(baseSubtype) => {
28072807
if (isClassInstance(baseSubtype)) {
2808-
classMemberInfo = lookUpObjectMember(
2808+
const classMemberInfo = lookUpObjectMember(
28092809
baseSubtype,
2810-
expression.d.member.d.value,
2810+
memberName,
28112811
MemberAccessFlags.DeclaredTypesOnly
28122812
);
2813+
28132814
classOrObjectBase = baseSubtype;
28142815
memberAccessClass = classMemberInfo?.classType;
2816+
symbol = classMemberInfo?.symbol;
2817+
useDescriptorSetterType = true;
28152818

28162819
// If this is an instance member (e.g. a dataclass field), don't
28172820
// bind it to the object if it's a function.
2818-
if (classMemberInfo?.isInstanceMember) {
2819-
bindFunction = false;
2820-
}
2821-
2822-
useDescriptorSetterType = true;
2821+
bindFunction = !classMemberInfo?.isInstanceMember;
28232822
} else if (isInstantiableClass(baseSubtype)) {
2824-
classMemberInfo = lookUpClassMember(
2823+
const classMemberInfo = lookUpClassMember(
28252824
baseSubtype,
2826-
expression.d.member.d.value,
2825+
memberName,
28272826
MemberAccessFlags.SkipInstanceMembers | MemberAccessFlags.DeclaredTypesOnly
28282827
);
2828+
28292829
classOrObjectBase = baseSubtype;
28302830
memberAccessClass = classMemberInfo?.classType;
2831+
symbol = classMemberInfo?.symbol;
2832+
useDescriptorSetterType = false;
2833+
bindFunction = true;
2834+
} else if (isModule(baseSubtype)) {
2835+
classOrObjectBase = undefined;
2836+
memberAccessClass = undefined;
2837+
symbol = ModuleType.getField(baseSubtype, memberName);
2838+
if (symbol && !symbol.hasTypedDeclarations()) {
2839+
// Do not use inferred types for the declared type.
2840+
symbol = undefined;
2841+
}
2842+
useDescriptorSetterType = false;
2843+
bindFunction = false;
28312844
}
28322845
},
28332846
/* sortSubtypes */ true
@@ -2836,10 +2849,6 @@ export function createTypeEvaluator(
28362849
if (isTypeVar(baseType)) {
28372850
selfType = baseType;
28382851
}
2839-
2840-
if (classMemberInfo) {
2841-
symbol = classMemberInfo.symbol;
2842-
}
28432852
break;
28442853
}
28452854

0 commit comments

Comments
 (0)