[FIR] Add forgotten replacing arguments in abbreviated type expansion

This commit is contained in:
Dmitriy Novozhilov
2019-07-29 10:01:34 +03:00
parent 317e3edba8
commit 6e2958880b
10 changed files with 249 additions and 21 deletions
@@ -18,7 +18,17 @@ sealed class ConeKotlinTypeProjection : TypeArgumentMarker {
}
enum class ProjectionKind {
STAR, IN, OUT, INVARIANT
STAR, IN, OUT, INVARIANT;
operator fun plus(other: ProjectionKind): ProjectionKind {
return when {
this == other -> this
this == STAR || other == STAR -> STAR
this == INVARIANT -> other
other == INVARIANT -> this
else -> STAR
}
}
}
object ConeStarProjection : ConeKotlinTypeProjection() {
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.resultType
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.*
@@ -46,10 +47,41 @@ fun ConeClassLikeLookupTag.toSymbol(useSiteSession: FirSession): ConeClassifierS
return firSymbolProvider.getSymbolByLookupTag(this)
}
fun ConeAbbreviatedType.directExpansionType(useSiteSession: FirSession): ConeClassLikeType? =
abbreviationLookupTag
fun ConeAbbreviatedType.directExpansionType(useSiteSession: FirSession): ConeClassLikeType? {
val typeAlias = abbreviationLookupTag
.toSymbol(useSiteSession)
?.safeAs<FirTypeAliasSymbol>()?.fir?.expandedConeType
?.safeAs<FirTypeAliasSymbol>()?.fir ?: return null
val resultType = typeAlias.expandedConeType ?: return null
if (resultType.typeArguments.isEmpty()) return resultType
return mapTypeAliasArguments(typeAlias, this, resultType) as? ConeClassLikeType
}
private fun mapTypeAliasArguments(typeAlias: FirTypeAlias, abbreviatedType: ConeAbbreviatedType, resultingType: ConeClassLikeType): ConeKotlinType {
val typeAliasMap = typeAlias.typeParameters.map { it.symbol }.zip(abbreviatedType.typeArguments).toMap()
val substitutor = object : AbstractConeSubstitutor() {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
return null
}
override fun substituteArgument(projection: ConeKotlinTypeProjection): ConeKotlinTypeProjection? {
val type = (projection as? ConeTypedProjection)?.type ?: return null
val symbol = (type as? ConeTypeParameterType)?.lookupTag?.toSymbol() ?: return super.substituteArgument(projection)
val mappedProjection = typeAliasMap[symbol] ?: return super.substituteArgument(projection)
val mappedType = (mappedProjection as? ConeTypedProjection)?.type ?: return mappedProjection
val resultingKind = mappedProjection.kind + projection.kind
return when (resultingKind) {
ProjectionKind.STAR -> ConeStarProjection
ProjectionKind.IN -> ConeKotlinTypeProjectionIn(mappedType)
ProjectionKind.OUT -> ConeKotlinTypeProjectionOut(mappedType)
ProjectionKind.INVARIANT -> mappedType
}
}
}
return substitutor.substituteOrSelf(resultingType)
}
fun ConeClassifierLookupTag.toSymbol(useSiteSession: FirSession): ConeClassifierSymbol? =
when (this) {
@@ -137,7 +169,7 @@ fun <T : ConeKotlinType> T.withNullability(nullability: ConeNullability): T {
}
fun <T : ConeKotlinType> T.withArguments(arguments: Array<ConeKotlinTypeProjection>): T {
fun <T : ConeKotlinType> T.withArguments(arguments: Array<out ConeKotlinTypeProjection>): T {
if (this.typeArguments === arguments) {
return this
}
@@ -34,7 +34,7 @@ fun ConeSubstitutor.substituteOrNull(type: ConeKotlinType?): ConeKotlinType? {
}
abstract class AbstractConeSubstitutor : ConeSubstitutor() {
private fun wrapProjection(old: ConeKotlinTypeProjection, newType: ConeKotlinType): ConeKotlinTypeProjection {
protected fun wrapProjection(old: ConeKotlinTypeProjection, newType: ConeKotlinType): ConeKotlinTypeProjection {
return when (old) {
is ConeStarProjection -> old
is ConeKotlinTypeProjectionIn -> ConeKotlinTypeProjectionIn(newType)
@@ -45,6 +45,11 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() {
}
abstract fun substituteType(type: ConeKotlinType): ConeKotlinType?
open fun substituteArgument(projection: ConeKotlinTypeProjection): ConeKotlinTypeProjection? {
val type = (projection as? ConeTypedProjection)?.type ?: return null
val newType = substituteOrNull(type) ?: return null
return wrapProjection(projection, newType)
}
fun makeNullableIfNeed(isNullable: Boolean, type: ConeKotlinType?): ConeKotlinType? {
if (!isNullable) return type
@@ -93,11 +98,8 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() {
val newArguments by lazy { arrayOfNulls<ConeKotlinTypeProjection>(typeArguments.size) }
var initialized = false
for ((index, typeArgument) in this.typeArguments.withIndex()) {
val type = (typeArgument as? ConeTypedProjection)?.type ?: continue
val newType = substituteOrNull(type)
if (newType != null) {
newArguments[index] = substituteArgument(typeArgument)?.also {
initialized = true
newArguments[index] = wrapProjection(typeArgument, newType)
}
}
@@ -16,10 +16,10 @@ FILE: simpleDelegatedToMap.kt
}
}
public final var bar: <ERROR TYPE REF: Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>by R|kotlin/collections/hashMapOf|<R|kotlin/String|, R|kotlin/Any|>()
public get(): <ERROR TYPE REF: Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]> {
^ D|/bar|.<Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>#(Null(null), ::R|/bar|)
public final var bar: <ERROR TYPE REF: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>by R|kotlin/collections/hashMapOf|<R|kotlin/String|, R|kotlin/Any|>()
public get(): <ERROR TYPE REF: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]> {
^ D|/bar|.<Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>#(Null(null), ::R|/bar|)
}
public set(<set-?>: <ERROR TYPE REF: Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>): R|kotlin/Unit| {
D|/bar|.<Inapplicable(WRONG_RECEIVER): [kotlin/collections/setValue]>#(Null(null), ::R|/bar|, R|<local>/<set-?>|)
public set(<set-?>: <ERROR TYPE REF: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>): R|kotlin/Unit| {
D|/bar|.<Inapplicable(INAPPLICABLE): [kotlin/collections/setValue]>#(Null(null), ::R|/bar|, R|<local>/<set-?>|)
}
@@ -0,0 +1,94 @@
interface A {
fun foo()
}
interface B {
fun bar()
}
interface C {
fun baz()
}
interface Inv<K, T>() {
fun k(): K
fun t(): T
}
typealias Inv0 = Inv<A, B>
typealias Inv1<X> = Inv<A, X>
typealias Inv2<X, Y> = Inv<X, Y>
typealias Inv3<X, Y, Z> = Inv<X, Z>
fun testBase(inv: Inv<A, B>) {
inv.k()
inv.t()
}
fun test_0(inv: Inv0) {
inv.k().foo()
inv.t().bar()
}
fun test_1(inv: Inv1<B>) {
inv.k().foo()
inv.t().bar()
}
fun test_2(inv: Inv2<A, B>) {
inv.k().foo()
inv.t().bar()
}
fun test_3(inv: Inv3<A, B, C>) {
inv.k().foo()
inv.t().bar()
inv.t().baz()
}
typealias Inv02<A1, B1, C1> = Inv<Inv<A1, B1>, C1>
fun test_4(inv: Inv02<A, B, C>) {
inv.k().k().foo()
inv.k().t().bar()
inv.t().baz()
}
interface In<in T> {
fun take(x: T)
}
interface Out<out T> {
fun value(): T
}
interface Invariant<T> {
fun take(x: T)
fun value(): T
}
typealias In1<X> = In<X>
typealias Out1<X> = Out<X>
typealias Invariant1<X> = Invariant<X>
fun test_5(a: A, in1: In1<A>, in2: In1<in A>, in3: In1<out A>) {
in1.take(a)
in2.take(a)
in3.take(a)
}
fun test_6(a: A, out1: Out1<A>, out2: Out1<in A>, out3: Out1<out A>) {
out1.value().foo()
out2.value().foo()
out3.value().foo()
}
fun test_7(a: A, inv1: Invariant1<A>, inv2: Invariant1<in A>, inv3: Invariant1<out A>) {
inv1.value().foo()
inv2.value().foo()
inv3.value().foo()
inv1.take(a)
inv2.take(a)
inv3.take(a)
}
@@ -0,0 +1,85 @@
FILE: typeAliasWithTypeArguments.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Unit|
}
public abstract interface B : R|kotlin/Any| {
public abstract fun bar(): R|kotlin/Unit|
}
public abstract interface C : R|kotlin/Any| {
public abstract fun baz(): R|kotlin/Unit|
}
public abstract interface Inv<K, T> : R|kotlin/Any| {
public abstract fun k(): R|K|
public abstract fun t(): R|T|
}
public final typealias Inv0 = R|Inv<A, B>|
public final typealias Inv1<X> = R|Inv<A, X>|
public final typealias Inv2<X, Y> = R|Inv<X, Y>|
public final typealias Inv3<X, Y, Z> = R|Inv<X, Z>|
public final fun testBase(inv: R|Inv<A, B>|): R|kotlin/Unit| {
R|<local>/inv|.R|FakeOverride</Inv.k: R|A|>|()
R|<local>/inv|.R|FakeOverride</Inv.t: R|B|>|()
}
public final fun test_0(inv: R|Inv0|): R|kotlin/Unit| {
R|<local>/inv|.R|FakeOverride</Inv.k: R|A|>|().R|/A.foo|()
R|<local>/inv|.R|FakeOverride</Inv.t: R|B|>|().R|/B.bar|()
}
public final fun test_1(inv: R|Inv1<B>|): R|kotlin/Unit| {
R|<local>/inv|.R|FakeOverride</Inv.k: R|A|>|().R|/A.foo|()
R|<local>/inv|.R|FakeOverride</Inv.t: R|B|>|().R|/B.bar|()
}
public final fun test_2(inv: R|Inv2<A, B>|): R|kotlin/Unit| {
R|<local>/inv|.R|FakeOverride</Inv.k: R|A|>|().R|/A.foo|()
R|<local>/inv|.R|FakeOverride</Inv.t: R|B|>|().R|/B.bar|()
}
public final fun test_3(inv: R|Inv3<A, B, C>|): R|kotlin/Unit| {
R|<local>/inv|.R|FakeOverride</Inv.k: R|A|>|().R|/A.foo|()
R|<local>/inv|.R|FakeOverride</Inv.t: R|C|>|().<Unresolved name: bar>#()
R|<local>/inv|.R|FakeOverride</Inv.t: R|C|>|().R|/C.baz|()
}
public final typealias Inv02<A1, B1, C1> = R|Inv<Inv<A1, B1>, C1>|
public final fun test_4(inv: R|Inv02<A, B, C>|): R|kotlin/Unit| {
R|<local>/inv|.R|FakeOverride</Inv.k: R|Inv<A, B>|>|().R|FakeOverride</Inv.k: R|A|>|().R|/A.foo|()
R|<local>/inv|.R|FakeOverride</Inv.k: R|Inv<A, B>|>|().R|FakeOverride</Inv.t: R|B|>|().R|/B.bar|()
R|<local>/inv|.R|FakeOverride</Inv.t: R|C|>|().R|/C.baz|()
}
public abstract interface In<in T> : R|kotlin/Any| {
public abstract fun take(x: R|T|): R|kotlin/Unit|
}
public abstract interface Out<out T> : R|kotlin/Any| {
public abstract fun value(): R|T|
}
public abstract interface Invariant<T> : R|kotlin/Any| {
public abstract fun take(x: R|T|): R|kotlin/Unit|
public abstract fun value(): R|T|
}
public final typealias In1<X> = R|In<X>|
public final typealias Out1<X> = R|Out<X>|
public final typealias Invariant1<X> = R|Invariant<X>|
public final fun test_5(a: R|A|, in1: R|In1<A>|, in2: R|In1<in A>|, in3: R|In1<out A>|): R|kotlin/Unit| {
R|<local>/in1|.R|FakeOverride</In.take: R|kotlin/Unit|>|(R|<local>/a|)
R|<local>/in2|.R|FakeOverride</In.take: R|kotlin/Unit|>|(R|<local>/a|)
R|<local>/in3|.R|FakeOverride</In.take: R|kotlin/Unit|>|(R|<local>/a|)
}
public final fun test_6(a: R|A|, out1: R|Out1<A>|, out2: R|Out1<in A>|, out3: R|Out1<out A>|): R|kotlin/Unit| {
R|<local>/out1|.R|FakeOverride</Out.value: R|A|>|().R|/A.foo|()
R|<local>/out2|.R|FakeOverride</Out.value: R|A|>|().R|/A.foo|()
R|<local>/out3|.R|FakeOverride</Out.value: R|A|>|().R|/A.foo|()
}
public final fun test_7(a: R|A|, inv1: R|Invariant1<A>|, inv2: R|Invariant1<in A>|, inv3: R|Invariant1<out A>|): R|kotlin/Unit| {
R|<local>/inv1|.R|FakeOverride</Invariant.value: R|A|>|().R|/A.foo|()
R|<local>/inv2|.R|FakeOverride</Invariant.value: R|A|>|().R|/A.foo|()
R|<local>/inv3|.R|FakeOverride</Invariant.value: R|A|>|().R|/A.foo|()
R|<local>/inv1|.R|FakeOverride</Invariant.take: R|kotlin/Unit|>|(R|<local>/a|)
R|<local>/inv2|.R|FakeOverride</Invariant.take: R|kotlin/Unit|>|(R|<local>/a|)
R|<local>/inv3|.R|FakeOverride</Invariant.take: R|kotlin/Unit|>|(R|<local>/a|)
}
@@ -144,6 +144,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/typeAliasWithGeneric.kt");
}
@TestMetadata("typeAliasWithTypeArguments.kt")
public void testTypeAliasWithTypeArguments() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/typeAliasWithTypeArguments.kt");
}
@TestMetadata("typeFromGetter.kt")
public void testTypeFromGetter() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/typeFromGetter.kt");
@@ -109,7 +109,7 @@ FILE fqName:<root> fileName:/classLevelProperties.kt
$this: VALUE_PARAMETER name:<this> type:<root>.C
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test8> (): IrErrorType declared in <root>.C'
ERROR_CALL 'Unresolved reference: <Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: this#' type=<root>.C
PROPERTY_REFERENCE 'public final test8: IrErrorType [delegated,var]' field='FIELD DELEGATE name:test8$delegate type:java.util.HashMap<kotlin.String, kotlin.Int> visibility:private [final]' getter=null setter=null type=kotlin.reflect.KProperty<*> origin=null
FUN DELEGATED_PROPERTY_ACCESSOR name:<set-test8> visibility:public modality:FINAL <> ($this:<root>.C, <set-?>:IrErrorType) returnType:kotlin.Unit
@@ -117,7 +117,7 @@ FILE fqName:<root> fileName:/classLevelProperties.kt
$this: VALUE_PARAMETER name:<this> type:<root>.C
VALUE_PARAMETER name:<set-?> index:0 type:IrErrorType
BLOCK_BODY
ERROR_CALL 'Unresolved reference: <Inapplicable(WRONG_RECEIVER): [kotlin/collections/setValue]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [kotlin/collections/setValue]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: this#' type=<root>.C
PROPERTY_REFERENCE 'public final test8: IrErrorType [delegated,var]' field='FIELD DELEGATE name:test8$delegate type:java.util.HashMap<kotlin.String, kotlin.Int> visibility:private [final]' getter='public final fun <get-test8> (): IrErrorType declared in <root>.C' setter=null type=kotlin.reflect.KProperty<*> origin=null
GET_VAR '<set-?>: IrErrorType declared in <root>.C.<set-test8>' type=IrErrorType origin=null
@@ -93,14 +93,14 @@ FILE fqName:<root> fileName:/delegatedProperties.kt
correspondingProperty: PROPERTY name:test4 visibility:public modality:FINAL [delegated,var]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test4> (): IrErrorType declared in <root>'
ERROR_CALL 'Unresolved reference: <Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>#' type=IrErrorType
CONST Null type=kotlin.Nothing? value=null
PROPERTY_REFERENCE 'public final test4: IrErrorType [delegated,var]' field='FIELD DELEGATE name:test4$delegate type:java.util.HashMap<kotlin.String, kotlin.Any> visibility:private [final,static]' getter=null setter=null type=kotlin.reflect.KProperty<*> origin=null
FUN DELEGATED_PROPERTY_ACCESSOR name:<set-test4> visibility:public modality:FINAL <> (<set-?>:IrErrorType) returnType:kotlin.Unit
correspondingProperty: PROPERTY name:test4 visibility:public modality:FINAL [delegated,var]
VALUE_PARAMETER name:<set-?> index:0 type:IrErrorType
BLOCK_BODY
ERROR_CALL 'Unresolved reference: <Inapplicable(WRONG_RECEIVER): [kotlin/collections/setValue]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [kotlin/collections/setValue]>#' type=IrErrorType
CONST Null type=kotlin.Nothing? value=null
PROPERTY_REFERENCE 'public final test4: IrErrorType [delegated,var]' field='FIELD DELEGATE name:test4$delegate type:java.util.HashMap<kotlin.String, kotlin.Any> visibility:private [final,static]' getter='public final fun <get-test4> (): IrErrorType declared in <root>' setter=null type=kotlin.reflect.KProperty<*> origin=null
GET_VAR '<set-?>: IrErrorType declared in <root>.<set-test4>' type=IrErrorType origin=null
@@ -86,14 +86,14 @@ FILE fqName:<root> fileName:/packageLevelProperties.kt
correspondingProperty: PROPERTY name:test8 visibility:public modality:FINAL [delegated,var]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test8> (): IrErrorType declared in <root>'
ERROR_CALL 'Unresolved reference: <Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>#' type=IrErrorType
CONST Null type=kotlin.Nothing? value=null
PROPERTY_REFERENCE 'public final test8: IrErrorType [delegated,var]' field='FIELD DELEGATE name:test8$delegate type:java.util.HashMap<kotlin.String, kotlin.Int> visibility:private [final,static]' getter=null setter=null type=kotlin.reflect.KProperty<*> origin=null
FUN DELEGATED_PROPERTY_ACCESSOR name:<set-test8> visibility:public modality:FINAL <> (<set-?>:IrErrorType) returnType:kotlin.Unit
correspondingProperty: PROPERTY name:test8 visibility:public modality:FINAL [delegated,var]
VALUE_PARAMETER name:<set-?> index:0 type:IrErrorType
BLOCK_BODY
ERROR_CALL 'Unresolved reference: <Inapplicable(WRONG_RECEIVER): [kotlin/collections/setValue]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [kotlin/collections/setValue]>#' type=IrErrorType
CONST Null type=kotlin.Nothing? value=null
PROPERTY_REFERENCE 'public final test8: IrErrorType [delegated,var]' field='FIELD DELEGATE name:test8$delegate type:java.util.HashMap<kotlin.String, kotlin.Int> visibility:private [final,static]' getter='public final fun <get-test8> (): IrErrorType declared in <root>' setter=null type=kotlin.reflect.KProperty<*> origin=null
GET_VAR '<set-?>: IrErrorType declared in <root>.<set-test8>' type=IrErrorType origin=null