From 689c091fd7c8c0156dba19fa5eb9bd08409d9694 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 12 Jul 2017 19:47:18 +0300 Subject: [PATCH] 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. --- .../python/psi/types/PyTypeChecker.java | 2 +- .../com/jetbrains/python/PyTypingTest.java | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java index 1b569176e27e..9827cdce647d 100644 --- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java +++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java @@ -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; diff --git a/python/testSrc/com/jetbrains/python/PyTypingTest.java b/python/testSrc/com/jetbrains/python/PyTypingTest.java index 88e96144e56a..369f12d99800 100644 --- a/python/testSrc/com/jetbrains/python/PyTypingTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypingTest.java @@ -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());