PY-24260 Don't check equality of PyGenericTypes using "==", they are not interned

Because we represent both "Type[T]" and "T" as immutable instances of
PyGenericType with different values of isDefinition flag and handle
transition between them in PyTypeChecker.substitute() by creating new
instances of the opposite kind, we can end up searching for the mapping
for "T" in the cache already containing "Type[T]" -> "Type[T]" over and
over again until SOE.
This commit is contained in:
Mikhail Golubev
2017-07-13 12:09:31 +03:00
parent 49f12ad572
commit 689c091fd7
2 changed files with 16 additions and 5 deletions
@@ -470,7 +470,7 @@ public class PyTypeChecker {
}
}
}
if (substitution instanceof PyGenericType && substitution != type) {
if (substitution instanceof PyGenericType && !typeVar.equals(substitution)) {
final PyType recursive = substitute(substitution, substitutions, context);
if (recursive != null) {
return recursive;
@@ -16,13 +16,9 @@
package com.jetbrains.python;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.testFramework.LightProjectDescriptor;
import com.jetbrains.python.documentation.PythonDocumentationProvider;
@@ -957,6 +953,21 @@ public class PyTypingTest extends PyTestCase {
"expr = f(True, 1, 'foo')\n");
}
// PY-24260
public void testGenericClassParameterTakenFromGenericClassObject() {
doTest("MyClass[TypeVar('T')]",
"from typing import TypeVar, Generic, Type\n" +
"\n" +
"T = TypeVar(\"T\")\n" +
"\n" +
"class MyClass(Generic[T]):\n" +
" def __init__(self, type: Type[T]):\n" +
" pass\n" +
"\n" +
"def f(x: Type[T]):\n" +
" expr = MyClass(x)\n");
}
private void doTestNoInjectedText(@NotNull String text) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myFixture.getProject());