Introduce warnings reporting by missed constraints because of incorrect optimization in the constraints processor
This commit is contained in:
+18
@@ -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 {
|
||||
|
||||
+48
@@ -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 {
|
||||
|
||||
+18
@@ -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")
|
||||
|
||||
@@ -155,6 +155,7 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<KtTypeProjection> PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = DiagnosticFactory0.create(ERROR, VARIANCE_IN_PROJECTION);
|
||||
DiagnosticFactory2<KtTypeReference, KotlinType, KotlinType> UPPER_BOUND_VIOLATED = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<KtTypeReference, KotlinType, KotlinType> UPPER_BOUND_VIOLATED_WARNING = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory0<KtNullableType> REDUNDANT_NULLABLE = DiagnosticFactory0.create(WARNING, NULLABLE_TYPE);
|
||||
DiagnosticFactory0<KtDefinitelyNotNullType> DEFINITELY_NOT_NULLABLE_NOT_APPLICABLE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtNullableType> NULLABLE_ON_DEFINITELY_NOT_NULLABLE = DiagnosticFactory0.create(ERROR);
|
||||
@@ -1080,6 +1081,7 @@ public interface Errors {
|
||||
// Type mismatch
|
||||
|
||||
DiagnosticFactory2<KtExpression, KotlinType, KotlinType> TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<KtExpression, KotlinType, KotlinType> TYPE_MISMATCH_WARNING = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory1<KtElement, KotlinType> TYPE_MISMATCH_DUE_TO_EQUALS_LAMBDA_IN_FUN = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtElement, TypeMismatchDueToTypeProjectionsData> TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<KtElement, CallableDescriptor, KotlinType> MEMBER_PROJECTED_OUT = DiagnosticFactory2.create(ERROR);
|
||||
@@ -1091,6 +1093,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtWhenConditionInRange> TYPE_MISMATCH_IN_RANGE = DiagnosticFactory0.create(ERROR, WHEN_CONDITION_IN_RANGE);
|
||||
|
||||
DiagnosticFactory1<KtParameter, KotlinType> EXPECTED_PARAMETER_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtParameter, KotlinType> EXPECTED_PARAMETER_TYPE_MISMATCH_WARNING = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory2<KtFunction, Integer, List<KotlinType>> EXPECTED_PARAMETERS_NUMBER_MISMATCH =
|
||||
DiagnosticFactory2.create(ERROR, FUNCTION_PARAMETERS);
|
||||
|
||||
|
||||
+3
@@ -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");
|
||||
|
||||
+10
-5
@@ -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<LambdaKotlinCallArgument>()?.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<PSIKotlinCall>()?.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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<D>(singleCandidate, diagnostics).also {
|
||||
tracingStrategy.unresolvedReferenceWrongReceiver(trace, listOf(it))
|
||||
|
||||
+3
@@ -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<TypeConstructorMarker>
|
||||
|
||||
fun addOtherSystem(otherSystem: ConstraintStorage)
|
||||
|
||||
val errors: List<ConstraintSystemError>
|
||||
}
|
||||
|
||||
interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
||||
|
||||
+80
-27
@@ -34,6 +34,11 @@ class ConstraintInjector(
|
||||
|
||||
fun addInitialConstraint(initialConstraint: InitialConstraint)
|
||||
fun addError(error: ConstraintSystemError)
|
||||
|
||||
fun addMissedConstraints(
|
||||
position: IncorporationConstraintPosition,
|
||||
constraints: MutableList<Pair<TypeVariableMarker, Constraint>>
|
||||
)
|
||||
}
|
||||
|
||||
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<Pair<TypeVariableMarker, Constraint>>
|
||||
) {
|
||||
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<Pair<TypeVariableMarker, Constraint>>? {
|
||||
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<Pair<TypeVariableMarker, Constraint>>
|
||||
) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -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)
|
||||
|
||||
+5
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.types.model.*
|
||||
interface ConstraintStorage {
|
||||
val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
|
||||
val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
|
||||
val missedConstraints: List<Pair<IncorporationConstraintPosition, List<Pair<TypeVariableMarker, Constraint>>>>
|
||||
val initialConstraints: List<InitialConstraint>
|
||||
val maxTypeDepthFromInitialConstraints: Int
|
||||
val errors: List<ConstraintSystemError>
|
||||
@@ -45,6 +46,7 @@ interface ConstraintStorage {
|
||||
object Empty : ConstraintStorage {
|
||||
override val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker> get() = emptyMap()
|
||||
override val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints> get() = emptyMap()
|
||||
override val missedConstraints: List<Pair<IncorporationConstraintPosition, List<Pair<TypeVariableMarker, Constraint>>>> get() = emptyList()
|
||||
override val initialConstraints: List<InitialConstraint> get() = emptyList()
|
||||
override val maxTypeDepthFromInitialConstraints: Int get() = 1
|
||||
override val errors: List<ConstraintSystemError> 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)
|
||||
|
||||
+7
-2
@@ -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<Constraint>? = 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<Constraint, Boolean> {
|
||||
@@ -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<TypeConstructorMarker, TypeVariableMarker> = LinkedHashMap()
|
||||
override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints> = LinkedHashMap()
|
||||
override val missedConstraints: MutableList<Pair<IncorporationConstraintPosition, MutableList<Pair<TypeVariableMarker, Constraint>>>> =
|
||||
SmartList()
|
||||
override val initialConstraints: MutableList<InitialConstraint> = SmartList()
|
||||
override var maxTypeDepthFromInitialConstraints: Int = 1
|
||||
override val errors: MutableList<ConstraintSystemError> = SmartList()
|
||||
|
||||
+58
-3
@@ -91,6 +91,13 @@ class NewConstraintSystemImpl(
|
||||
return storage
|
||||
}
|
||||
|
||||
override fun addMissedConstraints(
|
||||
position: IncorporationConstraintPosition,
|
||||
constraints: MutableList<Pair<TypeVariableMarker, Constraint>>
|
||||
) {
|
||||
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<NewConstraintError>().forEach(::add)
|
||||
false
|
||||
}
|
||||
}
|
||||
val constraintErrors = constraintSystem.errors.filterIsInstance<NewConstraintError>()
|
||||
// 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
|
||||
|
||||
+4
@@ -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<ConstraintSystemError>.asDiagnostics(): List<KotlinConstraintSystemDiagnostic> = map(ConstraintSystemError::asDiagnostic)
|
||||
|
||||
fun List<KotlinCallDiagnostic>.filterErrorDiagnostics() =
|
||||
filter { it !is KotlinConstraintSystemDiagnostic || (it.error as? NewConstraintError)?.isWarning != true }
|
||||
@@ -251,7 +251,7 @@ sealed class CallResolutionResult(
|
||||
if (error !is NewConstraintError) return@map it
|
||||
val lowerType = error.lowerType.safeAs<KotlinType>()?.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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
sealed class Subtype<A1, B1> {
|
||||
abstract fun cast(value: A1): B1
|
||||
class Trivial<A2 : B2, B2> : Subtype<A2, B2>() {
|
||||
override fun cast(value: A2): B2 = value
|
||||
}
|
||||
}
|
||||
|
||||
fun <A, B> unsafeCast(value: A): B {
|
||||
val proof: Subtype<A, B> = Subtype.Trivial()
|
||||
return proof.cast(value)
|
||||
}
|
||||
|
||||
fun box() = "OK"
|
||||
+34
@@ -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<SS, PS, L>,
|
||||
PS extends MyComparableSettings,
|
||||
L extends MySettingsListener<PS>
|
||||
>
|
||||
{
|
||||
public Collection<PS> getLinkedProjectsSettings() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public static MySettings getSettings() {
|
||||
return new MySettings();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class MyComparableSettings implements Comparable<MyComparableSettings> {}
|
||||
abstract class MySettingsListener<S extends MyComparableSettings> {}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
fun box(): String {
|
||||
val a = MySettings.getSettings()
|
||||
a.getLinkedProjectsSettings()
|
||||
a.linkedProjectsSettings
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS
|
||||
|
||||
fun <E : Enum<E>> createMap(enumClass: Class<E>) {}
|
||||
|
||||
enum class A
|
||||
|
||||
fun box(): String {
|
||||
val enumClass: Class<Enum<*>> = A::class.java as Class<Enum<*>>
|
||||
createMap(enumClass)
|
||||
return "OK"
|
||||
}
|
||||
+1
-1
@@ -4,5 +4,5 @@
|
||||
class Foo<T : Enum<T>>(val values: Array<T>)
|
||||
|
||||
fun foo(x: Array<out Enum<*>>) {
|
||||
val y = Foo(<!ARGUMENT_TYPE_MISMATCH!>x<!>)
|
||||
val y = Foo(<!ARGUMENT_TYPE_MISMATCH{LT}!>x<!>)
|
||||
}
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// SKIP_JAVAC
|
||||
|
||||
// FILE: MySettings.java
|
||||
|
||||
Vendored
+1
-2
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// SKIP_JAVAC
|
||||
|
||||
// FILE: MySettings.java
|
||||
@@ -28,5 +27,5 @@ abstract class MySettingsListener<S extends MyComparableSettings> {}
|
||||
fun test() {
|
||||
val a = MySettings.getSettings()
|
||||
a.getLinkedProjectsSettings()
|
||||
a.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE{OI}, TYPE_INFERENCE_UPPER_BOUND_VIOLATED{OI}!>linkedProjectsSettings<!>
|
||||
a.linkedProjectsSettings
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// !LANGUAGE: -ProperTypeInferenceConstraintsProcessing
|
||||
// WITH_RUNTIME
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS
|
||||
|
||||
@@ -5,5 +6,5 @@ fun <E : Enum<E>> createMap(enumClass: Class<E>) {}
|
||||
|
||||
fun reproduce() {
|
||||
val enumClass: Class<Enum<*>> = "any" as Class<Enum<*>>
|
||||
createMap(<!ARGUMENT_TYPE_MISMATCH!>enumClass<!>)
|
||||
createMap(enumClass)
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// !LANGUAGE: -ProperTypeInferenceConstraintsProcessing
|
||||
// WITH_RUNTIME
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS
|
||||
|
||||
@@ -5,5 +6,5 @@ fun <E : Enum<E>> createMap(enumClass: Class<E>) {}
|
||||
|
||||
fun reproduce() {
|
||||
val enumClass: Class<Enum<*>> = "any" as Class<Enum<*>>
|
||||
createMap(enumClass)
|
||||
createMap(<!TYPE_MISMATCH_WARNING("Enum<in Enum<*>>; Enum<*>")!>enumClass<!>)
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// !LANGUAGE: +ProperTypeInferenceConstraintsProcessing
|
||||
// WITH_RUNTIME
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS
|
||||
|
||||
fun <E : Enum<E>> createMap(enumClass: Class<E>) {}
|
||||
|
||||
fun reproduce() {
|
||||
val enumClass: Class<Enum<*>> = "any" as Class<Enum<*>>
|
||||
createMap(<!ARGUMENT_TYPE_MISMATCH!>enumClass<!>)
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// !LANGUAGE: +ProperTypeInferenceConstraintsProcessing
|
||||
// WITH_RUNTIME
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS
|
||||
|
||||
fun <E : Enum<E>> createMap(enumClass: Class<E>) {}
|
||||
|
||||
fun reproduce() {
|
||||
val enumClass: Class<Enum<*>> = "any" as Class<Enum<*>>
|
||||
createMap(<!TYPE_MISMATCH, TYPE_MISMATCH!>enumClass<!>)
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ E : kotlin.Enum<E>> createMap(/*0*/ enumClass: java.lang.Class<E>): kotlin.Unit
|
||||
public fun reproduce(): kotlin.Unit
|
||||
@@ -0,0 +1,13 @@
|
||||
// !LANGUAGE: -ProperTypeInferenceConstraintsProcessing
|
||||
|
||||
sealed class Subtype<A1, B1> {
|
||||
abstract fun cast(value: A1): B1
|
||||
class Trivial<A2 : B2, B2> : Subtype<A2, B2>() {
|
||||
override fun cast(value: A2): B2 = value
|
||||
}
|
||||
}
|
||||
|
||||
fun <A, B> unsafeCast(value: A): B {
|
||||
val proof: Subtype<A, B> = <!UPPER_BOUND_VIOLATED!>Subtype.Trivial()<!>
|
||||
return proof.cast(value)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// !LANGUAGE: -ProperTypeInferenceConstraintsProcessing
|
||||
|
||||
sealed class Subtype<A1, B1> {
|
||||
abstract fun cast(value: A1): B1
|
||||
class Trivial<A2 : B2, B2> : Subtype<A2, B2>() {
|
||||
override fun cast(value: A2): B2 = value
|
||||
}
|
||||
}
|
||||
|
||||
fun <A, B> unsafeCast(value: A): B {
|
||||
val proof: Subtype<A, B> = Subtype.<!TYPE_MISMATCH_WARNING("B; A")!>Trivial()<!>
|
||||
return proof.cast(value)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ A, /*1*/ B> unsafeCast(/*0*/ value: A): B
|
||||
|
||||
public sealed class Subtype</*0*/ A1, /*1*/ B1> {
|
||||
protected constructor Subtype</*0*/ A1, /*1*/ B1>()
|
||||
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</*0*/ A2 : B2, /*1*/ B2> : Subtype<A2, B2> {
|
||||
public constructor Trivial</*0*/ A2 : B2, /*1*/ B2>()
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// !LANGUAGE: +ProperTypeInferenceConstraintsProcessing
|
||||
|
||||
sealed class Subtype<A1, B1> {
|
||||
abstract fun cast(value: A1): B1
|
||||
class Trivial<A2 : B2, B2> : Subtype<A2, B2>() {
|
||||
override fun cast(value: A2): B2 = value
|
||||
}
|
||||
}
|
||||
|
||||
fun <A, B> unsafeCast(value: A): B {
|
||||
val proof: Subtype<A, B> = <!UPPER_BOUND_VIOLATED!>Subtype.Trivial()<!>
|
||||
return proof.cast(value)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// !LANGUAGE: +ProperTypeInferenceConstraintsProcessing
|
||||
|
||||
sealed class Subtype<A1, B1> {
|
||||
abstract fun cast(value: A1): B1
|
||||
class Trivial<A2 : B2, B2> : Subtype<A2, B2>() {
|
||||
override fun cast(value: A2): B2 = value
|
||||
}
|
||||
}
|
||||
|
||||
fun <A, B> unsafeCast(value: A): B {
|
||||
val proof: Subtype<A, B> = Subtype.<!TYPE_MISMATCH, TYPE_MISMATCH!>Trivial()<!>
|
||||
return proof.cast(value)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ A, /*1*/ B> unsafeCast(/*0*/ value: A): B
|
||||
|
||||
public sealed class Subtype</*0*/ A1, /*1*/ B1> {
|
||||
protected constructor Subtype</*0*/ A1, /*1*/ B1>()
|
||||
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</*0*/ A2 : B2, /*1*/ B2> : Subtype<A2, B2> {
|
||||
public constructor Trivial</*0*/ A2 : B2, /*1*/ B2>()
|
||||
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
|
||||
}
|
||||
}
|
||||
Generated
+18
@@ -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 {
|
||||
|
||||
+18
@@ -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")
|
||||
|
||||
+18
@@ -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")
|
||||
|
||||
+15
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user