mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 09:03:31 +07:00
Restrict matching against callables (PY-29993, PY-28364)
Expected class-like types are not considered as callables (exclusion: bare typing.Callable). Fix matching definition against metaclass. GitOrigin-RevId: a2fe59c3bc7f56ef08dfb960a9ed841a86a65815
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9f32d57ace
commit
17d5a4bbce
@@ -11,6 +11,7 @@ import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PythonRuntimeService;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.codeInsight.typing.PyProtocolsKt;
|
||||
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.impl.PyTypeProvider;
|
||||
@@ -450,6 +451,12 @@ public class PyTypeChecker {
|
||||
private static Optional<Boolean> match(@NotNull PyCallableType expected,
|
||||
@NotNull PyCallableType actual,
|
||||
@NotNull MatchContext matchContext) {
|
||||
if (expected instanceof PyClassLikeType) {
|
||||
return PyTypingTypeProvider.CALLABLE.equals(((PyClassLikeType)expected).getClassQName())
|
||||
? Optional.of(actual.isCallable())
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
if (expected.isCallable() && actual.isCallable()) {
|
||||
final TypeEvalContext context = matchContext.context;
|
||||
final List<PyCallableParameter> expectedParameters = expected.getParameters(context);
|
||||
@@ -489,7 +496,7 @@ public class PyTypeChecker {
|
||||
return false;
|
||||
}
|
||||
final PyClassLikeType metaClass = actual.getMetaClassType(context.context, true);
|
||||
return metaClass != null && match(expected, metaClass, context).orElse(true);
|
||||
return metaClass != null && match(expected, metaClass.toInstance(), context).orElse(true);
|
||||
}
|
||||
|
||||
private static boolean typeVarAcceptsBothClassAndInstanceTypes(@NotNull PyGenericType typeVar) {
|
||||
|
||||
+15
@@ -6,6 +6,10 @@ class SubMetaClass(MetaClass):
|
||||
pass
|
||||
|
||||
|
||||
class MetaClass2(type):
|
||||
pass
|
||||
|
||||
|
||||
class MyClass(object):
|
||||
__metaclass__ = MetaClass
|
||||
pass
|
||||
@@ -26,6 +30,15 @@ class MyClass3(Generated):
|
||||
pass
|
||||
|
||||
|
||||
class MyClass4:
|
||||
__metaclass__ = MetaClass2
|
||||
pass
|
||||
|
||||
|
||||
class MyClass5:
|
||||
pass
|
||||
|
||||
|
||||
def f(x):
|
||||
# type: (MetaClass) -> None
|
||||
pass
|
||||
@@ -35,3 +48,5 @@ f(MyClass)
|
||||
f(MyClass2)
|
||||
f(Generated)
|
||||
f(MyClass3)
|
||||
f(<warning descr="Expected type 'MetaClass', got 'Type[MyClass4]' instead">MyClass4</warning>)
|
||||
f(<warning descr="Expected type 'MetaClass', got 'Type[MyClass5]' instead">MyClass5</warning>)
|
||||
|
||||
@@ -1083,4 +1083,39 @@ public class PyTypeCheckerInspectionTest extends PyInspectionTestCase {
|
||||
public void testTypedDictInStub() {
|
||||
runWithLanguageLevel(LanguageLevel.getLatest(), this::doMultiFileTest);
|
||||
}
|
||||
|
||||
// PY-28364
|
||||
public void testDefinitionAgainstCallableInstance() {
|
||||
runWithLanguageLevel(
|
||||
LanguageLevel.getLatest(),
|
||||
() -> doTestByText("class B:\n" +
|
||||
" def __call__(self, *args, **kwargs):\n" +
|
||||
" pass\n" +
|
||||
"\n" +
|
||||
"def some_fn(arg: B):\n" +
|
||||
" pass\n" +
|
||||
"\n" +
|
||||
"some_fn(<warning descr=\"Expected type 'B', got 'Type[B]' instead\">B</warning>)")
|
||||
);
|
||||
}
|
||||
|
||||
// PY-29993
|
||||
public void testCallableInstanceAgainstOtherCallableInstance() {
|
||||
runWithLanguageLevel(
|
||||
LanguageLevel.getLatest(),
|
||||
() -> doTestByText("class MyCls:\n" +
|
||||
" def __call__(self):\n" +
|
||||
" return True\n" +
|
||||
"\n" +
|
||||
"class DifferentCls:\n" +
|
||||
" def __call__(self):\n" +
|
||||
" return True\n" +
|
||||
"\n" +
|
||||
"def foo(arg: MyCls):\n" +
|
||||
" pass\n" +
|
||||
"\n" +
|
||||
"foo(MyCls())\n" +
|
||||
"foo(<warning descr=\"Expected type 'MyCls', got 'DifferentCls' instead\">DifferentCls()</warning>)")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user