K1: report swallowed diagnostic about upper bound violation

#KT-55055 Fixed
This commit is contained in:
Mikhail Glukhikh
2023-02-06 09:30:14 +01:00
committed by Space Team
parent b148df15a9
commit 930237b60e
15 changed files with 90 additions and 5 deletions
@@ -36426,6 +36426,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/unsafeAssignment_noReport.kt");
}
@Test
@TestMetadata("upperBoundViolation.kt")
public void testUpperBoundViolation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/upperBoundViolation.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {
@@ -36426,6 +36426,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/unsafeAssignment_noReport.kt");
}
@Test
@TestMetadata("upperBoundViolation.kt")
public void testUpperBoundViolation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/upperBoundViolation.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {
@@ -36426,6 +36426,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/unsafeAssignment_noReport.kt");
}
@Test
@TestMetadata("upperBoundViolation.kt")
public void testUpperBoundViolation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/upperBoundViolation.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {
@@ -36522,6 +36522,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/unsafeAssignment_noReport.kt");
}
@Test
@TestMetadata("upperBoundViolation.kt")
public void testUpperBoundViolation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/upperBoundViolation.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {
@@ -884,6 +884,7 @@ public interface Errors {
DiagnosticFactory4<PsiElement, KotlinType, String, String, BuilderLambdaLabelingInfo> STUB_TYPE_IN_RECEIVER_CAUSES_AMBIGUITY = DiagnosticFactory4.create(ERROR);
DiagnosticFactory2<PsiElement, Name, Name> BUILDER_INFERENCE_MULTI_LAMBDA_RESTRICTION = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<PsiElement, Name, Name> BUILDER_INFERENCE_STUB_RECEIVER = DiagnosticFactory2.create(ERROR);
DiagnosticFactory4<KtElement, Name, Name, KotlinType, KotlinType> UPPER_BOUND_VIOLATION_IN_CONSTRAINT = DiagnosticFactory4.create(ERROR);
DiagnosticFactory1<PsiElement, Collection<? extends ResolvedCall<?>>> NONE_APPLICABLE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, Collection<? extends ResolvedCall<?>>> CANNOT_COMPLETE_RESOLVE = DiagnosticFactory1.create(ERROR);
@@ -1006,6 +1006,7 @@ public class DefaultErrorMessages {
MAP.put(STUB_TYPE_IN_RECEIVER_CAUSES_AMBIGUITY, "The type of a receiver hasn''t been inferred yet. To disambiguate this call, explicitly cast it to `{0}` if you want the builder''s type parameter(s) `{1}` to be inferred to `{2}`.", RENDER_TYPE, STRING, STRING, null);
MAP.put(BUILDER_INFERENCE_MULTI_LAMBDA_RESTRICTION, "Unstable inference behaviour with multiple lambdas. Please either specify the type argument for generic parameter `{0}` of `{1}` explicitly", TO_STRING, TO_STRING);
MAP.put(BUILDER_INFERENCE_STUB_RECEIVER, "The type of a receiver hasn''t been inferred yet. Please specify type argument for generic parameter `{0}` of `{1}` explicitly", TO_STRING, TO_STRING);
MAP.put(UPPER_BOUND_VIOLATION_IN_CONSTRAINT, "Upper bound violation for generic parameter `{0}` of `{1}`: {3} is not a subtype of {2}", TO_STRING, TO_STRING, RENDER_TYPE, RENDER_TYPE);
MAP.put(NONE_APPLICABLE, "None of the following functions can be called with the arguments supplied: {0}", AMBIGUOUS_CALLS);
MAP.put(CANNOT_COMPLETE_RESOLVE, "Cannot choose among the following candidates without completing type inference: {0}", AMBIGUOUS_CALLS);
MAP.put(UNRESOLVED_REFERENCE_WRONG_RECEIVER, "Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: {0}", AMBIGUOUS_CALLS);
@@ -513,7 +513,20 @@ class DiagnosticReporterByTrackingStrategy(
// some error reported later?
}
is CallableReferenceConstraintPosition<*> -> TODO()
is DeclaredUpperBoundConstraintPosition<*> -> TODO()
is DeclaredUpperBoundConstraintPosition<*> -> {
val originalCall = (position as DeclaredUpperBoundConstraintPositionImpl).kotlinCall
val typeParameterDescriptor = position.typeParameter
val ownerDescriptor = typeParameterDescriptor.containingDeclaration
trace.reportDiagnosticOnce(
UPPER_BOUND_VIOLATION_IN_CONSTRAINT.on(
(originalCall as PSIKotlinCall).psiCall.callElement,
typeParameterDescriptor.name,
ownerDescriptor.name,
error.upperKotlinType,
error.lowerKotlinType
)
)
}
is DelegatedPropertyConstraintPosition<*> -> {
// DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, reported later
}
@@ -39,6 +39,7 @@ class CallableReferenceArgumentResolver(val callableReferenceOverloadConflictRes
if (chosenCandidate != null) {
val toFreshSubstitutor = CreateFreshVariablesSubstitutor.createToFreshVariableSubstitutorAndAddInitialConstraints(
chosenCandidate.candidate,
resolvedAtom.atom.call,
csBuilder
)
chosenCandidate.addConstraints(csBuilder, toFreshSubstitutor, callableReference = argument)
@@ -124,7 +124,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
if (candidateDescriptor.typeParameters.isEmpty())
FreshVariableNewTypeSubstitutor.Empty
else
createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, csBuilder)
createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, resolvedCall.atom, csBuilder)
val knownTypeParametersSubstitutor = knownTypeParametersResultingSubstitutor?.let {
createKnownParametersFromFreshVariablesSubstitutor(toFreshVariables, it)
@@ -220,6 +220,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
fun createToFreshVariableSubstitutorAndAddInitialConstraints(
candidateDescriptor: CallableDescriptor,
kotlinCall: KotlinCall,
csBuilder: ConstraintSystemOperation
): FreshVariableNewTypeSubstitutor {
val typeParameters = candidateDescriptor.typeParameters
@@ -242,7 +243,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
for (index in typeParameters.indices) {
val typeParameter = typeParameters[index]
val freshVariable = freshTypeVariables[index]
val position = DeclaredUpperBoundConstraintPositionImpl(typeParameter)
val position = DeclaredUpperBoundConstraintPositionImpl(typeParameter, kotlinCall)
for (upperBound in typeParameter.upperBounds) {
freshVariable.addSubtypeConstraint(upperBound, position)
@@ -263,7 +264,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
// there can be null in case we already captured type parameter in outer class (in case of inner classes)
// see test innerClassTypeAliasConstructor.kt
val originalTypeParameter = originalTypeParameters.getOrNull(originalIndex) ?: continue
val position = DeclaredUpperBoundConstraintPositionImpl(originalTypeParameter)
val position = DeclaredUpperBoundConstraintPositionImpl(originalTypeParameter, kotlinCall)
for (upperBound in originalTypeParameter.upperBounds) {
freshVariable.addSubtypeConstraint(upperBound, position)
}
@@ -28,7 +28,8 @@ class BuilderInferenceSubstitutionConstraintPositionImpl(
class ExpectedTypeConstraintPositionImpl(topLevelCall: KotlinCall) : ExpectedTypeConstraintPosition<KotlinCall>(topLevelCall)
class DeclaredUpperBoundConstraintPositionImpl(
typeParameter: TypeParameterDescriptor
typeParameter: TypeParameterDescriptor,
val kotlinCall: KotlinCall
) : DeclaredUpperBoundConstraintPosition<TypeParameterDescriptor>(typeParameter) {
override fun toString() = "DeclaredUpperBound ${typeParameter.name} from ${typeParameter.containingDeclaration}"
}
@@ -0,0 +1,4 @@
/upperBoundViolation.kt:9:9: error: upper bound violation for generic parameter `T` of `printGenericNumber`: String is not a subtype of Number
printGenericNumber(this[0])
^
@@ -0,0 +1,11 @@
// !RENDER_DIAGNOSTICS_FULL_TEXT
// ISSUE: KT-55055
// FIR_DUMP
fun <T : Number> printGenericNumber(t: T) = println("Number is $t")
fun main() {
buildList { // inferred into MutableList<String>
add("Boom")
printGenericNumber(this[0])
}
}
@@ -0,0 +1,11 @@
FILE: upperBoundViolation.fir.kt
public final fun <T : R|kotlin/Number|> printGenericNumber(t: R|T|): R|kotlin/Unit| {
^printGenericNumber R|kotlin/io/println|(<strcat>(String(Number is ), R|<local>/t|))
}
public final fun main(): R|kotlin/Unit| {
R|kotlin/collections/buildList|<R|kotlin/String|>(<L> = buildList@fun R|kotlin/collections/MutableList<kotlin/String>|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=EXACTLY_ONCE> {
this@R|special/anonymous|.R|SubstitutionOverride<kotlin/collections/MutableList.add: R|kotlin/Boolean|>|(String(Boom))
R|/printGenericNumber|<R|kotlin/String|>(this@R|special/anonymous|.R|SubstitutionOverride<kotlin/collections/MutableList.get: R|Stub (chain inference): TypeVariable(E)|>|(Int(0)))
}
)
}
@@ -0,0 +1,11 @@
// !RENDER_DIAGNOSTICS_FULL_TEXT
// ISSUE: KT-55055
// FIR_DUMP
fun <T : Number> printGenericNumber(t: T) = println("Number is $t")
fun main() {
buildList { // inferred into MutableList<String>
add("Boom")
<!UPPER_BOUND_VIOLATION_IN_CONSTRAINT!>printGenericNumber(this[0])<!>
}
}
@@ -37258,6 +37258,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/unsafeAssignment_noReport.kt");
}
@Test
@TestMetadata("upperBoundViolation.kt")
public void testUpperBoundViolation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/upperBoundViolation.kt");
}
@Test
@TestMetadata("useInferenceInformationFromExtension.kt")
public void testUseInferenceInformationFromExtension() throws Exception {