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:
Dmitry Petrov
2016-11-10 12:23:25 +03:00
parent 549ae59562
commit 37eedc3703
7 changed files with 114 additions and 1 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve.calls
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -136,8 +137,13 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
) {
val substitutedType = substitutedArgument.type
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)
// 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)
}
}
@@ -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
}
@@ -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);
}
@TestMetadata("typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.kt")
public void testTypeAliasConstructorTypeArgumentsInferenceWithNestedCalls2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.kt");
doTest(fileName);
}
@TestMetadata("typeAliasConstructorTypeArgumentsInferenceWithPhantomTypes.kt")
public void testTypeAliasConstructorTypeArgumentsInferenceWithPhantomTypes() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithPhantomTypes.kt");
@@ -1304,6 +1304,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
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")
public void testTypeAliasSamAdapterConstructors() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/typealias/typeAliasSamAdapterConstructors.kt");