From c283e15425126b5a09c16b778aaed8facc748a2c Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 7 May 2019 17:55:03 +0300 Subject: [PATCH] [NI] Preserve annotations during type substitution #KT-31346 Fixed --- .../kotlin/resolve/DelegatedPropertyInferenceSession.kt | 6 +++--- .../resolve/calls/tower/KotlinResolutionCallbacksImpl.kt | 3 ++- .../kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt | 6 +++--- .../kotlin/resolve/calls/components/ExternalComponents.kt | 2 ++ .../resolve/calls/components/KotlinCallCompleter.kt | 2 +- .../calls/components/PostponedArgumentsAnalyzer.kt | 2 ++ .../kotlin/resolve/calls/components/ResolutionParts.kt | 2 +- .../calls/inference/components/NewTypeSubstitutor.kt | 7 +++---- .../tests/controlStructures/lambdasInExclExclAndElvis.kt | 4 ++-- .../tests/resolve/dslMarker/annotatedFunctionType.kt | 8 ++++---- .../tests/resolve/dslMarker/annotatedFunctionType_1_4.kt | 8 ++++---- .../tests/resolve/dslMarker/markersIntersection.kt | 4 ++-- .../resolve/dslMarker/substitutedReceiverAnnotatedType.kt | 2 +- .../tests/resolve/specialConstructions/constantsInIf.kt | 2 +- 14 files changed, 31 insertions(+), 27 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt index 6f03f3a1002..fdb6c744021 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt @@ -53,14 +53,14 @@ class DelegatedPropertyInferenceSession( ?: builtIns.nullableNothingType val valueParameterForThis = descriptor.valueParameters.getOrNull(0) ?: return - val substitutedType = substitutor.substituteKeepAnnotations(valueParameterForThis.type.unwrap()) + val substitutedType = substitutor.safeSubstitute(valueParameterForThis.type.unwrap()) commonSystem.addSubtypeConstraint(typeOfThis.unwrap(), substitutedType, DelegatedPropertyConstraintPosition(atom)) } private fun ResolvedCallAtom.addConstraintsForGetValueMethod(commonSystem: ConstraintSystemBuilder) { if (expectedType != null) { val unsubstitutedReturnType = candidateDescriptor.returnType?.unwrap() ?: return - val substitutedReturnType = substitutor.substituteKeepAnnotations(unsubstitutedReturnType) + val substitutedReturnType = substitutor.safeSubstitute(unsubstitutedReturnType) commonSystem.addSubtypeConstraint(substitutedReturnType, expectedType, DelegatedPropertyConstraintPosition(atom)) } @@ -71,7 +71,7 @@ class DelegatedPropertyInferenceSession( private fun ResolvedCallAtom.addConstraintsForSetValueMethod(commonSystem: ConstraintSystemBuilder) { if (expectedType != null) { val unsubstitutedParameterType = candidateDescriptor.valueParameters.getOrNull(2)?.type?.unwrap() ?: return - val substitutedParameterType = substitutor.substituteKeepAnnotations(unsubstitutedParameterType) + val substitutedParameterType = substitutor.safeSubstitute(unsubstitutedParameterType) commonSystem.addSubtypeConstraint(expectedType, substitutedParameterType, DelegatedPropertyConstraintPosition(atom)) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index 45e5591c4e5..15b14e31454 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -91,6 +91,7 @@ class KotlinResolutionCallbacksImpl( receiverType: UnwrappedType?, parameters: List, expectedReturnType: UnwrappedType?, + annotations: Annotations, stubsForPostponedVariables: Map ): Pair, InferenceSession?> { val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument @@ -130,7 +131,7 @@ class KotlinResolutionCallbacksImpl( val builtIns = outerCallContext.scope.ownerDescriptor.builtIns val expectedType = createFunctionType( - builtIns, Annotations.EMPTY, receiverType, parameters, null, + builtIns, annotations, receiverType, parameters, null, lambdaInfo.expectedType, isSuspend ) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index 3a2fb6e34c2..2750f5d521c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -191,8 +191,8 @@ class ResolvedAtomCompleter( val substitutedFunctionalType = createFunctionType( builtIns, existingLambdaType.annotations, - lambda.receiver?.let { resultSubstitutor.substituteKeepAnnotations(it) }, - lambda.parameters.map { resultSubstitutor.substituteKeepAnnotations(it) }, + lambda.receiver?.let { resultSubstitutor.safeSubstitute(it) }, + lambda.parameters.map { resultSubstitutor.safeSubstitute(it) }, null, // parameter names transforms to special annotations, so they are already taken from parameter types returnType, lambda.isSuspend @@ -208,7 +208,7 @@ class ResolvedAtomCompleter( } val valueType = receiver.value.type.unwrap() - val newValueType = resultSubstitutor.substituteKeepAnnotations(valueType) + val newValueType = resultSubstitutor.safeSubstitute(valueType) if (valueType !== newValueType) { val newReceiverValue = receiver.value.replaceType(newValueType) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index 8831def07a2..72e7e3fb94b 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower @@ -41,6 +42,7 @@ interface KotlinResolutionCallbacks { receiverType: UnwrappedType?, parameters: List, expectedReturnType: UnwrappedType?, // null means, that return type is not proper i.e. it depends on some type variables + annotations: Annotations, stubsForPostponedVariables: Map ): Pair, InferenceSession?> diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index e8630db6e5f..851008c6b2d 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -140,7 +140,7 @@ class KotlinCallCompleter( private fun KotlinResolutionCandidate.returnTypeWithSmartCastInfo(resolutionCallbacks: KotlinResolutionCallbacks): UnwrappedType? { val returnType = resolvedCall.candidateDescriptor.returnType?.unwrap() ?: return null val returnTypeWithSmartCastInfo = computeReturnTypeWithSmartCastInfo(returnType, resolutionCallbacks) - return resolvedCall.substitutor.substituteKeepAnnotations(returnTypeWithSmartCastInfo) + return resolvedCall.substitutor.safeSubstitute(returnTypeWithSmartCastInfo) } private fun KotlinResolutionCandidate.addExpectedTypeConstraint( diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt index d45d45d6db3..1e0d287c35c 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.addSubsystemFromArgument import org.jetbrains.kotlin.resolve.calls.inference.model.* @@ -105,6 +106,7 @@ class PostponedArgumentsAnalyzer( receiver, parameters, expectedTypeForReturnArguments, + lambda.expectedType?.annotations ?: Annotations.EMPTY, stubsForPostponedVariables.cast() ) 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 4a023d5fe27..1a3250fbb2a 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 @@ -290,7 +290,7 @@ private fun KotlinResolutionCandidate.prepareExpectedType( callComponents.languageVersionSettings ) val resultType = knownTypeParametersResultingSubstitutor?.substitute(argumentType) ?: argumentType - return resolvedCall.substitutor.substituteKeepAnnotations(resultType) + return resolvedCall.substitutor.safeSubstitute(resultType) } private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion( 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 9239640e440..15f485e9274 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 @@ -6,6 +6,7 @@ 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.types.* @@ -17,9 +18,7 @@ import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker interface NewTypeSubstitutor: TypeSubstitutorMarker { fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType? - fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type, runCapturedChecks = true, keepAnnotation = false) ?: type - - fun substituteKeepAnnotations(type: UnwrappedType): UnwrappedType = + fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type, runCapturedChecks = true, keepAnnotation = true) ?: type private fun substitute(type: UnwrappedType, keepAnnotation: Boolean, runCapturedChecks: Boolean): UnwrappedType? = @@ -114,7 +113,7 @@ interface NewTypeSubstitutor: TypeSubstitutorMarker { // simple classifier type var replacement = substituteNotNullTypeWithConstructor(typeConstructor) ?: return null if (keepAnnotation) { - replacement = replacement.replaceAnnotations(type.annotations) + replacement = replacement.replaceAnnotations(CompositeAnnotations(replacement.annotations, type.annotations)) } if (type.isMarkedNullable) { replacement = replacement.makeNullableAsSpecified(true) diff --git a/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt b/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt index b81ee7acdd5..cdf3a75a555 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt @@ -9,8 +9,8 @@ fun test() { // KT-KT-9070 { } ?: 1 - use({ 2 } ?: 1); + use({ 2 } ?: 1); 1 ?: { } - use(1 ?: { }) + use(1 ?: { }) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/dslMarker/annotatedFunctionType.kt b/compiler/testData/diagnostics/tests/resolve/dslMarker/annotatedFunctionType.kt index 9a3fe84a3c7..f694b3f8d5c 100644 --- a/compiler/testData/diagnostics/tests/resolve/dslMarker/annotatedFunctionType.kt +++ b/compiler/testData/diagnostics/tests/resolve/dslMarker/annotatedFunctionType.kt @@ -21,7 +21,7 @@ fun baz4(x: @MyDsl B.() -> Unit) {} fun @MyDsl A.baz5() { baz4 { bar() - foo() + foo() } } @@ -36,21 +36,21 @@ fun main() { baz3 { baz2 { bar() - foo() + foo() } } baz1 { baz4 { bar() - foo() + foo() } } baz3 { baz4 { bar() - foo() + foo() } } diff --git a/compiler/testData/diagnostics/tests/resolve/dslMarker/annotatedFunctionType_1_4.kt b/compiler/testData/diagnostics/tests/resolve/dslMarker/annotatedFunctionType_1_4.kt index e09446630c7..30b8565f613 100644 --- a/compiler/testData/diagnostics/tests/resolve/dslMarker/annotatedFunctionType_1_4.kt +++ b/compiler/testData/diagnostics/tests/resolve/dslMarker/annotatedFunctionType_1_4.kt @@ -22,7 +22,7 @@ fun baz4(x: @MyDsl B.() -> Unit) {} fun @MyDsl A.baz5() { baz4 { bar() - foo() + foo() } } @@ -37,21 +37,21 @@ fun main() { baz3 { baz2 { bar() - foo() + foo() } } baz1 { baz4 { bar() - foo() + foo() } } baz3 { baz4 { bar() - foo() + foo() } } diff --git a/compiler/testData/diagnostics/tests/resolve/dslMarker/markersIntersection.kt b/compiler/testData/diagnostics/tests/resolve/dslMarker/markersIntersection.kt index d3c5eff2170..775a0300d13 100644 --- a/compiler/testData/diagnostics/tests/resolve/dslMarker/markersIntersection.kt +++ b/compiler/testData/diagnostics/tests/resolve/dslMarker/markersIntersection.kt @@ -60,7 +60,7 @@ fun test() { bar1t(this) { a() bar1 { - a() + a() b() } @@ -76,7 +76,7 @@ fun test() { foo2 { bar1t(this) { a() - b() + b() } } } diff --git a/compiler/testData/diagnostics/tests/resolve/dslMarker/substitutedReceiverAnnotatedType.kt b/compiler/testData/diagnostics/tests/resolve/dslMarker/substitutedReceiverAnnotatedType.kt index b8e3754e133..d65adb64d78 100644 --- a/compiler/testData/diagnostics/tests/resolve/dslMarker/substitutedReceiverAnnotatedType.kt +++ b/compiler/testData/diagnostics/tests/resolve/dslMarker/substitutedReceiverAnnotatedType.kt @@ -19,7 +19,7 @@ fun test() { foo { a() bar { - a() + a() this@foo.a() b() } diff --git a/compiler/testData/diagnostics/tests/resolve/specialConstructions/constantsInIf.kt b/compiler/testData/diagnostics/tests/resolve/specialConstructions/constantsInIf.kt index a25eabd0684..2cabddea8fd 100644 --- a/compiler/testData/diagnostics/tests/resolve/specialConstructions/constantsInIf.kt +++ b/compiler/testData/diagnostics/tests/resolve/specialConstructions/constantsInIf.kt @@ -8,7 +8,7 @@ fun test() { 2 }) - bar(1 ?: 2) + bar(1 ?: 2) } fun bar(s: String) = s \ No newline at end of file