Skip to content

Commit

Permalink
Fixed a bug that led to a confusing error message when assigning a va…
Browse files Browse the repository at this point in the history
…lue with an incompatible type to a class variable that has no explicit type declaration. This addresses #6106. (#6107)

Co-authored-by: Eric Traut <erictr@microsoft.com>
  • Loading branch information
erictraut and msfterictraut authored Oct 9, 2023
1 parent 7e848e8 commit 08592ed
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 5 deletions.
11 changes: 7 additions & 4 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2000,7 +2000,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
}
}

if (memberInfo) {
if (memberInfo && !memberInfo.isSetTypeError) {
return {
type: memberInfo.type,
classType: memberInfo.classType,
Expand Down Expand Up @@ -2102,7 +2102,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
}
}

if (memberInfo) {
if (memberInfo && !memberInfo.isSetTypeError) {
return {
type: memberInfo.type,
isIncomplete: !!memberInfo.isTypeIncomplete,
Expand Down Expand Up @@ -5776,6 +5776,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
return undefined;
}
type = descriptorResult.type;
let isSetTypeError = false;

if (usage.method === 'set' && usage.setType) {
// Verify that the assigned type is compatible.
Expand All @@ -5789,7 +5790,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
})
);
}
return undefined;
isSetTypeError = true;
}

if (
Expand All @@ -5802,14 +5803,15 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
name: printType(ClassType.cloneAsInstance(memberInfo.classType)),
})
);
return undefined;
isSetTypeError = true;
}
}

return {
symbol: memberInfo.symbol,
type,
isTypeIncomplete,
isSetTypeError,
isClassMember: !memberInfo.isInstanceMember,
isClassVar: memberInfo.isClassVar,
classType: memberInfo.classType,
Expand All @@ -5831,6 +5833,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
symbol: undefined,
type: generalAttrType.type,
isTypeIncomplete: false,
isSetTypeError: false,
isClassMember: false,
isClassVar: false,
isAsymmetricAccessor: generalAttrType.isAsymmetricAccessor,
Expand Down
3 changes: 3 additions & 0 deletions packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@ export interface ClassMemberLookup {
type: Type;
isTypeIncomplete: boolean;

// True if access violates the type (used only for 'set' usage).
isSetTypeError: boolean;

// True if class member, false otherwise.
isClassMember: boolean;

Expand Down
1 change: 1 addition & 0 deletions packages/pyright-internal/src/tests/samples/metaclass11.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ClassB(metaclass=MetaB):
var0: int


# This should generate an error
ClassB.var0 = ""
ClassB.var1 = ""

Expand Down
2 changes: 1 addition & 1 deletion packages/pyright-internal/src/tests/typeEvaluator4.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ test('Metaclass10', () => {

test('Metaclass11', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['metaclass11.py']);
TestUtils.validateResults(analysisResults, 3);
TestUtils.validateResults(analysisResults, 4);
});

test('AssignmentExpr1', () => {
Expand Down

0 comments on commit 08592ed

Please sign in to comment.