[NI] Preserve annotations during type substitution

#KT-31346 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2019-05-07 17:55:03 +03:00
parent 2c26dc3af6
commit c283e15425
14 changed files with 31 additions and 27 deletions
@@ -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))
}
@@ -91,6 +91,7 @@ class KotlinResolutionCallbacksImpl(
receiverType: UnwrappedType?,
parameters: List<UnwrappedType>,
expectedReturnType: UnwrappedType?,
annotations: Annotations,
stubsForPostponedVariables: Map<NewTypeVariable, StubType>
): Pair<List<KotlinCallArgument>, 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
)
@@ -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)
@@ -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<UnwrappedType>,
expectedReturnType: UnwrappedType?, // null means, that return type is not proper i.e. it depends on some type variables
annotations: Annotations,
stubsForPostponedVariables: Map<NewTypeVariable, StubType>
): Pair<List<KotlinCallArgument>, InferenceSession?>
@@ -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(
@@ -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()
)
@@ -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(
@@ -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)
@@ -9,8 +9,8 @@ fun test() {
// KT-KT-9070
<!TYPE_MISMATCH!>{ }<!> <!USELESS_ELVIS!>?: 1<!>
use(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>{ 2 }<!> <!USELESS_ELVIS!>?: 1<!>);
use({ 2 } <!USELESS_ELVIS!>?: 1<!>);
1 <!USELESS_ELVIS!>?: <!TYPE_MISMATCH, UNUSED_LAMBDA_EXPRESSION!>{ }<!><!>
use(1 <!USELESS_ELVIS!>?: <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>{ }<!><!>)
use(1 <!USELESS_ELVIS!>?: { }<!>)
}
@@ -21,7 +21,7 @@ fun baz4(x: @MyDsl B.() -> Unit) {}
fun @MyDsl A.baz5() {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
<!DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
}
}
@@ -36,21 +36,21 @@ fun main() {
baz3 {
baz2 {
bar()
<!OI;DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
<!DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
}
}
baz1 {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
<!DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
}
}
baz3 {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
<!DSL_SCOPE_VIOLATION_WARNING!>foo<!>()
}
}
@@ -22,7 +22,7 @@ fun baz4(x: @MyDsl B.() -> Unit) {}
fun @MyDsl A.baz5() {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION!>foo<!>()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
@@ -37,21 +37,21 @@ fun main() {
baz3 {
baz2 {
bar()
<!OI;DSL_SCOPE_VIOLATION!>foo<!>()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
baz1 {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION!>foo<!>()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
baz3 {
baz4 {
bar()
<!OI;DSL_SCOPE_VIOLATION!>foo<!>()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
@@ -60,7 +60,7 @@ fun test() {
bar1t(this) {
a()
bar1 {
<!OI;DSL_SCOPE_VIOLATION!>a<!>()
<!DSL_SCOPE_VIOLATION!>a<!>()
b()
}
@@ -76,7 +76,7 @@ fun test() {
foo2 {
bar1t(this) {
a()
<!OI;DSL_SCOPE_VIOLATION!>b<!>()
<!DSL_SCOPE_VIOLATION!>b<!>()
}
}
}
@@ -19,7 +19,7 @@ fun test() {
foo<A> {
a()
bar<B> {
<!OI;DSL_SCOPE_VIOLATION!>a<!>()
<!DSL_SCOPE_VIOLATION!>a<!>()
this@foo.a()
b()
}
@@ -8,7 +8,7 @@ fun test() {
<!OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>
}<!>)
bar(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!><!OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> ?: <!OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!><!>)
bar(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!><!CONSTANT_EXPECTED_TYPE_MISMATCH, NI;CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> ?: <!CONSTANT_EXPECTED_TYPE_MISMATCH, NI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!><!>)
}
fun bar(s: String) = s