mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[python] PY-81651 respect explicit Any on binary operators
Merge-request: IJ-MR-174645 Merged-by: Morgan Bartholomew <morgan.bartholomew@jetbrains.com> GitOrigin-RevId: 9062f58b163d99f526f2bb0c3ebfa29039508f54
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0fc7813dec
commit
a13764a6b7
+10
-8
@@ -68,15 +68,17 @@ public class PyBinaryExpressionImpl extends PyElementImpl implements PyBinaryExp
|
||||
return PyBuiltinCache.getInstance(this).getBoolType();
|
||||
}
|
||||
PyType callResultType = PyCallExpressionHelper.getCallType(this, context, key);
|
||||
if (callResultType != null) {
|
||||
boolean bothOperandsAreKnown = operandIsKnown(getLeftExpression(), context) && operandIsKnown(getRightExpression(), context);
|
||||
// TODO requires weak union. See PyTypeCheckerInspectionTest#testBinaryExpressionWithUnknownOperand
|
||||
return bothOperandsAreKnown ? callResultType : PyUnionType.createWeakType(callResultType);
|
||||
if (callResultType == null) {
|
||||
if (referencedName != null && PyNames.COMPARISON_OPERATORS.contains(referencedName)) {
|
||||
// we don't know if it was explicit or not, so we form an unsafe union of Any and bool
|
||||
// TODO: when { explicit Any -> Any, Unknown -> UnsafeUnion[bool | Any] }
|
||||
return PyUnsafeUnionType.unsafeUnion(null, PyBuiltinCache.getInstance(this).getBoolType());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (referencedName != null && PyNames.COMPARISON_OPERATORS.contains(referencedName)) {
|
||||
return PyBuiltinCache.getInstance(this).getBoolType();
|
||||
}
|
||||
return null;
|
||||
boolean bothOperandsAreKnown = operandIsKnown(getLeftExpression(), context) && operandIsKnown(getRightExpression(), context);
|
||||
// TODO requires weak union. See PyTypeCheckerInspectionTest#testBinaryExpressionWithUnknownOperand
|
||||
return bothOperandsAreKnown ? callResultType : PyUnionType.createWeakType(callResultType);
|
||||
}
|
||||
|
||||
private static boolean operandIsKnown(@Nullable PyExpression operand, @NotNull TypeEvalContext context) {
|
||||
|
||||
@@ -11,7 +11,7 @@ def test():
|
||||
c = C()
|
||||
f(<warning descr="Expected type 'str', got 'bool' instead">1 < 2</warning>)
|
||||
f(<warning descr="Expected type 'str', got 'bool' instead">o == o</warning>)
|
||||
f(<warning descr="Expected type 'str', got 'bool' instead">o >= o</warning>)
|
||||
f(o >= o)
|
||||
f(<warning descr="Expected type 'str', got 'bool' instead">'foo' > 'bar'</warning>)
|
||||
f(<warning descr="Expected type 'str', got 'bool' instead"><warning descr="Expected type 'int', got 'C' instead">c</warning> < 1</warning>)
|
||||
f(<warning descr="Expected type 'str', got 'List[Any]' instead">c > 1</warning>)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2017 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;
|
||||
|
||||
import com.intellij.idea.TestFor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
@@ -3975,6 +3976,20 @@ public class Py3TypeTest extends PyTestCase {
|
||||
""");
|
||||
}
|
||||
|
||||
@TestFor(issues="PY-81651")
|
||||
public void testEqWithAny() {
|
||||
// the actual result is `Any`, but we don't have the technology yet
|
||||
doTest("UnsafeUnion[Any, bool]", """
|
||||
from typing import Any
|
||||
|
||||
class A:
|
||||
def __eq__(self, other) -> Any:
|
||||
return "hello :)"
|
||||
|
||||
expr = A() == 1
|
||||
""");
|
||||
}
|
||||
|
||||
private void doTest(final String expectedType, final String text) {
|
||||
myFixture.configureByText(PythonFileType.INSTANCE, text);
|
||||
final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
|
||||
|
||||
Reference in New Issue
Block a user