mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-21175 Don't lost explicit Any added by a definition in the result Union
We need to distinguish between initial synthetic value in the incremental union used to combine types and the actual "Any" type inferred from one of the definitions.
This commit is contained in:
@@ -504,22 +504,23 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
|
||||
final PyElement element = augAssignment != null ? augAssignment : anchor;
|
||||
try {
|
||||
final List<Instruction> defs = PyDefUseUtil.getLatestDefs(scopeOwner, name, element, true, false);
|
||||
PyType type = null;
|
||||
for (Instruction def : defs) {
|
||||
final ReadWriteInstruction instruction = PyUtil.as(def, ReadWriteInstruction.class);
|
||||
if (instruction != null) {
|
||||
final Ref<PyType> instructionType = instruction.getType(context, anchor);
|
||||
if (instructionType != null) {
|
||||
if (type != null) {
|
||||
type = PyUnionType.union(type, instructionType.get());
|
||||
}
|
||||
else {
|
||||
type = instructionType.get();
|
||||
}
|
||||
// null means empty set of possible types, Ref(null) means Any
|
||||
final @Nullable Ref<PyType> combinedType = StreamEx.of(defs)
|
||||
.select(ReadWriteInstruction.class)
|
||||
.map(instr -> instr.getType(context, anchor))
|
||||
// don't use foldLeft(BiFunction) here, as it doesn't support null results
|
||||
.foldLeft(null, (accType, defType) -> {
|
||||
if (defType == null) {
|
||||
return accType;
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
else if (accType == null) {
|
||||
return defType;
|
||||
}
|
||||
else {
|
||||
return Ref.create(PyUnionType.union(accType.get(), defType.get()));
|
||||
}
|
||||
});
|
||||
return Ref.deref(combinedType);
|
||||
}
|
||||
catch (PyDefUseUtil.InstructionNotFoundException ignored) {
|
||||
}
|
||||
|
||||
@@ -2001,6 +2001,17 @@ public class PyTypeTest extends PyTestCase {
|
||||
"expr = xs\n");
|
||||
}
|
||||
|
||||
// PY-21175
|
||||
public void testAnyAddedByConditionalDefinition() {
|
||||
doTest("Union[str, Any]",
|
||||
"def f(x, y):\n" +
|
||||
" if x:\n" +
|
||||
" var = y\n" +
|
||||
" else:\n" +
|
||||
" var = 'foo'\n" +
|
||||
" expr = var");
|
||||
}
|
||||
|
||||
private static List<TypeEvalContext> getTypeEvalContexts(@NotNull PyExpression element) {
|
||||
return ImmutableList.of(TypeEvalContext.codeAnalysis(element.getProject(), element.getContainingFile()).withTracing(),
|
||||
TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).withTracing());
|
||||
|
||||
Reference in New Issue
Block a user