diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index ef175f93970..fb9c3adc351 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -2152,6 +2152,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert UpperBoundViolatedImpl( firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), + firDiagnostic.c, firDiagnostic as KtPsiDiagnostic, token, ) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 11358f2e388..a22aa126e98 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1533,6 +1533,7 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = UpperBoundViolated::class val expectedUpperBound: KtType val actualUpperBound: KtType + val extraMessage: String } interface UpperBoundViolatedInTypealiasExpansion : KtFirDiagnostic { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index d318d065aec..7d656bba9a7 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1839,6 +1839,7 @@ internal class ProjectionOnNonClassTypeArgumentImpl( internal class UpperBoundViolatedImpl( override val expectedUpperBound: KtType, override val actualUpperBound: KtType, + override val extraMessage: String, firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.UpperBoundViolated diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 2763708fa00..91afe5b2e09 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -691,6 +691,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val UPPER_BOUND_VIOLATED by error { parameter("expectedUpperBound") parameter("actualUpperBound") + parameter("extraMessage") } val UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION by error { parameter("expectedUpperBound") diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index ad1dc889893..a659001ef33 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -433,7 +433,7 @@ object FirErrors { val RECURSION_IN_IMPLICIT_TYPES: KtDiagnosticFactory0 by error0() val INFERENCE_ERROR: KtDiagnosticFactory0 by error0() val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT: KtDiagnosticFactory0 by error0() - val UPPER_BOUND_VIOLATED: KtDiagnosticFactory2 by error2() + val UPPER_BOUND_VIOLATED: KtDiagnosticFactory3 by error3() val UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION: KtDiagnosticFactory2 by error2() val TYPE_ARGUMENTS_NOT_ALLOWED: KtDiagnosticFactory1 by error1() val TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED: KtDiagnosticFactory0 by error0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirUpperBoundViolatedHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirUpperBoundViolatedHelpers.kt index ac70324fb00..344f4fd146b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirUpperBoundViolatedHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirUpperBoundViolatedHelpers.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.utils.addToStdlib.runIf import kotlin.reflect.KClass /** @@ -203,11 +204,17 @@ fun checkUpperBoundViolated( stubTypesEqualToAnything = true ) ) { - val factory = when { - isReportExpansionError && argumentTypeRef == null -> FirErrors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION - else -> FirErrors.UPPER_BOUND_VIOLATED + if (isReportExpansionError && argumentTypeRef == null) { + reporter.reportOn( + argumentSource, FirErrors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION, upperBound, argumentType.type, context + ) + } else { + val extraMessage = if(upperBound is ConeCapturedType) "Consider removing the explicit type arguments" else "" + reporter.reportOn( + argumentSource, FirErrors.UPPER_BOUND_VIOLATED, + upperBound, argumentType.type, extraMessage, context + ) } - reporter.reportOn(argumentSource, factory, upperBound, argumentType.type, context) } else { // Only check if the original check was successful to prevent duplicate diagnostics val additionalUpperBound = additionalUpperBoundsProvider?.getAdditionalUpperBound(upperBound) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 41c51d821ec..023546f7dfe 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -1319,7 +1319,13 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(INFERENCE_ERROR, "Inference error.") map.put(ILLEGAL_PROJECTION_USAGE, "Illegal projection usage.") map.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections on type arguments of functions and properties are prohibited.") - map.put(UPPER_BOUND_VIOLATED, "Type argument is not within its bounds: should be subtype of ''{0}''.", RENDER_TYPE, RENDER_TYPE) + map.put( + UPPER_BOUND_VIOLATED, + "Type argument is not within its bounds: should be subtype of ''{0}''.{2}", + RENDER_TYPE, + RENDER_TYPE, + OPTIONAL_SENTENCE + ) map.put( UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION, "Type argument is not within its bounds: should be subtype of ''{0}''.", diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.diag.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.diag.txt new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.diag.txt @@ -0,0 +1 @@ + diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.fir.diag.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.fir.diag.txt new file mode 100644 index 00000000000..b2b3ba445ba --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.fir.diag.txt @@ -0,0 +1,5 @@ +/capturedUpperBound.fir.kt:(100,120): error: Type argument is not within its bounds: should be subtype of 'CapturedType(*)'. Consider removing the explicit type arguments. + +/capturedUpperBound.fir.kt:(136,150): error: Type argument is not within its bounds: should be subtype of 'CapturedType(*)'. Consider removing the explicit type arguments. + +/capturedUpperBound.fir.kt:(166,182): error: Type argument is not within its bounds: should be subtype of 'CapturedType(*)'. Consider removing the explicit type arguments. diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.fir.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.fir.kt index dddb6e4c05a..d76326fba84 100644 --- a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.fir.kt @@ -1,4 +1,5 @@ // ISSUE: KT-65712 +// RENDER_DIAGNOSTICS_FULL_TEXT fun test(a: BodySpec, *>) { a.value<BodySpec, *>>() diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.kt index 5af9a873ffc..75375a82ff6 100644 --- a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.kt +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedUpperBound.kt @@ -1,4 +1,5 @@ // ISSUE: KT-65712 +// RENDER_DIAGNOSTICS_FULL_TEXT fun test(a: BodySpec, *>) { a.value, *>>()