diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/typing/PyProtocols.kt b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/typing/PyProtocols.kt index 5d74b81d53e3..ba7e9296782f 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/typing/PyProtocols.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/typing/PyProtocols.kt @@ -1,6 +1,7 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.codeInsight.typing +import com.intellij.psi.util.contextOfType import com.jetbrains.python.PyNames import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider.PROTOCOL import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider.PROTOCOL_EXT @@ -41,6 +42,10 @@ fun inspectProtocolSubclass(protocol: PyClassType, subclass: PyClassType, contex return@visitMembers true } + if (e.contextOfType()?.containingClass == protocol.pyClass) { + return@visitMembers true + } + val name = e.name ?: return@visitMembers true when (name) { PyNames.SLOTS -> return@visitMembers true // __slots__ in a protocol definition are not considered to be a part of the protocol diff --git a/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java index 759997014bd6..b24259041d9b 100644 --- a/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java @@ -3098,4 +3098,31 @@ def foo(param: str | int) -> TypeGuard[str]: public void testStrictUnionImplicitProtocolMatching() { doTest(); } + + // PY-76822 + public void testProtocolWithAssignedPropertyInMethod() { + doTestByText(""" + from typing import Protocol + + class Template(Protocol): + name: str + value: int = 0 + + def method(self) -> None: + self.name = "name" + self.temp: list[int] = [] + + + class Concrete: + def __init__(self, name: str, value: int) -> None: + self.name = name + self.value = value + + def method(self) -> None: + return + + + var: Template = Concrete("value", 42) + """); + } }