From 37eedc37039d47e9644161e2c5b990231a83a05c Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 10 Nov 2016 12:23:25 +0300 Subject: [PATCH] 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. --- .../resolve/calls/GenericCandidateResolver.kt | 8 +++- ...rTypeArgumentsInferenceWithNestedCalls2.kt | 38 +++++++++++++++++++ ...TypeArgumentsInferenceWithNestedCalls2.txt | 28 ++++++++++++++ .../typealias/hashMapTypeAlias.kt | 20 ++++++++++ .../typealias/hashMapTypeAlias.txt | 9 +++++ .../checkers/DiagnosticsTestGenerated.java | 6 +++ .../DiagnosticsTestWithStdLibGenerated.java | 6 +++ 7 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt index b9535dde33f..1cefc16d8f7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -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) } } diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.kt new file mode 100644 index 00000000000..5fe130b151e --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.kt @@ -0,0 +1,38 @@ +interface Ref { + var x: T +} + +class LateInitNumRef() : Ref { + constructor(x: NN) : this() { this.x = x } + + private var xx: NN? = null + + override var x: NN + get() = xx!! + set(value) { + xx = value + } +} + +typealias LateNR = LateInitNumRef + +fun > 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 = r1.x + r1a.x = r1a.x + r2.x = r2.x + r2a.x = r2a.x + r3.x = r3.x + r3a.x = r3a.x +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.txt new file mode 100644 index 00000000000..1dc9e78df8a --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls2.txt @@ -0,0 +1,28 @@ +package + +public val r1: Ref +public val r1a: Ref +public val r2: LateInitNumRef +public val r2a: LateInitNumRef +public val r3: LateInitNumRef +public val r3a: LateInitNumRef +public fun test(): kotlin.Unit +public fun > update(/*0*/ r: R, /*1*/ v: V): R + +public final class LateInitNumRef : Ref { + public constructor LateInitNumRef() + public constructor LateInitNumRef(/*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 { + 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 = LateInitNumRef diff --git a/compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.kt b/compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.kt new file mode 100644 index 00000000000..1cb5f2b94a5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.kt @@ -0,0 +1,20 @@ +import kotlin.test.* +import java.util.* + +typealias HM = HashMap + +fun >> 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) +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.txt b/compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.txt new file mode 100644 index 00000000000..9899f8b18a5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/typealias/hashMapTypeAlias.txt @@ -0,0 +1,9 @@ +package + +public val mutableNamesByTeam1: java.util.HashMap> +public val mutableNamesByTeam2: java.util.HashMap> +public val nameToTeam: kotlin.collections.List> +public val namesByTeam: kotlin.collections.Map> +public fun test(): kotlin.Unit +public fun >> updateMap(/*0*/ map: M, /*1*/ k: K, /*2*/ v: V): M +public typealias HM = java.util.HashMap diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 1e2ebaf7433..44382c82ff9 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index d6480d5c6b9..952f83baca8 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -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");