Hack: do not add trivial constraints (t <: Any?) for constituent types,
otherwise nested calls handling logic in old inference wouldn't work for type alias constructors.
This commit is contained in:
+7
-1
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls
|
package org.jetbrains.kotlin.resolve.calls
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
@@ -136,8 +137,13 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
|||||||
) {
|
) {
|
||||||
val substitutedType = substitutedArgument.type
|
val substitutedType = substitutedArgument.type
|
||||||
for (upperBound in typeParameter.upperBounds) {
|
for (upperBound in typeParameter.upperBounds) {
|
||||||
val substitutedUpperBound = boundsSubstitutor.safeSubstitute(upperBound, Variance.INVARIANT)
|
val substitutedUpperBound = boundsSubstitutor.safeSubstitute(upperBound, Variance.INVARIANT).upperIfFlexible()
|
||||||
val constraintPosition = ValidityConstraintForConstituentType(substitutedType, typeParameter, substitutedUpperBound)
|
val constraintPosition = ValidityConstraintForConstituentType(substitutedType, typeParameter, substitutedUpperBound)
|
||||||
|
|
||||||
|
// Do not add extra constraints if upper bound is 'Any?';
|
||||||
|
// otherwise it will be treated incorrectly in nested calls processing.
|
||||||
|
if (KotlinBuiltIns.isNullableAny(substitutedUpperBound)) continue
|
||||||
|
|
||||||
builder.addSubtypeConstraint(substitutedType, substitutedUpperBound, constraintPosition)
|
builder.addSubtypeConstraint(substitutedType, substitutedUpperBound, constraintPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
interface Ref<T> {
|
||||||
|
var x: T
|
||||||
|
}
|
||||||
|
|
||||||
|
class LateInitNumRef<NN: Number>() : Ref<NN> {
|
||||||
|
constructor(x: NN) : this() { this.x = x }
|
||||||
|
|
||||||
|
private var xx: NN? = null
|
||||||
|
|
||||||
|
override var x: NN
|
||||||
|
get() = xx!!
|
||||||
|
set(value) {
|
||||||
|
xx = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias LateNR<Nt> = LateInitNumRef<Nt>
|
||||||
|
|
||||||
|
fun <V, R : Ref<in V>> update(r: R, v: V): R {
|
||||||
|
r.x = v
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
val r1 = update(LateInitNumRef(), 1)
|
||||||
|
val r1a = update(LateNR(), 1)
|
||||||
|
val r2 = update(LateInitNumRef(1), 1)
|
||||||
|
val r2a = update(LateNR(1), 1)
|
||||||
|
val r3 = LateInitNumRef(1)
|
||||||
|
val r3a = LateNR(1)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
r1.x = <!TYPE_MISMATCH!>r1.x<!>
|
||||||
|
r1a.x = <!TYPE_MISMATCH!>r1a.x<!>
|
||||||
|
r2.x = r2.x
|
||||||
|
r2a.x = r2a.x
|
||||||
|
r3.x = r3.x
|
||||||
|
r3a.x = r3a.x
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val r1: Ref<in kotlin.Int>
|
||||||
|
public val r1a: Ref<in kotlin.Int>
|
||||||
|
public val r2: LateInitNumRef<kotlin.Int>
|
||||||
|
public val r2a: LateInitNumRef<kotlin.Int>
|
||||||
|
public val r3: LateInitNumRef<kotlin.Int>
|
||||||
|
public val r3a: LateInitNumRef<kotlin.Int>
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
|
public fun </*0*/ V, /*1*/ R : Ref<in V>> update(/*0*/ r: R, /*1*/ v: V): R
|
||||||
|
|
||||||
|
public final class LateInitNumRef</*0*/ NN : kotlin.Number> : Ref<NN> {
|
||||||
|
public constructor LateInitNumRef</*0*/ NN : kotlin.Number>()
|
||||||
|
public constructor LateInitNumRef</*0*/ NN : kotlin.Number>(/*0*/ x: NN)
|
||||||
|
public open override /*1*/ var x: NN
|
||||||
|
private final var xx: NN?
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Ref</*0*/ T> {
|
||||||
|
public abstract var x: T
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
public typealias LateNR</*0*/ Nt> = LateInitNumRef<Nt>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import kotlin.test.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
typealias HM<Kt, Vt> = HashMap<Kt, Vt>
|
||||||
|
|
||||||
|
fun <K, V, M : MutableMap<in K, MutableList<V>>> updateMap(map: M, k: K, v: V): M {
|
||||||
|
map[k]!!.add(v)
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
|
val nameToTeam = listOf("Alice" to "Marketing", "Bob" to "Sales", "Carol" to "Marketing")
|
||||||
|
val namesByTeam = nameToTeam.groupBy({ it.second }, { it.first })
|
||||||
|
|
||||||
|
val mutableNamesByTeam1 = updateMap(HM(), "", "")
|
||||||
|
val mutableNamesByTeam2 = updateMap(HashMap(), "", "")
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
assertEquals(namesByTeam, mutableNamesByTeam1)
|
||||||
|
assertEquals(namesByTeam, mutableNamesByTeam2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val mutableNamesByTeam1: java.util.HashMap<kotlin.String, kotlin.collections.MutableList<kotlin.String>>
|
||||||
|
public val mutableNamesByTeam2: java.util.HashMap<kotlin.String, kotlin.collections.MutableList<kotlin.String>>
|
||||||
|
public val nameToTeam: kotlin.collections.List<kotlin.Pair<kotlin.String, kotlin.String>>
|
||||||
|
public val namesByTeam: kotlin.collections.Map<kotlin.String, kotlin.collections.List<kotlin.String>>
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
|
public fun </*0*/ K, /*1*/ V, /*2*/ M : kotlin.collections.MutableMap<in K, kotlin.collections.MutableList<V>>> updateMap(/*0*/ map: M, /*1*/ k: K, /*2*/ v: V): M
|
||||||
|
public typealias HM</*0*/ Kt, /*1*/ Vt> = java.util.HashMap<Kt, Vt>
|
||||||
@@ -21064,6 +21064,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.kt")
|
||||||
|
public void testTypeAliasConstructorTypeArgumentsInferenceWithNestedCalls2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeAliasConstructorTypeArgumentsInferenceWithPhantomTypes.kt")
|
@TestMetadata("typeAliasConstructorTypeArgumentsInferenceWithPhantomTypes.kt")
|
||||||
public void testTypeAliasConstructorTypeArgumentsInferenceWithPhantomTypes() throws Exception {
|
public void testTypeAliasConstructorTypeArgumentsInferenceWithPhantomTypes() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithPhantomTypes.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithPhantomTypes.kt");
|
||||||
|
|||||||
@@ -1304,6 +1304,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("hashMapTypeAlias.kt")
|
||||||
|
public void testHashMapTypeAlias() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeAliasSamAdapterConstructors.kt")
|
@TestMetadata("typeAliasSamAdapterConstructors.kt")
|
||||||
public void testTypeAliasSamAdapterConstructors() throws Exception {
|
public void testTypeAliasSamAdapterConstructors() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/typealias/typeAliasSamAdapterConstructors.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/typealias/typeAliasSamAdapterConstructors.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user