Skip to content

Commit

Permalink
Fixed a bug that led to a false positive error when a frozen dataclas…
Browse files Browse the repository at this point in the history
…s has an explicit `__eq__` method and is used in way that requires it to be `Hashable`. This addresses #5928.
  • Loading branch information
msfterictraut committed Sep 11, 2023
1 parent 46f5351 commit f330161
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 3 deletions.
3 changes: 1 addition & 2 deletions packages/pyright-internal/src/analyzer/dataClasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,7 @@ export function synthesizeDataClassMethods(
});
}

let synthesizeHashFunction =
!ClassType.isSkipSynthesizedDataClassEq(classType) && ClassType.isFrozenDataClass(classType);
let synthesizeHashFunction = ClassType.isFrozenDataClass(classType);
const synthesizeHashNone =
!ClassType.isSkipSynthesizedDataClassEq(classType) && !ClassType.isFrozenDataClass(classType);

Expand Down
5 changes: 4 additions & 1 deletion packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16409,7 +16409,10 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions

let skipSynthesizeHash = false;
const hashSymbol = lookUpClassMember(classType, '__hash__', ClassMemberLookupFlags.SkipBaseClasses);
if (hashSymbol) {

// If there is a hash symbol defined in the class (i.e. one that we didn't
// synthesize above), then we shouldn't synthesize a new one for the dataclass.
if (hashSymbol && !hashSymbol.symbol.getSynthesizedType()) {
skipSynthesizeHash = true;
}

Expand Down
14 changes: 14 additions & 0 deletions packages/pyright-internal/src/analyzer/typeGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2456,3 +2456,17 @@ function narrowTypeForCallable(
}
});
}

export class Animal {}
export class Dog extends Animal {}

export class Plant {}
export class Tree extends Plant {}

export function func1(val: Animal) {
if (val instanceof Tree) {
console.log(val);
} else {
console.log(val);
}
}
11 changes: 11 additions & 0 deletions packages/pyright-internal/src/tests/samples/dataclassHash1.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,14 @@ def __hash__(self) -> int:


v6: Hashable = DC6(0)


@dataclass(frozen=True)
class DC7:
a: int

def __eq__(self, other) -> bool:
return self.a == other.a


v7: Hashable = DC7(0)

0 comments on commit f330161

Please sign in to comment.