diff --git a/python/python-psi-api/src/com/jetbrains/python/psi/PyInstantTypeProvider.kt b/python/python-psi-api/src/com/jetbrains/python/psi/PyInstantTypeProvider.kt
new file mode 100644
index 000000000000..55dcd13b46c4
--- /dev/null
+++ b/python/python-psi-api/src/com/jetbrains/python/psi/PyInstantTypeProvider.kt
@@ -0,0 +1,7 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.jetbrains.python.psi
+
+import org.jetbrains.annotations.ApiStatus
+
+@ApiStatus.Internal
+interface PyInstantTypeProvider : PyTypedElement
\ No newline at end of file
diff --git a/python/python-psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java b/python/python-psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java
index 50bb740192b2..c5f3fca67505 100644
--- a/python/python-psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java
+++ b/python/python-psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java
@@ -4,13 +4,12 @@ package com.jetbrains.python.psi.types;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionManager;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.ProcessingContext;
-import com.jetbrains.python.psi.PyCallable;
-import com.jetbrains.python.psi.PyNoneLiteralExpression;
-import com.jetbrains.python.psi.PyTypedElement;
+import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyTypeProvider;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -22,7 +21,7 @@ import java.util.List;
import java.util.Map;
-public final class TypeEvalContext {
+public sealed class TypeEvalContext {
/**
* This class ensures that only {@link TypeEvalContext} instances can directly invoke
@@ -97,7 +96,7 @@ public final class TypeEvalContext {
* Inspections should not create a new type evaluation context. They should re-use the context of the inspection session.
*/
public static TypeEvalContext codeAnalysis(final @NotNull Project project, final @Nullable PsiFile origin) {
- return getContextFromCache(project, new TypeEvalContext(false, false, false, origin));
+ return getContextFromCache(project, buildCodeAnalysisContext(origin));
}
/**
@@ -124,6 +123,13 @@ public final class TypeEvalContext {
return getContextFromCache(project, new TypeEvalContext(false, true, false, null));
}
+ private static TypeEvalContext buildCodeAnalysisContext(@Nullable PsiFile origin) {
+ if (Registry.is("python.optimized.type.eval.context")) {
+ return new OptimizedTypeEvalContext(false, false, false, origin);
+ }
+ return new TypeEvalContext(false, false, false, origin);
+ }
+
/**
* Moves context through cache returning one from cache (if exists).
*
@@ -283,4 +289,48 @@ public final class TypeEvalContext {
return getContextFile(context);
}
}
+
+ final static class OptimizedTypeEvalContext extends TypeEvalContext {
+ private volatile TypeEvalContext codeInsightFallback;
+
+ OptimizedTypeEvalContext(boolean allowDataFlow, boolean allowStubToAST, boolean allowCallContext, @Nullable PsiFile origin) {
+ super(allowDataFlow, allowStubToAST, allowCallContext, origin);
+ }
+
+ private boolean shouldSwitchToFallbackContext(PsiElement element) {
+ PsiFile file = element.getContainingFile();
+ if (file instanceof PyExpressionCodeFragment codeFragment) {
+ PsiElement context = codeFragment.getContext();
+ if (context != null) {
+ file = context.getContainingFile();
+ }
+ }
+ TypeEvalConstraints constraints = getConstraints();
+ return constraints.myOrigin != null && file != constraints.myOrigin && (file instanceof PyFile) &&
+ !constraints.myAllowDataFlow && !constraints.myAllowStubToAST && !constraints.myAllowCallContext;
+ }
+
+ private TypeEvalContext getFallbackContext(Project project) {
+ if (codeInsightFallback == null) {
+ codeInsightFallback = codeInsightFallback(project);
+ }
+ return codeInsightFallback;
+ }
+
+ @Override
+ public @Nullable PyType getType(@NotNull PyTypedElement element) {
+ if (shouldSwitchToFallbackContext(element)) {
+ return getFallbackContext(element.getProject()).getType(element);
+ }
+ return super.getType(element);
+ }
+
+ @Override
+ public @Nullable PyType getReturnType(@NotNull PyCallable callable) {
+ if (shouldSwitchToFallbackContext(callable)) {
+ return getFallbackContext(callable.getProject()).getReturnType(callable);
+ }
+ return super.getReturnType(callable);
+ }
+ }
}
diff --git a/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml b/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
index 3e538adbd78e..33764f35547d 100644
--- a/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
+++ b/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml
@@ -477,6 +477,8 @@
description="Require marking namespace packages explicitly, treat regular directories as implicit source roots"/>
+
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyBoolLiteralExpressionImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyBoolLiteralExpressionImpl.java
index aba98d9bd095..90a6e30d87e4 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyBoolLiteralExpressionImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyBoolLiteralExpressionImpl.java
@@ -4,12 +4,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyBoolLiteralExpression;
import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
-public class PyBoolLiteralExpressionImpl extends PyElementImpl implements PyBoolLiteralExpression {
+public class PyBoolLiteralExpressionImpl extends PyElementImpl implements PyBoolLiteralExpression, PyInstantTypeProvider {
public PyBoolLiteralExpressionImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyDoubleStarExpressionImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyDoubleStarExpressionImpl.java
index 1299b54a4495..0d22a08c6c03 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyDoubleStarExpressionImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyDoubleStarExpressionImpl.java
@@ -18,12 +18,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyDoubleStarExpression;
import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class PyDoubleStarExpressionImpl extends PyElementImpl implements PyDoubleStarExpression {
+public class PyDoubleStarExpressionImpl extends PyElementImpl implements PyDoubleStarExpression, PyInstantTypeProvider {
public PyDoubleStarExpressionImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyDoubleStarPatternImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyDoubleStarPatternImpl.java
index f5c4dfd8e114..64fe3beae3c1 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyDoubleStarPatternImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyDoubleStarPatternImpl.java
@@ -3,12 +3,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyDoubleStarPattern;
import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class PyDoubleStarPatternImpl extends PyElementImpl implements PyDoubleStarPattern {
+public class PyDoubleStarPatternImpl extends PyElementImpl implements PyDoubleStarPattern, PyInstantTypeProvider {
public PyDoubleStarPatternImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyEmptyExpressionImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyEmptyExpressionImpl.java
index caaa32c3a687..4247f8ca065c 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyEmptyExpressionImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyEmptyExpressionImpl.java
@@ -3,12 +3,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyEmptyExpression;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
-public class PyEmptyExpressionImpl extends PyElementImpl implements PyEmptyExpression {
+public class PyEmptyExpressionImpl extends PyElementImpl implements PyEmptyExpression, PyInstantTypeProvider {
public PyEmptyExpressionImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyKeyValuePatternImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyKeyValuePatternImpl.java
index 5bc2c8eb59da..0b22e0cbb48d 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyKeyValuePatternImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyKeyValuePatternImpl.java
@@ -2,6 +2,7 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyKeyValuePattern;
import com.jetbrains.python.psi.PyPattern;
import com.jetbrains.python.psi.types.PyTupleType;
@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
-public class PyKeyValuePatternImpl extends PyElementImpl implements PyKeyValuePattern {
+public class PyKeyValuePatternImpl extends PyElementImpl implements PyKeyValuePattern, PyInstantTypeProvider {
public PyKeyValuePatternImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNoneLiteralExpressionImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNoneLiteralExpressionImpl.java
index 1268db5e2b7c..932bd5f8560a 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNoneLiteralExpressionImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNoneLiteralExpressionImpl.java
@@ -17,6 +17,7 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyNoneLiteralExpression;
import com.jetbrains.python.psi.types.PyNoneType;
import com.jetbrains.python.psi.types.PyType;
@@ -25,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class PyNoneLiteralExpressionImpl extends PyElementImpl implements PyNoneLiteralExpression {
+public class PyNoneLiteralExpressionImpl extends PyElementImpl implements PyNoneLiteralExpression, PyInstantTypeProvider {
public PyNoneLiteralExpressionImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNumericLiteralExpressionImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNumericLiteralExpressionImpl.java
index d19ea0df6aa0..33045d245f29 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNumericLiteralExpressionImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNumericLiteralExpressionImpl.java
@@ -19,6 +19,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.IElementType;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyNumericLiteralExpression;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -26,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class PyNumericLiteralExpressionImpl extends PyElementImpl implements PyNumericLiteralExpression {
+public class PyNumericLiteralExpressionImpl extends PyElementImpl implements PyNumericLiteralExpression, PyInstantTypeProvider {
public PyNumericLiteralExpressionImpl(@NotNull ASTNode astNode) {
super(astNode);
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyReprExpressionImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyReprExpressionImpl.java
index 2d45f6e45877..2a70026c86da 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyReprExpressionImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyReprExpressionImpl.java
@@ -3,13 +3,14 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyReprExpression;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
-public class PyReprExpressionImpl extends PyElementImpl implements PyReprExpression {
+public class PyReprExpressionImpl extends PyElementImpl implements PyReprExpression, PyInstantTypeProvider {
public PyReprExpressionImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PySingleStarPatternImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PySingleStarPatternImpl.java
index e50857893a49..9ee3745357d9 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PySingleStarPatternImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PySingleStarPatternImpl.java
@@ -9,7 +9,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
-public class PySingleStarPatternImpl extends PyElementImpl implements PySingleStarPattern {
+public class PySingleStarPatternImpl extends PyElementImpl implements PySingleStarPattern, PyInstantTypeProvider {
public PySingleStarPatternImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyStarArgumentImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyStarArgumentImpl.java
index 4bb074b783e8..f7d08405d2cd 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyStarArgumentImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyStarArgumentImpl.java
@@ -2,13 +2,14 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyStarArgument;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
-public class PyStarArgumentImpl extends PyElementImpl implements PyStarArgument {
+public class PyStarArgumentImpl extends PyElementImpl implements PyStarArgument, PyInstantTypeProvider {
public PyStarArgumentImpl(ASTNode astNode) {
super(astNode);
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyStarExpressionImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyStarExpressionImpl.java
index a60e67285c2b..86a04efaabf3 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyStarExpressionImpl.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyStarExpressionImpl.java
@@ -3,12 +3,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyStarExpression;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
-public class PyStarExpressionImpl extends PyElementImpl implements PyStarExpression {
+public class PyStarExpressionImpl extends PyElementImpl implements PyStarExpression, PyInstantTypeProvider {
public PyStarExpressionImpl(ASTNode astNode) {
super(astNode);
}