From b6af13f18de8fbbc1fb20f66cf44ad0990c20558 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Fri, 8 Nov 2019 12:47:54 +0300 Subject: [PATCH] [NI] Add missing substitution of known type parameters Known type parameters appear after inheriting from class with type parameters. Their substitution matters for inner class constructor, because without substitution it's parameters will be type checked against incorrect (original) parameter descriptor with unsubstituted type parameters. Skip creation of composite substitutor, if old substitutor is empty. New substitutors return null in case they don't substitute a type, but old type substitutors have explicit isEmpty method. Composite substitutor with empty old substitutor leads to creation of incorrect descriptor copies. --- .../fir/FirDiagnosticsSmokeTestGenerated.java | 10 +++ .../tower/KotlinToResolvedCallTransformer.kt | 12 ++- .../calls/components/ResolutionParts.kt | 4 + .../components/NewTypeSubstitutor.kt | 23 ++++- .../resolve/calls/model/ResolutionAtoms.kt | 3 +- .../calls/model/ResolutionCandidate.kt | 1 + .../tests/inference/knownTypeParameters.kt | 30 +++++++ .../tests/inference/knownTypeParameters.txt | 86 +++++++++++++++++++ .../diagnostics/tests/inference/kt32415.kt | 9 ++ .../diagnostics/tests/inference/kt32415.txt | 31 +++++++ .../checkers/DiagnosticsTestGenerated.java | 10 +++ .../DiagnosticsUsingJavacTestGenerated.java | 10 +++ 12 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt create mode 100644 compiler/testData/diagnostics/tests/inference/knownTypeParameters.txt create mode 100644 compiler/testData/diagnostics/tests/inference/kt32415.kt create mode 100644 compiler/testData/diagnostics/tests/inference/kt32415.txt diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index f5dd8b5e26e..11889a4d50c 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -9823,6 +9823,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/inference/invokeLambdaAsFunction.kt"); } + @TestMetadata("knownTypeParameters.kt") + public void testKnownTypeParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt"); + } + @TestMetadata("kt11963.kt") public void testKt11963() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/kt11963.kt"); @@ -9858,6 +9863,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/inference/kt3184.kt"); } + @TestMetadata("kt32415.kt") + public void testKt32415() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/kt32415.kt"); + } + @TestMetadata("kt32434.kt") public void testKt32434() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/kt32434.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index d3a40a891f6..f0d8e717847 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.calls.context.CallPosition import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor +import org.jetbrains.kotlin.resolve.calls.inference.components.composeWith import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.inference.substitute import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateTypes @@ -728,10 +729,13 @@ class NewResolvedCallImpl( } private fun CallableDescriptor.substituteInferredVariablesAndApproximate(substitutor: NewTypeSubstitutor?): CallableDescriptor { - return substitute(resolvedCallAtom.freshVariablesSubstitutor) - .substituteAndApproximateTypes( - substitutor ?: FreshVariableNewTypeSubstitutor.Empty, typeApproximator - ) + val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty + + val compositeSubstitutor = resolvedCallAtom.freshVariablesSubstitutor + .composeWith(resolvedCallAtom.knownParametersSubstitutor) + .composeWith(inferredTypeVariablesSubstitutor) + + return substituteAndApproximateTypes(compositeSubstitutor, typeApproximator) } fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? = diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index 9aa870e2b46..1686264a451 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorMo import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -124,6 +125,8 @@ internal object NoArguments : ResolutionPart() { internal object CreateFreshVariablesSubstitutor : ResolutionPart() { override fun KotlinResolutionCandidate.process(workIndex: Int) { + resolvedCall.knownParametersSubstitutor = knownTypeParametersResultingSubstitutor ?: TypeSubstitutor.EMPTY + if (candidateDescriptor.typeParameters.isEmpty()) { resolvedCall.freshVariablesSubstitutor = FreshVariableNewTypeSubstitutor.Empty return @@ -415,6 +418,7 @@ internal object ErrorDescriptorResolutionPart : ResolutionPart() { resolvedCall.typeArgumentMappingByOriginal = TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments resolvedCall.argumentMappingByOriginal = emptyMap() resolvedCall.freshVariablesSubstitutor = FreshVariableNewTypeSubstitutor.Empty + resolvedCall.knownParametersSubstitutor = TypeSubstitutor.EMPTY resolvedCall.argumentToCandidateParameter = emptyMap() kotlinCall.explicitReceiver?.safeAs()?.let { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt index 2f53bd7538e..a58f2db1441 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt @@ -7,8 +7,8 @@ package org.jetbrains.kotlin.resolve.calls.inference.components import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations -import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor +import org.jetbrains.kotlin.resolve.calls.inference.substitute import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.NewCapturedType import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor @@ -190,7 +190,22 @@ class FreshVariableNewTypeSubstitutor(val freshVariables: List abstract val freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor - + abstract val knownParametersSubstitutor: TypeSubstitutor abstract val argumentsWithConversion: Map } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt index 3277453ff96..c558ae66c1d 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt @@ -179,6 +179,7 @@ class MutableResolvedCallAtom( override lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping override lateinit var argumentMappingByOriginal: Map override lateinit var freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor + override lateinit var knownParametersSubstitutor: TypeSubstitutor lateinit var argumentToCandidateParameter: Map private var samAdapterMap: HashMap? = null diff --git a/compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt b/compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt new file mode 100644 index 00000000000..d719187d3fa --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt @@ -0,0 +1,30 @@ +// !LANGUAGE: +NewInference + +open class A { + open inner class A1(val a1: T1) + open inner class A2(val a2: T2) + + open fun f1(arg: T1) = arg + open fun f2(arg: T2) = arg +} + +open class B : A() { + open inner class B1(b1: T) : A1(b1) + open inner class B2(b2: Int) : A2(b2) + + fun variableToKnownParameter(p: T): Int = + p as? Int ?: 0 + + inner class B3(b3: T) : A2(variableToKnownParameter(b3)) + + override fun f1(arg: T) = arg + override fun f2(arg: Int) = arg +} + +class C : B() { + inner class C1(c1: String): B1(c1) + inner class C2 : B2(15) + + override fun f1(arg: String) = arg + override fun f2(arg: Int) = arg +} diff --git a/compiler/testData/diagnostics/tests/inference/knownTypeParameters.txt b/compiler/testData/diagnostics/tests/inference/knownTypeParameters.txt new file mode 100644 index 00000000000..bbd7d1b2d6c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/knownTypeParameters.txt @@ -0,0 +1,86 @@ +package + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun f1(/*0*/ arg: T1): T1 + public open fun f2(/*0*/ arg: T2): T2 + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public open inner class A1 /*captured type parameters: /*0*/ T1, /*1*/ T2*/ { + public constructor A1(/*0*/ a1: T1) + public final val a1: T1 + 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 open inner class A2 /*captured type parameters: /*0*/ T1, /*1*/ T2*/ { + public constructor A2(/*0*/ a2: T2) + public final val a2: T2 + 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 open class B : A { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun f1(/*0*/ arg: T): T + public open override /*1*/ fun f2(/*0*/ arg: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final fun variableToKnownParameter(/*0*/ p: T): kotlin.Int + + public open inner class B1 /*captured type parameters: /*0*/ T*/ : A.A1 { + public constructor B1(/*0*/ b1: T) + public final override /*1*/ /*fake_override*/ val a1: 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 open inner class B2 /*captured type parameters: /*0*/ T*/ : A.A2 { + public constructor B2(/*0*/ b2: kotlin.Int) + public final override /*1*/ /*fake_override*/ val a2: kotlin.Int + 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 final inner class B3 /*captured type parameters: /*0*/ T*/ : A.A2 { + public constructor B3(/*0*/ b3: T) + public final override /*1*/ /*fake_override*/ val a2: kotlin.Int + 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 final class C : B { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun f1(/*0*/ arg: kotlin.String): kotlin.String + public open override /*1*/ fun f2(/*0*/ arg: kotlin.Int): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + public final override /*1*/ /*fake_override*/ fun variableToKnownParameter(/*0*/ p: kotlin.String): kotlin.Int + + public final inner class C1 : B.B1 { + public constructor C1(/*0*/ c1: kotlin.String) + public final override /*1*/ /*fake_override*/ val a1: kotlin.String + 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 final inner class C2 : B.B2 { + public constructor C2() + public final override /*1*/ /*fake_override*/ val a2: kotlin.Int + 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 + } +} diff --git a/compiler/testData/diagnostics/tests/inference/kt32415.kt b/compiler/testData/diagnostics/tests/inference/kt32415.kt new file mode 100644 index 00000000000..3b56457ee7d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/kt32415.kt @@ -0,0 +1,9 @@ +// !LANGUAGE: +NewInference + +abstract class TestType { + open inner class Inner(val item: V) +} + +class Derived: TestType() { + inner class DerivedInner(item: Long): Inner(item) +} diff --git a/compiler/testData/diagnostics/tests/inference/kt32415.txt b/compiler/testData/diagnostics/tests/inference/kt32415.txt new file mode 100644 index 00000000000..12b2efea43b --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/kt32415.txt @@ -0,0 +1,31 @@ +package + +public final class Derived : TestType { + public constructor Derived() + 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 final inner class DerivedInner : TestType.Inner { + public constructor DerivedInner(/*0*/ item: kotlin.Long) + public final override /*1*/ /*fake_override*/ val item: kotlin.Long + 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 abstract class TestType { + public constructor TestType() + 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 open inner class Inner /*captured type parameters: /*0*/ V : kotlin.Any*/ { + public constructor Inner(/*0*/ item: V) + public final val item: V + 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 + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 85c0e3b05f9..c304a506817 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -9830,6 +9830,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/invokeLambdaAsFunction.kt"); } + @TestMetadata("knownTypeParameters.kt") + public void testKnownTypeParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt"); + } + @TestMetadata("kt11963.kt") public void testKt11963() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/kt11963.kt"); @@ -9865,6 +9870,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/kt3184.kt"); } + @TestMetadata("kt32415.kt") + public void testKt32415() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/kt32415.kt"); + } + @TestMetadata("kt32434.kt") public void testKt32434() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/kt32434.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 27faa31d7ec..c75feb1210f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -9825,6 +9825,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/invokeLambdaAsFunction.kt"); } + @TestMetadata("knownTypeParameters.kt") + public void testKnownTypeParameters() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt"); + } + @TestMetadata("kt11963.kt") public void testKt11963() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/kt11963.kt"); @@ -9860,6 +9865,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/kt3184.kt"); } + @TestMetadata("kt32415.kt") + public void testKt32415() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/kt32415.kt"); + } + @TestMetadata("kt32434.kt") public void testKt32434() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/kt32434.kt");