diff --git a/packages/pyright-internal/src/analyzer/checker.ts b/packages/pyright-internal/src/analyzer/checker.ts index 8041b6596..cc888ae19 100644 --- a/packages/pyright-internal/src/analyzer/checker.ts +++ b/packages/pyright-internal/src/analyzer/checker.ts @@ -6132,9 +6132,11 @@ export class Checker extends ParseTreeWalker { } // If the symbol has no declaration, and the type is inferred, - // skip this check. - if (!symbol.hasTypedDeclarations() && !this._evaluator.isFinalVariable(symbol)) { - return; + // skip the type validation but still check for other issues like + // Final overrides and class/instance variable mismatches. + let validateType = true; + if (!symbol.hasTypedDeclarations()) { + validateType = false; } // Get the symbol type defined in this class. @@ -6169,7 +6171,13 @@ export class Checker extends ParseTreeWalker { firstOverride = firstOverride ?? baseClassAndSymbol; - this._validateBaseClassOverride(baseClassAndSymbol, symbol, typeOfSymbol, classType, name); + this._validateBaseClassOverride( + baseClassAndSymbol, + symbol, + validateType ? typeOfSymbol : AnyType.create(), + classType, + name + ); } if (!firstOverride) { diff --git a/packages/pyright-internal/src/tests/samples/protocol3.py b/packages/pyright-internal/src/tests/samples/protocol3.py index ab4e71be6..5f232d485 100644 --- a/packages/pyright-internal/src/tests/samples/protocol3.py +++ b/packages/pyright-internal/src/tests/samples/protocol3.py @@ -110,14 +110,12 @@ _Self = TypeVar("_Self") class Class5: @property - def real(self: _Self) -> _Self: - ... + def real(self: _Self) -> _Self: ... class MockClass5(Protocol[_T_co]): @property - def real(self) -> _T_co: - ... + def real(self) -> _T_co: ... foo5 = Class5() @@ -130,14 +128,12 @@ C6 = TypeVar("C6", bound="Class6") class MockClass6(Protocol): @property - def bar(self: P6) -> ContextManager[P6]: - ... + def bar(self: P6) -> ContextManager[P6]: ... class Class6: @property - def bar(self: C6) -> ContextManager[C6]: - ... + def bar(self: C6) -> ContextManager[C6]: ... i: MockClass6 = Class6() @@ -158,8 +154,7 @@ a: Proto7 = Class7("") class Proto8(Protocol): @property - def x(self) -> str: - ... + def x(self) -> str: ... class Class8(NamedTuple): @@ -171,12 +166,10 @@ b: Proto8 = Class8("") class Proto9(Protocol): @property - def x(self) -> str: - ... + def x(self) -> str: ... @x.setter - def x(self, n: str) -> None: - ... + def x(self, n: str) -> None: ... class Proto10(Protocol): @@ -231,11 +224,11 @@ p11_1: Proto11 = Concrete11() class Proto12(Protocol): - val1: Sequence[int] + val1: list[int] class Concrete12: - val1: ClassVar[Sequence[int]] + val1: ClassVar = [1, 2, 3] # This should generate an error because of a ClassVar mismatch. @@ -255,12 +248,10 @@ T13 = TypeVar("T13", covariant=True) class Proto13(Protocol[T13]): @property - def prop1(self) -> T13: - ... + def prop1(self) -> T13: ... -class Proto14(Proto13[T13], Protocol): - ... +class Proto14(Proto13[T13], Protocol): ... class Concrete14(Generic[T13]): @@ -268,8 +259,7 @@ class Concrete14(Generic[T13]): self.prop1 = val -def func14(val: Proto14[T13]): - ... +def func14(val: Proto14[T13]): ... func14(Concrete14(1)) diff --git a/packages/pyright-internal/src/tests/samples/protocolExplicit1.py b/packages/pyright-internal/src/tests/samples/protocolExplicit1.py index 9792c8689..95c30c2a1 100644 --- a/packages/pyright-internal/src/tests/samples/protocolExplicit1.py +++ b/packages/pyright-internal/src/tests/samples/protocolExplicit1.py @@ -26,8 +26,7 @@ class Protocol3(Protocol2, Protocol): cm11: int -class Concrete1(Protocol1): - ... +class Concrete1(Protocol1): ... # This should generate an error because some attributes are not implemented. @@ -67,8 +66,7 @@ Concrete4() class Protocol5(Protocol): - def method1(self) -> int: - ... + def method1(self) -> int: ... # This should generate an error because "method1" is @@ -93,8 +91,7 @@ class Concrete6(Mixin, Protocol6): class Protocol7(Protocol): @abstractmethod - def method1(self): - ... + def method1(self): ... class Mixin7(Protocol7, ABC): @@ -112,3 +109,12 @@ class Concrete7A(Protocol7): @final class Concrete7B(Mixin7, Protocol7): pass + + +class Protocol8(Protocol): + x: int + + +class Concrete8(Protocol8): + # This should generate an error because x is a ClassVar. + x: ClassVar = 1 diff --git a/packages/pyright-internal/src/tests/typeEvaluator2.test.ts b/packages/pyright-internal/src/tests/typeEvaluator2.test.ts index 424269c22..8f4b6e0ca 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator2.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator2.test.ts @@ -1414,7 +1414,7 @@ test('Protocol48', () => { test('ProtocolExplicit1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['protocolExplicit1.py']); - TestUtils.validateResults(analysisResults, 4); + TestUtils.validateResults(analysisResults, 5); }); test('ProtocolExplicit3', () => {