From 7c62e9aecdc59d23be94cb8946daf10094fb8f7d Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Mon, 26 Apr 2021 20:14:21 +0300 Subject: [PATCH] Introduce warnings reporting by missed constraints because of incorrect optimization in the constraints processor --- ...irOldFrontendDiagnosticsTestGenerated.java | 18 +++ ...DiagnosticsWithLightTreeTestGenerated.java | 48 ++++++++ .../FirBlackBoxCodegenTestGenerated.java | 18 +++ .../jetbrains/kotlin/diagnostics/Errors.java | 3 + .../rendering/DefaultErrorMessages.java | 3 + .../DiagnosticReporterByTrackingStrategy.kt | 15 ++- .../resolve/calls/tower/PSICallResolver.kt | 2 +- .../inference/ConstraintSystemBuilder.kt | 3 + .../components/ConstraintInjector.kt | 107 +++++++++++++----- .../model/ConstraintPositionAndErrors.kt | 5 +- .../inference/model/ConstraintStorage.kt | 5 + .../model/MutableConstraintStorage.kt | 9 +- .../model/NewConstraintSystemImpl.kt | 61 +++++++++- .../calls/model/KotlinCallDiagnostics.kt | 4 + .../resolve/calls/model/ResolutionAtoms.kt | 2 +- .../testData/codegen/box/inference/kt42042.kt | 15 +++ .../manyConstraintsDueToFlexibleRawTypes.kt | 34 ++++++ .../violatingUpperBoundForSelfType.kt | 13 +++ .../inference/capturedTypesInSelfType.fir.kt | 2 +- ...anyConstraintsDueToFlexibleRawTypes.fir.kt | 1 - .../manyConstraintsDueToFlexibleRawTypes.kt | 3 +- .../violatingUpperBoundForSelfType.fir.kt | 3 +- .../violatingUpperBoundForSelfType.kt | 3 +- ...violatingUpperBoundForSelfTypeError.fir.kt | 10 ++ .../violatingUpperBoundForSelfTypeError.kt | 10 ++ .../violatingUpperBoundForSelfTypeError.txt | 4 + .../tests/typeParameters/kt42042.fir.kt | 13 +++ .../tests/typeParameters/kt42042.kt | 13 +++ .../tests/typeParameters/kt42042.txt | 19 ++++ .../tests/typeParameters/kt42042Error.fir.kt | 13 +++ .../tests/typeParameters/kt42042Error.kt | 13 +++ .../tests/typeParameters/kt42042Error.txt | 19 ++++ .../test/runners/DiagnosticTestGenerated.java | 18 +++ .../codegen/BlackBoxCodegenTestGenerated.java | 18 +++ .../IrBlackBoxCodegenTestGenerated.java | 18 +++ .../LightAnalysisModeTestGenerated.java | 15 +++ .../kotlin/config/LanguageVersionSettings.kt | 1 + .../IrJsCodegenBoxES6TestGenerated.java | 5 + .../IrJsCodegenBoxTestGenerated.java | 5 + .../semantics/JsCodegenBoxTestGenerated.java | 5 + .../IrCodegenBoxWasmTestGenerated.java | 5 + 41 files changed, 535 insertions(+), 46 deletions(-) create mode 100644 compiler/testData/codegen/box/inference/kt42042.kt create mode 100644 compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt create mode 100644 compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt create mode 100644 compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt create mode 100644 compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.txt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/kt42042.fir.kt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/kt42042.kt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/kt42042.txt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/kt42042Error.fir.kt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/kt42042Error.txt diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 885ec72b012..55c5d230b46 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -12587,6 +12587,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt"); } + @Test + @TestMetadata("violatingUpperBoundForSelfTypeError.kt") + public void testViolatingUpperBoundForSelfTypeError() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference") @TestDataPath("$PROJECT_ROOT") @@ -29189,6 +29195,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingOnDelegates.kt"); } + @Test + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042.kt"); + } + + @Test + @TestMetadata("kt42042Error.kt") + public void testKt42042Error() throws Exception { + runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt"); + } + @Test @TestMetadata("kt42396.kt") public void testKt42396() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index e1e5e39730c..c7e12a3c167 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -12587,6 +12587,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt"); } + @Test + @TestMetadata("violatingUpperBoundForSelfTypeError.kt") + public void testViolatingUpperBoundForSelfTypeError() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference") @TestDataPath("$PROJECT_ROOT") @@ -21142,6 +21148,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/arrays.kt"); } + @Test + @TestMetadata("dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt") + public void testDontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt"); + } + + @Test + @TestMetadata("dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt") + public void testDontSubstituteAnotherErasedTypeArgumentIfRecursive() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt"); + } + @Test @TestMetadata("errorType.kt") public void testErrorType() throws Exception { @@ -21232,6 +21250,30 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/starProjectionToRaw.kt"); } + @Test + @TestMetadata("substituteAnotherErasedTypeArgument.kt") + public void testSubstituteAnotherErasedTypeArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteAnotherErasedTypeArgument.kt"); + } + + @Test + @TestMetadata("substituteOtherErasedDeepTypeArguments.kt") + public void testSubstituteOtherErasedDeepTypeArguments() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteOtherErasedDeepTypeArguments.kt"); + } + + @Test + @TestMetadata("substituteSeveralOtherErasedDependentTypeArguments.kt") + public void testSubstituteSeveralOtherErasedDependentTypeArguments() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedDependentTypeArguments.kt"); + } + + @Test + @TestMetadata("substituteSeveralOtherErasedTypeArguments.kt") + public void testSubstituteSeveralOtherErasedTypeArguments() throws Exception { + runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt"); + } + @Test @TestMetadata("typeEnhancement.kt") public void testTypeEnhancement() throws Exception { @@ -29159,6 +29201,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042.kt"); } + @Test + @TestMetadata("kt42042Error.kt") + public void testKt42042Error() throws Exception { + runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt"); + } + @Test @TestMetadata("kt42396.kt") public void testKt42396() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index f33561796b0..3c0a00e72c2 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -17190,6 +17190,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inference/kt39824.kt"); } + @Test + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/codegen/box/inference/kt42042.kt"); + } + @Test @TestMetadata("kt42130.kt") public void testKt42130() throws Exception { @@ -17214,6 +17220,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); } + @Test + @TestMetadata("manyConstraintsDueToFlexibleRawTypes.kt") + public void testManyConstraintsDueToFlexibleRawTypes() throws Exception { + runTest("compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt"); + } + @Test @TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt") public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception { @@ -17298,6 +17310,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt"); } + @Test + @TestMetadata("violatingUpperBoundForSelfType.kt") + public void testViolatingUpperBoundForSelfType() throws Exception { + runTest("compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt"); + } + @Nested @TestMetadata("compiler/testData/codegen/box/inference/builderInference") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 7d067eab79a..1f04af12dbf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -155,6 +155,7 @@ public interface Errors { DiagnosticFactory0 PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = DiagnosticFactory0.create(ERROR, VARIANCE_IN_PROJECTION); DiagnosticFactory2 UPPER_BOUND_VIOLATED = DiagnosticFactory2.create(ERROR); + DiagnosticFactory2 UPPER_BOUND_VIOLATED_WARNING = DiagnosticFactory2.create(WARNING); DiagnosticFactory0 REDUNDANT_NULLABLE = DiagnosticFactory0.create(WARNING, NULLABLE_TYPE); DiagnosticFactory0 DEFINITELY_NOT_NULLABLE_NOT_APPLICABLE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NULLABLE_ON_DEFINITELY_NOT_NULLABLE = DiagnosticFactory0.create(ERROR); @@ -1080,6 +1081,7 @@ public interface Errors { // Type mismatch DiagnosticFactory2 TYPE_MISMATCH = DiagnosticFactory2.create(ERROR); + DiagnosticFactory2 TYPE_MISMATCH_WARNING = DiagnosticFactory2.create(WARNING); DiagnosticFactory1 TYPE_MISMATCH_DUE_TO_EQUALS_LAMBDA_IN_FUN = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS = DiagnosticFactory1.create(ERROR); DiagnosticFactory2 MEMBER_PROJECTED_OUT = DiagnosticFactory2.create(ERROR); @@ -1091,6 +1093,7 @@ public interface Errors { DiagnosticFactory0 TYPE_MISMATCH_IN_RANGE = DiagnosticFactory0.create(ERROR, WHEN_CONDITION_IN_RANGE); DiagnosticFactory1 EXPECTED_PARAMETER_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 EXPECTED_PARAMETER_TYPE_MISMATCH_WARNING = DiagnosticFactory1.create(WARNING); DiagnosticFactory2> EXPECTED_PARAMETERS_NUMBER_MISMATCH = DiagnosticFactory2.create(ERROR, FUNCTION_PARAMETERS); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 2749b747a78..8f372ed221b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -104,6 +104,7 @@ public class DefaultErrorMessages { MAP.put(ACCESSOR_PARAMETER_NAME_SHADOWING, "Accessor parameter name 'field' is shadowed by backing field variable"); MAP.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE); + MAP.put(TYPE_MISMATCH_WARNING, "Type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE); MAP.put(TYPE_MISMATCH_DUE_TO_EQUALS_LAMBDA_IN_FUN, "Inferred type is a function type, but a non-function type {0} was expected. Use either ''= ...'' or '''{ ... }'', but not both.", RENDER_TYPE); @@ -559,6 +560,7 @@ public class DefaultErrorMessages { "Expected a value of type {0}. Assignment operation is not an expression, so it does not return any value", RENDER_TYPE); MAP.put(EXPECTED_PARAMETER_TYPE_MISMATCH, "Expected parameter of type {0}", RENDER_TYPE); + MAP.put(EXPECTED_PARAMETER_TYPE_MISMATCH_WARNING, "Expected parameter of type {0}", RENDER_TYPE); MAP.put(EXPECTED_PARAMETERS_NUMBER_MISMATCH, "Expected {0,choice,0#no parameters|1#one parameter of type|1<{0,number,integer} parameters of types} {1}", null, RENDER_COLLECTION_OF_TYPES); MAP.put(IMPLICIT_CAST_TO_ANY, "Conditional branch result of type {0} is implicitly cast to {1}", @@ -570,6 +572,7 @@ public class DefaultErrorMessages { }); 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_WARNING, "Type argument is not within its bounds: should be subtype of ''{0}''", RENDER_TYPE, RENDER_TYPE); MAP.put(FINAL_UPPER_BOUND, "''{0}'' is a final type, and thus a value of the type parameter is predetermined", RENDER_TYPE); MAP.put(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE, "Extension function type can not be used as an upper bound"); MAP.put(ONLY_ONE_CLASS_BOUND_ALLOWED, "Only one of the upper bounds can be a class"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index 48693d738e9..ec42a40c032 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -356,13 +356,17 @@ class DiagnosticReporterByTrackingStrategy( is LambdaArgumentConstraintPositionImpl -> position.lambda.atom else -> null } + val typeMismatchDiagnostic = if (error.isWarning) TYPE_MISMATCH_WARNING else TYPE_MISMATCH + val report = if (error.isWarning) trace::reportDiagnosticOnce else trace::report argument?.let { it.safeAs()?.let lambda@{ lambda -> val parameterTypes = lambda.parametersTypes?.toList() ?: return@lambda val index = parameterTypes.indexOf(error.upperKotlinType.unwrap()) val lambdaExpression = lambda.psiExpression as? KtLambdaExpression ?: return@lambda val parameter = lambdaExpression.valueParameters.getOrNull(index) ?: return@lambda - trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(parameter, error.upperKotlinType)) + val diagnosticFactory = + if (error.isWarning) EXPECTED_PARAMETER_TYPE_MISMATCH_WARNING else EXPECTED_PARAMETER_TYPE_MISMATCH + report(diagnosticFactory.on(parameter, error.upperKotlinType)) return } @@ -379,7 +383,7 @@ class DiagnosticReporterByTrackingStrategy( return } } - trace.report(TYPE_MISMATCH.on(deparenthesized, error.upperKotlinType, error.lowerKotlinType)) + report(typeMismatchDiagnostic.on(deparenthesized, error.upperKotlinType, error.lowerKotlinType)) } (position as? ExpectedTypeConstraintPositionImpl)?.let { @@ -388,13 +392,14 @@ class DiagnosticReporterByTrackingStrategy( if (!error.lowerKotlinType.isNullableNothing()) error.lowerKotlinType else error.upperKotlinType.makeNullable() if (call != null) { - trace.report(TYPE_MISMATCH.on(call, error.upperKotlinType, inferredType)) + report(typeMismatchDiagnostic.on(call, error.upperKotlinType, inferredType)) } } (position as? ExplicitTypeParameterConstraintPositionImpl)?.let { val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference - trace.report(UPPER_BOUND_VIOLATED.on(typeArgumentReference, error.upperKotlinType, error.lowerKotlinType)) + val diagnosticFactory = if (error.isWarning) UPPER_BOUND_VIOLATED_WARNING else UPPER_BOUND_VIOLATED + report(diagnosticFactory.on(typeArgumentReference, error.upperKotlinType, error.lowerKotlinType)) } (position as? FixVariableConstraintPositionImpl)?.let { @@ -407,7 +412,7 @@ class DiagnosticReporterByTrackingStrategy( val call = it.resolvedAtom?.atom?.safeAs()?.psiCall ?: call val expression = call.calleeExpression ?: return - trace.reportDiagnosticOnce(TYPE_MISMATCH.on(expression, error.upperKotlinType, error.lowerKotlinType)) + trace.reportDiagnosticOnce(typeMismatchDiagnostic.on(expression, error.upperKotlinType, error.lowerKotlinType)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index d73b00e502c..dc0eb8cfda1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -262,7 +262,7 @@ class PSICallResolver( return transformManyCandidatesAndRecordTrace(it, tracingStrategy, trace, context) } - if (getResultApplicability(diagnostics) == CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) { + if (getResultApplicability(diagnostics.filterErrorDiagnostics()) == CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) { val singleCandidate = result.resultCallAtom() ?: error("Should be not null for result: $result") val resolvedCall = kotlinToResolvedCallTransformer.onlyTransform(singleCandidate, diagnostics).also { tracingStrategy.unresolvedReferenceWrongReceiver(trace, listOf(it)) diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt index f940784ef41..9f8aa59ac78 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.inference import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage +import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError import org.jetbrains.kotlin.types.model.* interface ConstraintSystemOperation { @@ -45,6 +46,8 @@ interface ConstraintSystemOperation { fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List fun addOtherSystem(otherSystem: ConstraintStorage) + + val errors: List } interface ConstraintSystemBuilder : ConstraintSystemOperation { diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt index 61eca16a127..c7d3a61ac60 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt @@ -34,6 +34,11 @@ class ConstraintInjector( fun addInitialConstraint(initialConstraint: InitialConstraint) fun addError(error: ConstraintSystemError) + + fun addMissedConstraints( + position: IncorporationConstraintPosition, + constraints: MutableList> + ) } fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) { @@ -85,7 +90,12 @@ class ConstraintInjector( typeCheckerContext.setConstrainingTypesToPrintDebugInfo(lowerType, upperType) typeCheckerContext.runIsSubtypeOf(lowerType, upperType) - processConstraints(c, typeCheckerContext) + // Missed constraints are constraints which we skipped in the constraints processor by mistake (incorrect optimization) + val missedConstraints = processConstraints(c, typeCheckerContext) + + if (missedConstraints != null) { + c.addMissedConstraints(typeCheckerContext.position, missedConstraints) + } } private fun addEqualityConstraintAndIncorporateIt( @@ -97,41 +107,84 @@ class ConstraintInjector( typeCheckerContext.setConstrainingTypesToPrintDebugInfo(typeVariable, equalType) typeCheckerContext.addEqualityConstraint(typeVariable.typeConstructor(c), equalType) - processConstraints(c, typeCheckerContext) + // Missed constraints are constraints which we skipped in the constraints processor by mistake (incorrect optimization) + val missedConstraints = processConstraints(c, typeCheckerContext) + + if (missedConstraints != null) { + c.addMissedConstraints(typeCheckerContext.position, missedConstraints) + } } - private fun processConstraints(c: Context, typeCheckerContext: TypeCheckerContext) { + fun processMissedConstraints( + c: Context, + position: IncorporationConstraintPosition, + missedConstraints: List> + ) { + val properConstraintsProcessingEnabled = + languageVersionSettings.supportsFeature(LanguageFeature.ProperTypeInferenceConstraintsProcessing) + + // If proper constraints processing is enabled, then we don't have missed constraints + if (properConstraintsProcessingEnabled) return + + val typeCheckerContext = TypeCheckerContext(c, position) + for ((variable, constraint) in missedConstraints) { + typeCheckerContext.addPossibleNewConstraint(variable, constraint) + } + processConstraints(c, typeCheckerContext, skipProperEqualityConstraints = false) + } + + private fun processConstraints( + c: Context, + typeCheckerContext: TypeCheckerContext, + skipProperEqualityConstraints: Boolean = true + ): MutableList>? { + val properConstraintsProcessingEnabled = + languageVersionSettings.supportsFeature(LanguageFeature.ProperTypeInferenceConstraintsProcessing) + while (typeCheckerContext.hasConstraintsToProcess()) { - for ((typeVariable, constraint) in typeCheckerContext.extractAllConstraints()!!) { - if (c.shouldWeSkipConstraint(typeVariable, constraint)) continue + processGivenConstraints(c, typeCheckerContext, typeCheckerContext.extractAllConstraints()!!) - val constraints = - c.notFixedTypeVariables[typeVariable.freshTypeConstructor(c)] ?: typeCheckerContext.fixedTypeVariable(typeVariable) + val contextOps = c as? ConstraintSystemOperation - // it is important, that we add constraint here(not inside TypeCheckerContext), because inside incorporation we read constraints - val (addedOrNonRedundantExistedConstraint, wasAdded) = constraints.addConstraint(constraint) - val positionFrom = constraint.position.from - val constraintToIncorporate = when { - wasAdded && !constraint.isNullabilityConstraint -> addedOrNonRedundantExistedConstraint - positionFrom is FixVariableConstraintPosition<*> && positionFrom.variable == typeVariable && constraint.kind == EQUALITY -> - addedOrNonRedundantExistedConstraint - else -> null - } + val useIncorrectOptimization = skipProperEqualityConstraints && !properConstraintsProcessingEnabled - if (constraintToIncorporate != null) { - constraintIncorporator.incorporate(typeCheckerContext, typeVariable, constraintToIncorporate) + if (!useIncorrectOptimization) continue + + // Optimization below is wrong and it's going to be removed after finished the corresponding deprecation cycle + val hasProperEqualityConstraintForEachVariable = contextOps != null && c.notFixedTypeVariables.all { typeVariable -> + typeVariable.value.constraints.any { constraint -> + constraint.kind == EQUALITY && contextOps.isProperType(constraint.type) } } - val contextOps = c as? ConstraintSystemOperation - if (!typeCheckerContext.hasConstraintsToProcess() || - (contextOps != null && c.notFixedTypeVariables.all { typeVariable -> - typeVariable.value.constraints.any { constraint -> - constraint.kind == EQUALITY && contextOps.isProperType(constraint.type) - } - }) - ) { - break + if (hasProperEqualityConstraintForEachVariable) return typeCheckerContext.extractAllConstraints() + } + return null + } + + private fun processGivenConstraints( + c: Context, + typeCheckerContext: TypeCheckerContext, + constraintsToProcess: MutableList> + ) { + for ((typeVariable, constraint) in constraintsToProcess) { + if (c.shouldWeSkipConstraint(typeVariable, constraint)) continue + + val constraints = + c.notFixedTypeVariables[typeVariable.freshTypeConstructor(c)] ?: typeCheckerContext.fixedTypeVariable(typeVariable) + + // it is important, that we add constraint here(not inside TypeCheckerContext), because inside incorporation we read constraints + val (addedOrNonRedundantExistedConstraint, wasAdded) = constraints.addConstraint(constraint) + val positionFrom = constraint.position.from + val constraintToIncorporate = when { + wasAdded && !constraint.isNullabilityConstraint -> addedOrNonRedundantExistedConstraint + positionFrom is FixVariableConstraintPosition<*> && positionFrom.variable == typeVariable && constraint.kind == EQUALITY -> + addedOrNonRedundantExistedConstraint + else -> null + } + + if (constraintToIncorporate != null) { + constraintIncorporator.incorporate(typeCheckerContext, typeVariable, constraintToIncorporate) } } } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt index 0bf1dbb0d47..8bcbd1678a3 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt @@ -83,7 +83,8 @@ sealed class ConstraintSystemError(val applicability: CandidateApplicability) class NewConstraintError( val lowerType: KotlinTypeMarker, val upperType: KotlinTypeMarker, - val position: IncorporationConstraintPosition + val position: IncorporationConstraintPosition, + val isWarning: Boolean = false ) : ConstraintSystemError(if (position.from is ReceiverConstraintPosition<*>) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE) class CapturedTypeFromSubtyping( @@ -109,3 +110,5 @@ object LowerPriorityToPreserveCompatibility : ConstraintSystemError(RESOLVED_NEE fun Constraint.isExpectedTypePosition() = position.from is ExpectedTypeConstraintPosition<*> || position.from is DelegatedPropertyConstraintPosition<*> + +fun NewConstraintError.transformToWarning() = NewConstraintError(lowerType, upperType, position, isWarning = true) diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt index bce889f6a9c..d65b13a2f9b 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.types.model.* interface ConstraintStorage { val allTypeVariables: Map val notFixedTypeVariables: Map + val missedConstraints: List>>> val initialConstraints: List val maxTypeDepthFromInitialConstraints: Int val errors: List @@ -45,6 +46,7 @@ interface ConstraintStorage { object Empty : ConstraintStorage { override val allTypeVariables: Map get() = emptyMap() override val notFixedTypeVariables: Map get() = emptyMap() + override val missedConstraints: List>>> get() = emptyList() override val initialConstraints: List get() = emptyList() override val maxTypeDepthFromInitialConstraints: Int get() = 1 override val errors: List get() = emptyList() @@ -143,3 +145,6 @@ fun checkConstraint( ConstraintKind.UPPER -> typeChecker.isSubtypeOf(context, resultType, constraintType) } } + +fun Constraint.replaceType(newType: KotlinTypeMarker) = + Constraint(kind, newType, position, typeHashCode, derivedFrom, isNullabilityConstraint, inputTypePositionBeforeIncorporation) diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt index 63c95717622..2532bf1eec4 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/MutableConstraintStorage.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.model +import org.jetbrains.kotlin.resolve.calls.inference.components.AbstractTypeCheckerContextForConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemUtilContext import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.types.model.* @@ -47,6 +48,8 @@ class MutableVariableWithConstraints private constructor( private var simplifiedConstraints: SmartList? = mutableConstraints + val rawConstraintsCount get() = mutableConstraints.size + // return new actual constraint, if this constraint is new, otherwise return already existed not redundant constraint // the second element of pair is a flag whether a constraint was added in fact fun addConstraint(constraint: Constraint): Pair { @@ -104,8 +107,8 @@ class MutableVariableWithConstraints private constructor( // This method should be used only for transaction in constraint system // shouldRemove should give true only for tail elements - internal fun removeLastConstraints(shouldRemove: (Constraint) -> Boolean) { - mutableConstraints.trimToSize(mutableConstraints.indexOfLast { !shouldRemove(it) } + 1) + internal fun removeLastConstraints(sinceIndex: Int) { + mutableConstraints.trimToSize(sinceIndex) if (simplifiedConstraints !== mutableConstraints) { simplifiedConstraints = null } @@ -212,6 +215,8 @@ class MutableVariableWithConstraints private constructor( internal class MutableConstraintStorage : ConstraintStorage { override val allTypeVariables: MutableMap = LinkedHashMap() override val notFixedTypeVariables: MutableMap = LinkedHashMap() + override val missedConstraints: MutableList>>> = + SmartList() override val initialConstraints: MutableList = SmartList() override var maxTypeDepthFromInitialConstraints: Int = 1 override val errors: MutableList = SmartList() diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index d45d2bf3e2e..9daa033b5d2 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -91,6 +91,13 @@ class NewConstraintSystemImpl( return storage } + override fun addMissedConstraints( + position: IncorporationConstraintPosition, + constraints: MutableList> + ) { + storage.missedConstraints.add(position to constraints) + } + override fun asConstraintSystemCompleterContext() = apply { checkState(State.BUILDING) } override fun asPostponedArgumentsAnalyzerContext() = apply { checkState(State.BUILDING) } @@ -187,6 +194,8 @@ class NewConstraintSystemImpl( val beforeErrorsCount = storage.errors.size val beforeMaxTypeDepthFromInitialConstraints = storage.maxTypeDepthFromInitialConstraints val beforeTypeVariablesTransactionSize = typeVariablesTransaction.size + val beforeMissedConstraintsCount = storage.missedConstraints.size + val beforeConstraintCountByVariables = storage.notFixedTypeVariables.mapValues { it.value.rawConstraintsCount } state = State.TRANSACTION // typeVariablesTransaction is clear @@ -201,13 +210,16 @@ class NewConstraintSystemImpl( } storage.maxTypeDepthFromInitialConstraints = beforeMaxTypeDepthFromInitialConstraints storage.errors.trimToSize(beforeErrorsCount) + storage.missedConstraints.trimToSize(beforeMissedConstraintsCount) val addedInitialConstraints = storage.initialConstraints.subList(beforeInitialConstraintCount, storage.initialConstraints.size) - val shouldRemove = { c: Constraint -> addedInitialConstraints.contains(c.position.initialConstraint) } - for (variableWithConstraint in storage.notFixedTypeVariables.values) { - variableWithConstraint.removeLastConstraints(shouldRemove) + val sinceIndexToRemoveConstraints = + beforeConstraintCountByVariables[variableWithConstraint.typeVariable.freshTypeConstructor()] + if (sinceIndexToRemoveConstraints != null) { + variableWithConstraint.removeLastConstraints(sinceIndexToRemoveConstraints) + } } addedInitialConstraints.clear() // remove constraint from storage.initialConstraints @@ -334,6 +346,13 @@ class NewConstraintSystemImpl( constraintInjector.addInitialEqualityConstraint(this@NewConstraintSystemImpl, variable.defaultType(), resultType, position) + /* + * Checking missed constraint can introduce new type mismatch warnings. + * It's needed to deprecate green code which works only due to incorrect optimization in the constraint injector. + * TODO: remove this code (and `substituteMissedConstraints`) with removing `ProperTypeInferenceConstraintsProcessing` feature + */ + checkMissedConstraints() + val freshTypeConstructor = variable.freshTypeConstructor() val variableWithConstraints = notFixedTypeVariables.remove(freshTypeConstructor) @@ -343,11 +362,47 @@ class NewConstraintSystemImpl( storage.fixedTypeVariables[freshTypeConstructor] = resultType + // Substitute freshly fixed type variable into missed constraints + substituteMissedConstraints() + postponeOnlyInputTypesCheck(variableWithConstraints, resultType) doPostponedComputationsIfAllVariablesAreFixed() } + @OptIn(ExperimentalStdlibApi::class) + private fun checkMissedConstraints() { + val constraintSystem = this@NewConstraintSystemImpl + val errorsByMissedConstraints = buildList { + runTransaction { + for ((position, constraints) in storage.missedConstraints) { + val fixedVariableConstraints = + constraints.filter { (typeVariable, _) -> typeVariable.freshTypeConstructor() in notFixedTypeVariables } + constraintInjector.processMissedConstraints(constraintSystem, position, fixedVariableConstraints) + } + errors.filterIsInstance().forEach(::add) + false + } + } + val constraintErrors = constraintSystem.errors.filterIsInstance() + // Don't report warning if an error on the same call has already been reported + if (constraintErrors.isEmpty() || constraintErrors.all { it.isWarning }) { + errorsByMissedConstraints.forEach { + constraintSystem.addError(it.transformToWarning()) + } + } + } + + private fun substituteMissedConstraints() { + val substitutor = buildCurrentSubstitutor() + for ((_, constraints) in storage.missedConstraints) { + for ((index, variableWithConstraint) in constraints.withIndex()) { + val (typeVariable, constraint) = variableWithConstraint + constraints[index] = typeVariable to constraint.replaceType(substitutor.safeSubstitute(constraint.type)) + } + } + } + private fun ConstraintSystemUtilContext.postponeOnlyInputTypesCheck( variableWithConstraints: MutableVariableWithConstraints?, resultType: KotlinTypeMarker diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt index 6c17765699a..11a592577f3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceCandidate import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError +import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintError import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability.* import org.jetbrains.kotlin.types.TypeConstructor @@ -279,3 +280,6 @@ val KotlinCallDiagnostic.constraintSystemError: ConstraintSystemError? fun ConstraintSystemError.asDiagnostic(): KotlinConstraintSystemDiagnostic = KotlinConstraintSystemDiagnostic(this) fun Collection.asDiagnostics(): List = map(ConstraintSystemError::asDiagnostic) + +fun List.filterErrorDiagnostics() = + filter { it !is KotlinConstraintSystemDiagnostic || (it.error as? NewConstraintError)?.isWarning != true } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt index d2c8123f9eb..7654fa45526 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt @@ -251,7 +251,7 @@ sealed class CallResolutionResult( if (error !is NewConstraintError) return@map it val lowerType = error.lowerType.safeAs()?.unwrap() ?: return@map it val newLowerType = substitutor.safeSubstitute(lowerType.unCapture()) - NewConstraintError(newLowerType, error.upperType, error.position).asDiagnostic() + NewConstraintError(newLowerType, error.upperType, error.position, error.isWarning).asDiagnostic() } } diff --git a/compiler/testData/codegen/box/inference/kt42042.kt b/compiler/testData/codegen/box/inference/kt42042.kt new file mode 100644 index 00000000000..e36882a8a11 --- /dev/null +++ b/compiler/testData/codegen/box/inference/kt42042.kt @@ -0,0 +1,15 @@ +// IGNORE_BACKEND_FIR: JVM_IR + +sealed class Subtype { + abstract fun cast(value: A1): B1 + class Trivial : Subtype() { + override fun cast(value: A2): B2 = value + } +} + +fun unsafeCast(value: A): B { + val proof: Subtype = Subtype.Trivial() + return proof.cast(value) +} + +fun box() = "OK" diff --git a/compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt b/compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt new file mode 100644 index 00000000000..4ae08c0ea3b --- /dev/null +++ b/compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt @@ -0,0 +1,34 @@ +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// FILE: MySettings.java + +import java.util.Collection; +import java.util.Collections; + +public class MySettings< + SS extends MySettings, + PS extends MyComparableSettings, + L extends MySettingsListener + > +{ + public Collection getLinkedProjectsSettings() { + return Collections.emptyList(); + } + + public static MySettings getSettings() { + return new MySettings(); + } +} + +abstract class MyComparableSettings implements Comparable {} +abstract class MySettingsListener {} + +// FILE: test.kt + +fun box(): String { + val a = MySettings.getSettings() + a.getLinkedProjectsSettings() + a.linkedProjectsSettings + + return "OK" +} diff --git a/compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt b/compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt new file mode 100644 index 00000000000..5e9e25e4066 --- /dev/null +++ b/compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt @@ -0,0 +1,13 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS + +fun > createMap(enumClass: Class) {} + +enum class A + +fun box(): String { + val enumClass: Class> = A::class.java as Class> + createMap(enumClass) + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypesInSelfType.fir.kt b/compiler/testData/diagnostics/tests/inference/capturedTypesInSelfType.fir.kt index c6c4582bd8f..1d3d9961b31 100644 --- a/compiler/testData/diagnostics/tests/inference/capturedTypesInSelfType.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/capturedTypesInSelfType.fir.kt @@ -4,5 +4,5 @@ class Foo>(val values: Array) fun foo(x: Array>) { - val y = Foo(x) + val y = Foo(x) } diff --git a/compiler/testData/diagnostics/tests/inference/constraints/manyConstraintsDueToFlexibleRawTypes.fir.kt b/compiler/testData/diagnostics/tests/inference/constraints/manyConstraintsDueToFlexibleRawTypes.fir.kt index 66206f17c5c..4f4dc1ec881 100644 --- a/compiler/testData/diagnostics/tests/inference/constraints/manyConstraintsDueToFlexibleRawTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/constraints/manyConstraintsDueToFlexibleRawTypes.fir.kt @@ -1,4 +1,3 @@ -// !WITH_NEW_INFERENCE // SKIP_JAVAC // FILE: MySettings.java diff --git a/compiler/testData/diagnostics/tests/inference/constraints/manyConstraintsDueToFlexibleRawTypes.kt b/compiler/testData/diagnostics/tests/inference/constraints/manyConstraintsDueToFlexibleRawTypes.kt index d19f12d2a13..4f4dc1ec881 100644 --- a/compiler/testData/diagnostics/tests/inference/constraints/manyConstraintsDueToFlexibleRawTypes.kt +++ b/compiler/testData/diagnostics/tests/inference/constraints/manyConstraintsDueToFlexibleRawTypes.kt @@ -1,4 +1,3 @@ -// !WITH_NEW_INFERENCE // SKIP_JAVAC // FILE: MySettings.java @@ -28,5 +27,5 @@ abstract class MySettingsListener {} fun test() { val a = MySettings.getSettings() a.getLinkedProjectsSettings() - a.linkedProjectsSettings + a.linkedProjectsSettings } diff --git a/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.fir.kt b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.fir.kt index 760bbb2af4e..2e4f8805a8e 100644 --- a/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.fir.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -ProperTypeInferenceConstraintsProcessing // WITH_RUNTIME // !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS @@ -5,5 +6,5 @@ fun > createMap(enumClass: Class) {} fun reproduce() { val enumClass: Class> = "any" as Class> - createMap(enumClass) + createMap(enumClass) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt index 5f5e0635fee..7b74f4b0599 100644 --- a/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt +++ b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -ProperTypeInferenceConstraintsProcessing // WITH_RUNTIME // !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS @@ -5,5 +6,5 @@ fun > createMap(enumClass: Class) {} fun reproduce() { val enumClass: Class> = "any" as Class> - createMap(enumClass) + createMap(>; Enum<*>")!>enumClass) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.fir.kt b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.fir.kt new file mode 100644 index 00000000000..d4dcbdc4f9a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.fir.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +ProperTypeInferenceConstraintsProcessing +// WITH_RUNTIME +// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS + +fun > createMap(enumClass: Class) {} + +fun reproduce() { + val enumClass: Class> = "any" as Class> + createMap(enumClass) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt new file mode 100644 index 00000000000..1016185eab7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +ProperTypeInferenceConstraintsProcessing +// WITH_RUNTIME +// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS + +fun > createMap(enumClass: Class) {} + +fun reproduce() { + val enumClass: Class> = "any" as Class> + createMap(enumClass) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.txt b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.txt new file mode 100644 index 00000000000..fb1669a9433 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.txt @@ -0,0 +1,4 @@ +package + +public fun > createMap(/*0*/ enumClass: java.lang.Class): kotlin.Unit +public fun reproduce(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/typeParameters/kt42042.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/kt42042.fir.kt new file mode 100644 index 00000000000..9048fe31266 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/kt42042.fir.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: -ProperTypeInferenceConstraintsProcessing + +sealed class Subtype { + abstract fun cast(value: A1): B1 + class Trivial : Subtype() { + override fun cast(value: A2): B2 = value + } +} + +fun unsafeCast(value: A): B { + val proof: Subtype = Subtype.Trivial() + return proof.cast(value) +} diff --git a/compiler/testData/diagnostics/tests/typeParameters/kt42042.kt b/compiler/testData/diagnostics/tests/typeParameters/kt42042.kt new file mode 100644 index 00000000000..3d44da71dfe --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/kt42042.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: -ProperTypeInferenceConstraintsProcessing + +sealed class Subtype { + abstract fun cast(value: A1): B1 + class Trivial : Subtype() { + override fun cast(value: A2): B2 = value + } +} + +fun unsafeCast(value: A): B { + val proof: Subtype = Subtype.Trivial() + return proof.cast(value) +} diff --git a/compiler/testData/diagnostics/tests/typeParameters/kt42042.txt b/compiler/testData/diagnostics/tests/typeParameters/kt42042.txt new file mode 100644 index 00000000000..1472e3562e1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/kt42042.txt @@ -0,0 +1,19 @@ +package + +public fun unsafeCast(/*0*/ value: A): B + +public sealed class Subtype { + protected constructor Subtype() + public abstract fun cast(/*0*/ value: A1): B1 + 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 Trivial : Subtype { + public constructor Trivial() + public open override /*1*/ fun cast(/*0*/ value: A2): B2 + 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/typeParameters/kt42042Error.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/kt42042Error.fir.kt new file mode 100644 index 00000000000..f645eae87f9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/kt42042Error.fir.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +ProperTypeInferenceConstraintsProcessing + +sealed class Subtype { + abstract fun cast(value: A1): B1 + class Trivial : Subtype() { + override fun cast(value: A2): B2 = value + } +} + +fun unsafeCast(value: A): B { + val proof: Subtype = Subtype.Trivial() + return proof.cast(value) +} diff --git a/compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt b/compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt new file mode 100644 index 00000000000..79d3cd30e86 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +ProperTypeInferenceConstraintsProcessing + +sealed class Subtype { + abstract fun cast(value: A1): B1 + class Trivial : Subtype() { + override fun cast(value: A2): B2 = value + } +} + +fun unsafeCast(value: A): B { + val proof: Subtype = Subtype.Trivial() + return proof.cast(value) +} diff --git a/compiler/testData/diagnostics/tests/typeParameters/kt42042Error.txt b/compiler/testData/diagnostics/tests/typeParameters/kt42042Error.txt new file mode 100644 index 00000000000..1472e3562e1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/kt42042Error.txt @@ -0,0 +1,19 @@ +package + +public fun unsafeCast(/*0*/ value: A): B + +public sealed class Subtype { + protected constructor Subtype() + public abstract fun cast(/*0*/ value: A1): B1 + 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 Trivial : Subtype { + public constructor Trivial() + public open override /*1*/ fun cast(/*0*/ value: A2): B2 + 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-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 1fe677c7ed7..56f58775d33 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -12593,6 +12593,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfType.kt"); } + @Test + @TestMetadata("violatingUpperBoundForSelfTypeError.kt") + public void testViolatingUpperBoundForSelfTypeError() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/violatingUpperBoundForSelfTypeError.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference") @TestDataPath("$PROJECT_ROOT") @@ -29285,6 +29291,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingOnDelegates.kt"); } + @Test + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042.kt"); + } + + @Test + @TestMetadata("kt42042Error.kt") + public void testKt42042Error() throws Exception { + runTest("compiler/testData/diagnostics/tests/typeParameters/kt42042Error.kt"); + } + @Test @TestMetadata("kt42396.kt") public void testKt42396() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 27ed5f42ccb..3e1953c2ccc 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -17166,6 +17166,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inference/kt39824.kt"); } + @Test + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/codegen/box/inference/kt42042.kt"); + } + @Test @TestMetadata("kt42130.kt") public void testKt42130() throws Exception { @@ -17190,6 +17196,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); } + @Test + @TestMetadata("manyConstraintsDueToFlexibleRawTypes.kt") + public void testManyConstraintsDueToFlexibleRawTypes() throws Exception { + runTest("compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt"); + } + @Test @TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt") public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception { @@ -17274,6 +17286,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt"); } + @Test + @TestMetadata("violatingUpperBoundForSelfType.kt") + public void testViolatingUpperBoundForSelfType() throws Exception { + runTest("compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt"); + } + @Nested @TestMetadata("compiler/testData/codegen/box/inference/builderInference") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 31817b9385d..d160ee91e0c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -17190,6 +17190,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inference/kt39824.kt"); } + @Test + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/codegen/box/inference/kt42042.kt"); + } + @Test @TestMetadata("kt42130.kt") public void testKt42130() throws Exception { @@ -17214,6 +17220,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); } + @Test + @TestMetadata("manyConstraintsDueToFlexibleRawTypes.kt") + public void testManyConstraintsDueToFlexibleRawTypes() throws Exception { + runTest("compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt"); + } + @Test @TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt") public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception { @@ -17298,6 +17310,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt"); } + @Test + @TestMetadata("violatingUpperBoundForSelfType.kt") + public void testViolatingUpperBoundForSelfType() throws Exception { + runTest("compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt"); + } + @Nested @TestMetadata("compiler/testData/codegen/box/inference/builderInference") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index c3d50ede40a..c23f4c737f6 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -14211,6 +14211,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inference/kt39824.kt"); } + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/codegen/box/inference/kt42042.kt"); + } + @TestMetadata("kt42130.kt") public void testKt42130() throws Exception { runTest("compiler/testData/codegen/box/inference/kt42130.kt"); @@ -14231,6 +14236,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); } + @TestMetadata("manyConstraintsDueToFlexibleRawTypes.kt") + public void testManyConstraintsDueToFlexibleRawTypes() throws Exception { + runTest("compiler/testData/codegen/box/inference/manyConstraintsDueToFlexibleRawTypes.kt"); + } + @TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt") public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception { runTest("compiler/testData/codegen/box/inference/manyFlexibleTypeParametersFromJavaAndConversions.kt"); @@ -14301,6 +14311,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt"); } + @TestMetadata("violatingUpperBoundForSelfType.kt") + public void testViolatingUpperBoundForSelfType() throws Exception { + runTest("compiler/testData/codegen/box/inference/violatingUpperBoundForSelfType.kt"); + } + @TestMetadata("compiler/testData/codegen/box/inference/builderInference") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index b6f1dbc96fb..71e788880da 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -207,6 +207,7 @@ enum class LanguageFeature( AbstractClassMemberNotImplementedWithIntermediateAbstractClass(KOTLIN_1_6, kind = BUG_FIX), SuspendFunctionAsSupertype(KOTLIN_1_6), + ProperTypeInferenceConstraintsProcessing(KOTLIN_1_6, kind = BUG_FIX), // Temporarily disabled, see KT-27084/KT-22379 SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX), diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 9882a9fafe2..8a52d637923 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -12485,6 +12485,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/inference/kt39824.kt"); } + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/codegen/box/inference/kt42042.kt"); + } + @TestMetadata("kt42130.kt") public void testKt42130() throws Exception { runTest("compiler/testData/codegen/box/inference/kt42130.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index f34764eb6b6..0bae74acc17 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -11896,6 +11896,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inference/kt39824.kt"); } + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/codegen/box/inference/kt42042.kt"); + } + @TestMetadata("kt42130.kt") public void testKt42130() throws Exception { runTest("compiler/testData/codegen/box/inference/kt42130.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 37a11816b3a..355caba3f6c 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -11961,6 +11961,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inference/kt39824.kt"); } + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/codegen/box/inference/kt42042.kt"); + } + @TestMetadata("kt42130.kt") public void testKt42130() throws Exception { runTest("compiler/testData/codegen/box/inference/kt42130.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 82c78baefe3..9f552e67f27 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -6311,6 +6311,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/inference/kt38664.kt"); } + @TestMetadata("kt42042.kt") + public void testKt42042() throws Exception { + runTest("compiler/testData/codegen/box/inference/kt42042.kt"); + } + @TestMetadata("kt42130.kt") public void testKt42130() throws Exception { runTest("compiler/testData/codegen/box/inference/kt42130.kt");