FIR: Do not copy type parameters from class to constructors

Use the same instances from class declaration instead

Otherwise, primary constructor value parameter types when used
in the class body are considered as different from types
based on the class type parameters

See the test genericConstructors.kt, before this commit
"id" call was reported in inapplicable
This commit is contained in:
Denis Zharkov
2019-12-05 13:08:51 +03:00
parent 20d02dd0ee
commit b8984d154b
46 changed files with 212 additions and 153 deletions
@@ -9,10 +9,13 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirMemberFunction
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirErrorFunctionImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl
import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.references.FirReference
@@ -35,11 +38,9 @@ import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtStringTemplateEntryWithExpression
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.KtUnaryExpression
import org.jetbrains.kotlin.resolve.constants.evaluate.*
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
//T can be either PsiElement, or LighterASTNode
@@ -150,17 +151,11 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
}
fun KtClassOrObject?.toDelegatedSelfType(firClass: FirRegularClass): FirTypeRef {
val typeParameters = firClass.typeParameters.map {
FirTypeParameterImpl(it.source, session, it.name, FirTypeParameterSymbol(), Variance.INVARIANT, false).apply {
this.bounds += it.bounds
addDefaultBoundIfNecessary()
}
}
return FirResolvedTypeRefImpl(
this?.toFirSourceElement(),
ConeClassLikeTypeImpl(
firClass.symbol.toLookupTag(),
typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
firClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
false
)
)
@@ -1,11 +1,11 @@
FILE: complexTypes.kt
public? final? class C<T, out S> : R|kotlin/Any| {
public? constructor<T, S>(): R|a/b/C<T, S>| {
public? constructor<T, out S>(): R|a/b/C<T, S>| {
super<R|kotlin/Any|>()
}
public? final? inner class D<R, in P> : R|kotlin/Any| {
public? constructor<R, P>(): R|a/b/C.D<R, P>| {
public? constructor<R, in P>(): R|a/b/C.D<R, P>| {
super<R|kotlin/Any|>()
}
@@ -8,7 +8,7 @@ FILE: typeParameters.kt
public? final typealias StringList = List<out String>
public? final typealias AnyList = List<*>
public? abstract class AbstractList<out T : Any> : List<T> {
public? constructor<T : Any>(): R|AbstractList<T>| {
public? constructor<out T : Any>(): R|AbstractList<T>| {
super<R|kotlin/Any|>()
}
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.FirSessionBase
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
@@ -134,16 +135,14 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
override fun visitElement(element: FirElement) {
// NB: types are reused sometimes (e.g. in accessors)
if (!result.add(element)) {
if (element !is FirTypeRef && element !is FirNoReceiverExpression && element !is FirEmptyContractDescription && !element.isExtensionFunctionAnnotation) {
val elementDump = StringBuilder().also { element.accept(FirRenderer(it)) }.toString()
throw AssertionError("FirElement ${element.javaClass} is visited twice: $elementDump")
}
throwTwiceVisitingError(element)
} else if (element !is FirWrappedDelegateExpression) {
element.acceptChildren(this)
} else {
element.delegateProvider.accept(this)
}
}
}
private class ConsistencyTransformer : FirTransformer<Unit>() {
@@ -151,10 +150,7 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
override fun <E : FirElement> transformElement(element: E, data: Unit): CompositeTransformResult<E> {
if (!result.add(element)) {
if (element !is FirTypeRef && element !is FirNoReceiverExpression && element !is FirEmptyContractDescription && !element.isExtensionFunctionAnnotation) {
val elementDump = StringBuilder().also { element.accept(FirRenderer(it)) }.toString()
throw AssertionError("FirElement ${element.javaClass} is visited twice: $elementDump")
}
throwTwiceVisitingError(element)
} else if (element !is FirWrappedDelegateExpressionImpl) {
element.transformChildren(this, Unit)
} else {
@@ -171,5 +167,16 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
}
private fun throwTwiceVisitingError(element: FirElement) {
if (element is FirTypeRef || element is FirNoReceiverExpression || element is FirTypeParameter ||
element is FirEmptyContractDescription || element.isExtensionFunctionAnnotation
) {
return
}
val elementDump = StringBuilder().also { element.accept(FirRenderer(it)) }.toString()
throw AssertionError("FirElement ${element.javaClass} is visited twice: $elementDump")
}
private val FirElement.isExtensionFunctionAnnotation: Boolean
get() = (this as? FirAnnotationCall)?.isExtensionFunctionAnnotationCall == true
@@ -1,11 +1,11 @@
FILE: complexTypes.kt
public final class C<T, out S> : R|kotlin/Any| {
public constructor<T, S>(): R|a/b/C<T, S>| {
public constructor<T, out S>(): R|a/b/C<T, S>| {
super<R|kotlin/Any|>()
}
public final inner class D<R, in P> : R|kotlin/Any| {
public constructor<R, P>(): R|a/b/C.D<R, P>| {
public constructor<R, in P>(): R|a/b/C.D<R, P>| {
super<R|kotlin/Any|>()
}
@@ -8,7 +8,7 @@ FILE: typeParameters.kt
public final typealias StringList = R|List<out kotlin/String>|
public final typealias AnyList = R|List<*>|
public abstract class AbstractList<out T : R|kotlin/Any|> : R|List<T>| {
public constructor<T : R|kotlin/Any|>(): R|AbstractList<T>| {
public constructor<out T : R|kotlin/Any|>(): R|AbstractList<T>| {
super<R|kotlin/Any|>()
}
@@ -0,0 +1,16 @@
class A<T>(t: T) {
fun foo(x: T) {}
}
abstract class B<E>(e: E) {
val myE: E = id(e)
val a = A(e)
fun id(e: E): E = e
}
class C : B<String>("") {
fun bar() {
a.foo("")
}
}
@@ -0,0 +1,36 @@
FILE: genericConstructors.kt
public final class A<T> : R|kotlin/Any| {
public constructor<T>(t: R|T|): R|A<T>| {
super<R|kotlin/Any|>()
}
public final fun foo(x: R|T|): R|kotlin/Unit| {
}
}
public abstract class B<E> : R|kotlin/Any| {
public constructor<E>(e: R|E|): R|B<E>| {
super<R|kotlin/Any|>()
}
public final val myE: R|E| = this@R|/B|.R|FakeOverride</B.id: R|E|>|(R|<local>/e|)
public get(): R|E|
public final val a: R|A<E>| = R|/A.A|<R|E|>(R|<local>/e|)
public get(): R|A<E>|
public final fun id(e: R|E|): R|E| {
^id R|<local>/e|
}
}
public final class C : R|B<kotlin/String>| {
public constructor(): R|C| {
super<R|B<kotlin/String>|>(String())
}
public final fun bar(): R|kotlin/Unit| {
this@R|/B|.R|FakeOverride</B.a: R|A<kotlin/String>|>|.R|FakeOverride</A.foo: R|kotlin/Unit|>|(String())
}
}
@@ -1,6 +1,6 @@
FILE: supertypeGenericsComplex.kt
public final class Out<out T> : R|kotlin/Any| {
public constructor<T>(): R|Out<T>| {
public constructor<out T>(): R|Out<T>| {
super<R|kotlin/Any|>()
}
@@ -18,7 +18,7 @@ FILE: eagerResolveOfSingleCallableReference.kt
}
public final class Out<out T> : R|kotlin/Any| {
public constructor<T>(): R|Out<T>| {
public constructor<out T>(): R|Out<T>| {
super<R|kotlin/Any|>()
}
@@ -2,7 +2,7 @@ FILE: typeParameterVsNested.kt
public abstract interface Some : R|kotlin/Any| {
}
public abstract class My<T : R|test/Some|> : R|kotlin/Any| {
public constructor<T : R|test/My.Some|>(): R|test/My<T>| {
public constructor<T : R|test/Some|>(): R|test/My<T>| {
super<R|kotlin/Any|>()
}
@@ -113,6 +113,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/functionTypes.kt");
}
@TestMetadata("genericConstructors.kt")
public void testGenericConstructors() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/genericConstructors.kt");
}
@TestMetadata("genericFunctions.kt")
public void testGenericFunctions() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/genericFunctions.kt");