[FIR] Infer type arguments for captured parameters of inner classes
KT-38992
This commit is contained in:
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
interface AbstractFirTreeBuilder
|
||||
|
||||
class FirTreeBuilder : AbstractFirTreeBuilder
|
||||
|
||||
abstract class AbstractBuilderConfigurator<T : AbstractFirTreeBuilder> {
|
||||
abstract class BuilderConfigurationContext
|
||||
|
||||
inner class LeafBuilderConfigurationContext : BuilderConfigurationContext()
|
||||
}
|
||||
|
||||
class BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>() {
|
||||
fun test(func: (LeafBuilderConfigurationContext) -> Unit) {
|
||||
val context = LeafBuilderConfigurationContext()
|
||||
func(context)
|
||||
}
|
||||
}
|
||||
|
||||
class Outer<E> {
|
||||
inner class Inner
|
||||
|
||||
fun foo(x: (Inner) -> Unit, y: Inner.() -> Unit) {
|
||||
// each call reported as INAPPLICABLE because "Inner<E> is not a subtype of Inner"
|
||||
bar(Inner())
|
||||
x(Inner())
|
||||
Inner().y()
|
||||
}
|
||||
|
||||
fun bar(i: Inner) {}
|
||||
}
|
||||
Vendored
+62
@@ -0,0 +1,62 @@
|
||||
FILE: invokeWithReceiverAndArgument.kt
|
||||
public abstract interface AbstractFirTreeBuilder : R|kotlin/Any| {
|
||||
}
|
||||
public final class FirTreeBuilder : R|AbstractFirTreeBuilder| {
|
||||
public constructor(): R|FirTreeBuilder| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public abstract class AbstractBuilderConfigurator<T : R|AbstractFirTreeBuilder|> : R|kotlin/Any| {
|
||||
public constructor<T : R|AbstractFirTreeBuilder|>(): R|AbstractBuilderConfigurator<T>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public abstract class BuilderConfigurationContext : R|kotlin/Any| {
|
||||
public constructor(): R|AbstractBuilderConfigurator.BuilderConfigurationContext| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final inner class LeafBuilderConfigurationContext<T : R|AbstractFirTreeBuilder|> : R|AbstractBuilderConfigurator.BuilderConfigurationContext| {
|
||||
public constructor(): R|AbstractBuilderConfigurator.LeafBuilderConfigurationContext<T>| {
|
||||
super<R|AbstractBuilderConfigurator.BuilderConfigurationContext|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final class BuilderConfigurator : R|AbstractBuilderConfigurator<FirTreeBuilder>| {
|
||||
public constructor(): R|BuilderConfigurator| {
|
||||
super<R|AbstractBuilderConfigurator<FirTreeBuilder>|>()
|
||||
}
|
||||
|
||||
public final fun test(func: R|(AbstractBuilderConfigurator.LeafBuilderConfigurationContext<FirTreeBuilder>) -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
lval context: R|AbstractBuilderConfigurator.LeafBuilderConfigurationContext<FirTreeBuilder>| = this@R|/BuilderConfigurator|.R|/AbstractBuilderConfigurator.LeafBuilderConfigurationContext.LeafBuilderConfigurationContext|()
|
||||
R|<local>/func|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/context|)
|
||||
}
|
||||
|
||||
}
|
||||
public final class Outer<E> : R|kotlin/Any| {
|
||||
public constructor<E>(): R|Outer<E>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final inner class Inner<E> : R|kotlin/Any| {
|
||||
public constructor(): R|Outer.Inner<E>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final fun foo(x: R|(Outer.Inner<E>) -> kotlin/Unit|, y: R|Outer.Inner<E>.() -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
this@R|/Outer|.R|/Outer.bar|(this@R|/Outer|.R|/Outer.Inner.Inner|())
|
||||
R|<local>/x|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(this@R|/Outer|.R|/Outer.Inner.Inner|())
|
||||
R|<local>/y|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(this@R|/Outer|.R|/Outer.Inner.Inner|())
|
||||
}
|
||||
|
||||
public final fun bar(i: R|Outer.Inner<E>|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
+10
-10
@@ -23,11 +23,11 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt
|
||||
}
|
||||
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
this@R|/Test|.super<R|IBase|>.R|/IBase.foo|()
|
||||
this@R|/Test|.super<R|IBase|>.R|/IBase.bar|()
|
||||
this@R|/Test|.super<R|IDerived|>.R|/IDerived.foo|()
|
||||
this@R|/Test|.super<R|IDerived|>.R|/IBase.bar|()
|
||||
this@R|/Test|.super<R|IDerived|>.R|/IDerived.qux|()
|
||||
this@R|/Test|.super<R|IBase<T>|>.R|/IBase.foo|()
|
||||
this@R|/Test|.super<R|IBase<T>|>.R|/IBase.bar|()
|
||||
this@R|/Test|.super<R|IDerived<T>|>.R|/IDerived.foo|()
|
||||
this@R|/Test|.super<R|IDerived<T>|>.R|/IBase.bar|()
|
||||
this@R|/Test|.super<R|IDerived<T>|>.R|/IDerived.qux|()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,13 +37,13 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt
|
||||
}
|
||||
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
this@R|/Test2|.super<R|IBase|>.R|/IBase.foo|()
|
||||
this@R|/Test2|.super<R|IBase|>.R|/IBase.bar|()
|
||||
this@R|/Test2|.super<R|IBase<T>|>.R|/IBase.foo|()
|
||||
this@R|/Test2|.super<R|IBase<T>|>.R|/IBase.bar|()
|
||||
this@R|/Test2|.super<R|AliasedIBase|>.R|/IBase.foo|()
|
||||
this@R|/Test2|.super<R|AliasedIBase|>.R|/IBase.bar|()
|
||||
this@R|/Test2|.super<R|IDerived|>.R|/IDerived.foo|()
|
||||
this@R|/Test2|.super<R|IDerived|>.R|/IBase.bar|()
|
||||
this@R|/Test2|.super<R|IDerived|>.R|/IDerived.qux|()
|
||||
this@R|/Test2|.super<R|IDerived<T>|>.R|/IDerived.foo|()
|
||||
this@R|/Test2|.super<R|IDerived<T>|>.R|/IBase.bar|()
|
||||
this@R|/Test2|.super<R|IDerived<T>|>.R|/IDerived.qux|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,20 +13,20 @@ FILE: typeParameterVsNested.kt
|
||||
|
||||
}
|
||||
|
||||
public abstract val x: R|test/My.T|
|
||||
public get(): R|test/My.T|
|
||||
public abstract val x: R|test/My.T<T>|
|
||||
public get(): R|test/My.T<T>|
|
||||
|
||||
public abstract fun foo(arg: R|test/My.T|): R|kotlin/Unit|
|
||||
public abstract fun foo(arg: R|test/My.T<T>|): R|kotlin/Unit|
|
||||
|
||||
public abstract val y: R|test/My.T|
|
||||
public get(): R|test/My.T|
|
||||
public abstract val y: R|test/My.T<ERROR CLASS: Type argument not defined>|
|
||||
public get(): R|test/My.T<ERROR CLASS: Type argument not defined>|
|
||||
|
||||
public abstract val z: R|test/My.T|
|
||||
public get(): R|test/My.T|
|
||||
public abstract val z: R|test/My.T<ERROR CLASS: Type argument not defined>|
|
||||
public get(): R|test/My.T<ERROR CLASS: Type argument not defined>|
|
||||
|
||||
public final class Some : R|test/My.T| {
|
||||
public final class Some : R|test/My.T<T>| {
|
||||
public constructor(): R|test/My.Some| {
|
||||
super<R|test/My.T|>()
|
||||
super<R|test/My.T<T>|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class A<T1, T2> {
|
||||
inner class B<K1, K2> {
|
||||
inner class C<U1, U2>
|
||||
|
||||
fun <R3> foo(c: C<R3, R3>) {}
|
||||
}
|
||||
|
||||
fun <R2, R3> foo(c: B<R2, R2>.C<R3, R3>) {}
|
||||
}
|
||||
|
||||
fun <R1, R2, R3> foo(c: A<R1, R1>.B<R2, R2>.C<R3, R3>) {}
|
||||
|
||||
fun <R3> foo(c: A.B.C<R3, R3>) {}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
FILE: capturedParametersOfInnerClasses.kt
|
||||
public final class A<T1, T2> : R|kotlin/Any| {
|
||||
public constructor<T1, T2>(): R|A<T1, T2>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final inner class B<K1, K2, T1, T2> : R|kotlin/Any| {
|
||||
public constructor<K1, K2>(): R|A.B<K1, K2, T1, T2>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final inner class C<U1, U2, K1, K2, T1, T2> : R|kotlin/Any| {
|
||||
public constructor<U1, U2>(): R|A.B.C<U1, U2, K1, K2, T1, T2>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final fun <R3> foo(c: R|A.B.C<R3, R3, K1, K2, T1, T2>|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final fun <R2, R3> foo(c: R|A.B.C<R3, R3, R2, R2, T1, T2>|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
public final fun <R1, R2, R3> foo(c: R|A.B.C<R3, R3, R2, R2, R1, R1>|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun <R3> foo(c: R|A.B.C<R3, R3, ERROR CLASS: Type argument not defined, ERROR CLASS: Type argument not defined, ERROR CLASS: Type argument not defined, ERROR CLASS: Type argument not defined>|): R|kotlin/Unit| {
|
||||
}
|
||||
Generated
+10
@@ -644,6 +644,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/invokeAmbiguity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeWithReceiverAndArgument.kt")
|
||||
public void testInvokeWithReceiverAndArgument() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/invokeWithReceiverAndArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("objectInvoke.kt")
|
||||
public void testObjectInvoke() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/objectInvoke.kt");
|
||||
@@ -2352,6 +2357,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
public void testBareWithSubjectTypeAlias() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/types/bareWithSubjectTypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("capturedParametersOfInnerClasses.kt")
|
||||
public void testCapturedParametersOfInnerClasses() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/types/capturedParametersOfInnerClasses.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
||||
|
||||
+10
@@ -644,6 +644,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/invokeAmbiguity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeWithReceiverAndArgument.kt")
|
||||
public void testInvokeWithReceiverAndArgument() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/invokeWithReceiverAndArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("objectInvoke.kt")
|
||||
public void testObjectInvoke() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/objectInvoke.kt");
|
||||
@@ -2352,6 +2357,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
public void testBareWithSubjectTypeAlias() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/types/bareWithSubjectTypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("capturedParametersOfInnerClasses.kt")
|
||||
public void testCapturedParametersOfInnerClasses() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/types/capturedParametersOfInnerClasses.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/visibility")
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
package org.jetbrains.kotlin.fir.resolve
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
|
||||
|
||||
interface FirTypeResolver : FirSessionComponent {
|
||||
fun resolveType(typeRef: FirTypeRef, scope: FirScope): ConeKotlinType
|
||||
fun resolveToSymbol(typeRef: FirTypeRef, scope: FirScope): FirClassifierSymbol<*>?
|
||||
fun resolveType(typeRef: FirTypeRef, scope: FirScope, areBareTypesAllowed: Boolean): ConeKotlinType
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.bindSymbolToLookupTag
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getSymbolByTypeRef
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
|
||||
@@ -191,21 +192,7 @@ fun FirClassifierSymbol<*>.constructType(
|
||||
fun FirClassifierSymbol<*>.constructType(parts: List<FirQualifierPart>, isNullable: Boolean): ConeKotlinType =
|
||||
constructType(parts.toTypeProjections(), isNullable)
|
||||
|
||||
fun FirClassifierSymbol<*>.constructType(
|
||||
parts: List<FirQualifierPart>,
|
||||
isNullable: Boolean,
|
||||
symbolOriginSession: FirSession,
|
||||
attributes: ConeAttributes = ConeAttributes.Empty
|
||||
): ConeKotlinType =
|
||||
constructType(parts.toTypeProjections(), isNullable, attributes)
|
||||
.also {
|
||||
val lookupTag = it.lookupTag
|
||||
if (lookupTag is ConeClassLikeLookupTagImpl && this is FirClassLikeSymbol<*>) {
|
||||
lookupTag.bindSymbolToLookupTag(symbolOriginSession.firSymbolProvider, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
|
||||
fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
|
||||
asReversed().flatMap { it.typeArguments.map { typeArgument -> typeArgument.toConeTypeProjection() } }.toTypedArray()
|
||||
|
||||
fun FirFunction<*>.constructFunctionalTypeRef(isSuspend: Boolean = false): FirResolvedTypeRef {
|
||||
|
||||
+58
-21
@@ -8,17 +8,15 @@ package org.jetbrains.kotlin.fir.resolve.providers.impl
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.constructType
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.qualifierResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.bindSymbolToLookupTag
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
@@ -40,18 +38,22 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveToSymbol(
|
||||
private fun resolveToSymbol(
|
||||
typeRef: FirTypeRef,
|
||||
scope: FirScope
|
||||
): FirClassifierSymbol<*>? {
|
||||
): Pair<FirClassifierSymbol<*>?, ConeSubstitutor?> {
|
||||
return when (typeRef) {
|
||||
is FirResolvedTypeRef -> typeRef.coneTypeSafe<ConeLookupTagBasedType>()?.lookupTag?.let(symbolProvider::getSymbolByLookupTag)
|
||||
is FirResolvedTypeRef -> {
|
||||
val resultSymbol = typeRef.coneTypeSafe<ConeLookupTagBasedType>()?.lookupTag?.let(symbolProvider::getSymbolByLookupTag)
|
||||
resultSymbol to null
|
||||
}
|
||||
|
||||
is FirUserTypeRef -> {
|
||||
val qualifierResolver = session.qualifierResolver
|
||||
var resolvedSymbol: FirClassifierSymbol<*>? = null
|
||||
scope.processClassifiersByName(typeRef.qualifier.first().name) { symbol ->
|
||||
if (resolvedSymbol != null) return@processClassifiersByName
|
||||
var substitutor: ConeSubstitutor? = null
|
||||
scope.processClassifiersByNameWithSubstitution(typeRef.qualifier.first().name) { symbol, substitutorFromScope ->
|
||||
if (resolvedSymbol != null) return@processClassifiersByNameWithSubstitution
|
||||
resolvedSymbol = when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> {
|
||||
if (typeRef.qualifier.size == 1) {
|
||||
@@ -66,25 +68,56 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
|
||||
}
|
||||
else -> error("!")
|
||||
}
|
||||
substitutor = substitutorFromScope
|
||||
}
|
||||
|
||||
// TODO: Imports
|
||||
resolvedSymbol ?: qualifierResolver.resolveSymbol(typeRef.qualifier)
|
||||
val resultSymbol: FirClassifierSymbol<*>? = resolvedSymbol ?: qualifierResolver.resolveSymbol(typeRef.qualifier)
|
||||
resultSymbol to substitutor
|
||||
}
|
||||
|
||||
is FirImplicitBuiltinTypeRef -> {
|
||||
resolveBuiltInQualified(typeRef.id, session)
|
||||
resolveBuiltInQualified(typeRef.id, session) to null
|
||||
}
|
||||
|
||||
else -> null
|
||||
else -> null to null
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveUserType(typeRef: FirUserTypeRef, symbol: FirClassifierSymbol<*>?): ConeKotlinType {
|
||||
private fun resolveUserType(
|
||||
typeRef: FirUserTypeRef,
|
||||
symbol: FirClassifierSymbol<*>?,
|
||||
substitutor: ConeSubstitutor?,
|
||||
areBareTypesAllowed: Boolean
|
||||
): ConeKotlinType {
|
||||
if (symbol == null) {
|
||||
return ConeKotlinErrorType("Symbol not found, for `${typeRef.render()}`")
|
||||
}
|
||||
return symbol.constructType(typeRef.qualifier, typeRef.isMarkedNullable, symbolOriginSession = session, typeRef.annotations.computeTypeAttributes())
|
||||
var typeArguments = typeRef.qualifier.toTypeProjections()
|
||||
if (symbol is FirRegularClassSymbol) {
|
||||
val isPossibleBareType = areBareTypesAllowed && typeArguments.isEmpty()
|
||||
if (typeArguments.size != symbol.fir.typeParameters.size && !isPossibleBareType) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val substitutor = substitutor ?: ConeSubstitutor.Empty
|
||||
val n = symbol.fir.typeParameters.size - typeArguments.size
|
||||
if (n < 0) {
|
||||
typeArguments = (1..symbol.fir.typeParameters.size).map { ConeClassErrorType("Type arguments number mismatch") }.toTypedArray()
|
||||
} else {
|
||||
val argumentsFromOuterClassesAndParents = symbol.fir.typeParameters.takeLast(n).map {
|
||||
val type = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(it.symbol), isNullable = false)
|
||||
substitutor.substituteOrNull(type) ?: ConeClassErrorType("Type argument not defined")
|
||||
}.toTypedArray<ConeTypeProjection>()
|
||||
typeArguments += argumentsFromOuterClassesAndParents
|
||||
}
|
||||
}
|
||||
}
|
||||
return symbol.constructType(typeArguments, typeRef.isMarkedNullable, typeRef.annotations.computeTypeAttributes())
|
||||
.also {
|
||||
val lookupTag = it.lookupTag
|
||||
if (lookupTag is ConeClassLikeLookupTagImpl && symbol is FirClassLikeSymbol<*>) {
|
||||
lookupTag.bindSymbolToLookupTag(session.firSymbolProvider, symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFunctionalType(typeRef: FirFunctionTypeRef): ConeClassLikeType {
|
||||
@@ -108,13 +141,17 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
|
||||
|
||||
override fun resolveType(
|
||||
typeRef: FirTypeRef,
|
||||
scope: FirScope
|
||||
scope: FirScope,
|
||||
areBareTypesAllowed: Boolean
|
||||
): ConeKotlinType {
|
||||
return when (typeRef) {
|
||||
is FirResolvedTypeRef -> typeRef.type
|
||||
is FirUserTypeRef -> resolveUserType(typeRef, resolveToSymbol(typeRef, scope))
|
||||
is FirUserTypeRef -> {
|
||||
val (symbol, substitutor) = resolveToSymbol(typeRef, scope)
|
||||
resolveUserType(typeRef, symbol, substitutor, areBareTypesAllowed)
|
||||
}
|
||||
is FirFunctionTypeRef -> createFunctionalType(typeRef)
|
||||
is FirDelegatedTypeRef -> resolveType(typeRef.typeRef, scope)
|
||||
is FirDelegatedTypeRef -> resolveType(typeRef.typeRef, scope, areBareTypesAllowed)
|
||||
is FirDynamicTypeRef -> ConeKotlinErrorType("Not supported: ${typeRef::class.simpleName}")
|
||||
else -> error("!")
|
||||
}
|
||||
|
||||
+31
-2
@@ -10,13 +10,24 @@ import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getNestedClassifierScope
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirNestedClassifierScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class FirAbstractTreeTransformerWithSuperTypes(
|
||||
phase: FirResolvePhase
|
||||
@@ -43,8 +54,16 @@ abstract class FirAbstractTreeTransformerWithSuperTypes(
|
||||
// ? Is it Ok to use original file session here ?
|
||||
val superTypes = lookupSuperTypes(firClass, lookupInterfaces = false, deep = true, useSiteSession = session).asReversed()
|
||||
for (superType in superTypes) {
|
||||
session.getNestedClassifierScope(superType.lookupTag)?.let {
|
||||
scopes.add(it)
|
||||
session.getNestedClassifierScope(superType.lookupTag)?.let { nestedClassifierScope ->
|
||||
val klass = superType.lookupTag.toSymbol(session)?.fir as? FirRegularClass
|
||||
val mapping = klass?.typeParameters?.map { it.symbol }?.zip(superType.typeArguments.map { it as ConeKotlinType })?.toMap()
|
||||
val substitutor = mapping?.let { ConeSubstitutorByMap(it) } ?: ConeSubstitutor.Empty
|
||||
val scope = if (nestedClassifierScope is FirNestedClassifierScope) {
|
||||
FirNestedClassifierScopeWithSubstitution(nestedClassifierScope, substitutor)
|
||||
} else {
|
||||
nestedClassifierScope
|
||||
}
|
||||
scopes.add(scope)
|
||||
}
|
||||
}
|
||||
if (firClass is FirRegularClass) {
|
||||
@@ -67,3 +86,13 @@ abstract class FirAbstractTreeTransformerWithSuperTypes(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FirNestedClassifierScopeWithSubstitution(
|
||||
private val scope: FirNestedClassifierScope,
|
||||
private val substitutor: ConeSubstitutor
|
||||
) : FirScope() {
|
||||
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
||||
val matchedClass = scope.getClassifierByName(name) ?: return
|
||||
processor(matchedClass, substitutor)
|
||||
}
|
||||
}
|
||||
+17
-2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.typeResolver
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
@@ -21,16 +22,30 @@ class FirSpecificTypeResolverTransformer(
|
||||
) : FirAbstractTreeTransformer<FirScope>(phase = FirResolvePhase.SUPER_TYPES) {
|
||||
private val typeResolver = session.typeResolver
|
||||
|
||||
@set:PrivateForInline
|
||||
var areBareTypesAllowed: Boolean = false
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <R> withAllowedBareTypes(block: () -> R): R {
|
||||
val oldValue = areBareTypesAllowed
|
||||
areBareTypesAllowed = true
|
||||
return try {
|
||||
block()
|
||||
} finally {
|
||||
areBareTypesAllowed = oldValue
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformTypeRef(typeRef: FirTypeRef, data: FirScope): CompositeTransformResult<FirTypeRef> {
|
||||
typeRef.transformChildren(this, data)
|
||||
return transformType(typeRef, typeResolver.resolveType(typeRef, data))
|
||||
return transformType(typeRef, typeResolver.resolveType(typeRef, data, areBareTypesAllowed))
|
||||
}
|
||||
|
||||
override fun transformFunctionTypeRef(functionTypeRef: FirFunctionTypeRef, data: FirScope): CompositeTransformResult<FirTypeRef> {
|
||||
functionTypeRef.transformChildren(this, data)
|
||||
return buildResolvedFunctionTypeRef {
|
||||
source = functionTypeRef.source
|
||||
type = typeResolver.resolveType(functionTypeRef, data).takeIfAcceptable() ?: return functionTypeRef.compose()
|
||||
type = typeResolver.resolveType(functionTypeRef, data, areBareTypesAllowed).takeIfAcceptable() ?: return functionTypeRef.compose()
|
||||
isMarkedNullable = functionTypeRef.isMarkedNullable
|
||||
isSuspend = functionTypeRef.isSuspend
|
||||
receiverTypeRef = functionTypeRef.receiverTypeRef
|
||||
|
||||
+3
-1
@@ -432,7 +432,9 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
typeOperatorCall: FirTypeOperatorCall,
|
||||
data: ResolutionMode,
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
val resolved = transformExpression(typeOperatorCall, ResolutionMode.ContextIndependent).single as FirTypeOperatorCall
|
||||
val resolved = components.typeResolverTransformer.withAllowedBareTypes {
|
||||
typeOperatorCall.transformConversionTypeRef(transformer, ResolutionMode.ContextIndependent)
|
||||
}.transformOtherChildren(transformer, ResolutionMode.ContextIndependent)
|
||||
resolved.argumentList.transformArguments(integerLiteralTypeApproximator, null)
|
||||
val conversionTypeRef = resolved.conversionTypeRef.withTypeArgumentsForBareType(resolved.argument)
|
||||
resolved.transformChildren(object : FirDefaultTransformer<Nothing?>() {
|
||||
|
||||
+13
-1
@@ -7,10 +7,15 @@ package org.jetbrains.kotlin.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FirNestedClassifierScope(val klass: FirClass<*>) : FirScope() {
|
||||
@@ -31,6 +36,13 @@ class FirNestedClassifierScope(val klass: FirClass<*>) : FirScope() {
|
||||
processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit
|
||||
) {
|
||||
val matchedClass = classIndex[name] ?: return
|
||||
processor(matchedClass, ConeSubstitutor.Empty)
|
||||
val substitution = klass.typeParameters.associate {
|
||||
it.symbol to it.toConeType()
|
||||
}
|
||||
processor(matchedClass, ConeSubstitutorByMap(substitution))
|
||||
}
|
||||
|
||||
fun getClassifierByName(name: Name): FirRegularClassSymbol? = classIndex[name]
|
||||
}
|
||||
|
||||
fun FirTypeParameterRef.toConeType(): ConeKotlinType = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(symbol), isNullable = false)
|
||||
-2
@@ -1,5 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
fun <T> tableView(init: Table<T>.() -> Unit) {
|
||||
Table<T>().init()
|
||||
}
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// SKIP_JDK6
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// SKIP_JDK6
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// SKIP_JDK6
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
Vendored
+2
-2
@@ -19,8 +19,8 @@ class A : Outer<Double, Short>() {
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
Derived().foo() checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Outer<String, Int>.Inner<Char>>() }
|
||||
Derived().foo() checkType { _<Outer<String, Int>.Inner<Char>>() }
|
||||
Derived().baz() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Map<Char, String>>() }
|
||||
A.B().bar() checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Outer<Float, Long>.Inner<String>>() }
|
||||
A.B().bar() checkType { _<Outer<Float, Long>.Inner<String>>() }
|
||||
A.B().x() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Map<String, Float>>() }
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,6 +50,6 @@ fun test() {
|
||||
var y = noParameters()
|
||||
y = noParameters()
|
||||
|
||||
y().foo().a() checkType { <!INAPPLICABLE_CANDIDATE!>_<!><A<Any, Double, Short, Long>>() }
|
||||
y().foo().a() checkType { _<A<Any, Double, Short, Long>>() }
|
||||
y().bar() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><A<Any, Double, Short, Char>>() }
|
||||
}
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ class Outer<T> {
|
||||
var y = noParameters()
|
||||
y = noParameters()
|
||||
|
||||
y().foo().a() checkType { <!INAPPLICABLE_CANDIDATE!>_<!><A<T, F, Any, Double, Short, Long>>() }
|
||||
y().foo().a() checkType { _<A<T, F, Any, Double, Short, Long>>() }
|
||||
y().bar() <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><A<T, F, Any, Double, Short, Char>>() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class Outer<E> {
|
||||
fun set(inner: Inner<out E>) {}
|
||||
|
||||
fun inside() {
|
||||
innerFactory().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Inner<String>>() }
|
||||
innerFactory().checkType { _<Inner<String>>() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ fun main() {
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Outer<CharSequence>.Inner<CharSequence>>(outer.bar())
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Outer<CharSequence>.Inner<CharSequence>>(outer.Inner())
|
||||
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(outer.bar())
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(outer.Inner())
|
||||
outer.set(outer.bar())
|
||||
outer.set(outer.Inner())
|
||||
|
||||
val x: Outer<String>.Inner<String> = factoryString()
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(x)
|
||||
outer.set(x)
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ class Outer<T> {
|
||||
x.checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Inner>() }
|
||||
x.checkType { _<Outer<String>.Inner>() }
|
||||
z.checkType { _<Inner>() }
|
||||
z.checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Outer<T>.Inner>() }
|
||||
z.checkType { _<Outer<T>.Inner>() }
|
||||
|
||||
inner = x
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ fun main() {
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Outer<CharSequence>.Inner>(outer.bar())
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Outer<CharSequence>.Inner>(outer.Inner())
|
||||
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(outer.bar())
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(outer.Inner())
|
||||
outer.set(outer.bar())
|
||||
outer.set(outer.Inner())
|
||||
|
||||
val x: Outer<String>.Inner = factoryString()
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(x)
|
||||
outer.set(x)
|
||||
}
|
||||
@@ -28,13 +28,13 @@ fun main() {
|
||||
checkSubtype<Outer<String>.Inner>(outer.bar())
|
||||
checkSubtype<Outer<String>.Inner>(outer.Inner())
|
||||
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(outer.bar())
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(outer.Inner())
|
||||
outer.set(outer.bar())
|
||||
outer.set(outer.Inner())
|
||||
|
||||
val x: Outer<String>.Inner = factoryString()
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(x)
|
||||
val y: Outer<CharSequence>.Inner = infer<CharSequence>("")
|
||||
outer.<!INAPPLICABLE_CANDIDATE!>set<!>(y)
|
||||
outer.set(y)
|
||||
|
||||
outer.set(infer<Any>(""))
|
||||
}
|
||||
|
||||
+1
-1
@@ -44,6 +44,6 @@ fun foo() {
|
||||
|
||||
strInt.instance().Inner<Double>().checkType { _<Outer<String>.Inner<Double>>() }
|
||||
|
||||
Outer<String>().<!INAPPLICABLE_CANDIDATE!>setInner<!>(strInt)
|
||||
Outer<String>().setInner(strInt)
|
||||
Outer<CharSequence>().<!INAPPLICABLE_CANDIDATE!>setInner<!>(strInt)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user