Add expected type constraints in a builder inference call
This commit is contained in:
+16
@@ -12686,6 +12686,22 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class AddingConstraints {
|
||||
@Test
|
||||
public void testAllFilesPresentInAddingConstraints() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bySpecifiedReturnType.kt")
|
||||
public void testBySpecifiedReturnType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints/bySpecifiedReturnType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+16
@@ -12686,6 +12686,22 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class AddingConstraints {
|
||||
@Test
|
||||
public void testAllFilesPresentInAddingConstraints() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bySpecifiedReturnType.kt")
|
||||
public void testBySpecifiedReturnType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints/bySpecifiedReturnType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+8
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.reportTrailingLambdaErrorOr
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceExpectedTypeConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
@@ -396,6 +397,13 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
}
|
||||
}
|
||||
|
||||
(position as? BuilderInferenceExpectedTypeConstraintPosition)?.let {
|
||||
val inferredType =
|
||||
if (!error.lowerKotlinType.isNullableNothing()) error.lowerKotlinType
|
||||
else error.upperKotlinType.makeNullable()
|
||||
trace.report(TYPE_MISMATCH.on(it.topLevelCall, error.upperKotlinType, inferredType))
|
||||
}
|
||||
|
||||
(position as? ExplicitTypeParameterConstraintPositionImpl)?.let {
|
||||
val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference
|
||||
val diagnosticFactory = if (error.isWarning) UPPER_BOUND_VIOLATED_WARNING else UPPER_BOUND_VIOLATED
|
||||
|
||||
+19
@@ -324,6 +324,23 @@ class BuilderInferenceSession(
|
||||
return introducedConstraint
|
||||
}
|
||||
|
||||
fun addExpectedTypeConstraint(
|
||||
callExpression: KtExpression,
|
||||
a: KotlinType,
|
||||
b: KotlinType
|
||||
) {
|
||||
val nonFixedToVariablesSubstitutor: NewTypeSubstitutor = createNonFixedTypeToVariableSubstitutor()
|
||||
val (lower, upper) = substituteNotFixedVariables(a, b, nonFixedToVariablesSubstitutor)
|
||||
val position = BuilderInferenceExpectedTypeConstraintPosition(callExpression)
|
||||
val currentSubstitutor = commonSystem.buildCurrentSubstitutor()
|
||||
|
||||
commonSystem.addSubtypeConstraint(
|
||||
currentSubstitutor.safeSubstitute(commonSystem.typeSystemContext, lower),
|
||||
currentSubstitutor.safeSubstitute(commonSystem.typeSystemContext, upper),
|
||||
position
|
||||
)
|
||||
}
|
||||
|
||||
private fun substituteNotFixedVariables(
|
||||
lowerType: KotlinType,
|
||||
upperType: KotlinType,
|
||||
@@ -530,3 +547,5 @@ class ComposedSubstitutor(val left: NewTypeSubstitutor, val right: NewTypeSubsti
|
||||
|
||||
override val isEmpty: Boolean get() = left.isEmpty && right.isEmpty
|
||||
}
|
||||
|
||||
class BuilderInferenceExpectedTypeConstraintPosition(callElement: KtExpression) : ExpectedTypeConstraintPosition<KtExpression>(callElement)
|
||||
|
||||
@@ -35,15 +35,14 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.*;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.KotlinTypeKt;
|
||||
import org.jetbrains.kotlin.types.TypeConstructor;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -287,6 +286,11 @@ public class DataFlowAnalyzer {
|
||||
@NotNull Ref<Boolean> hasError,
|
||||
boolean reportErrorForTypeMismatch
|
||||
) {
|
||||
if (!noExpectedType(c.expectedType) && TypeUtilsKt.contains(expressionType, (type) -> type instanceof StubType)) {
|
||||
if (c.inferenceSession instanceof BuilderInferenceSession) {
|
||||
((BuilderInferenceSession) c.inferenceSession).addExpectedTypeConstraint(expression, expressionType, c.expectedType);
|
||||
}
|
||||
}
|
||||
if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() ||
|
||||
kotlinTypeChecker.isSubtypeOf(expressionType, c.expectedType)) {
|
||||
return expressionType;
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface A {
|
||||
fun foo(): MutableList<String>
|
||||
}
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
fun main() {
|
||||
buildList {
|
||||
add(3)
|
||||
object : A {
|
||||
override fun foo(): MutableList<String> = this@buildList
|
||||
}
|
||||
}
|
||||
buildList {
|
||||
add(3)
|
||||
val x: String = get(0)
|
||||
}
|
||||
buildList {
|
||||
add("3")
|
||||
val x: MutableList<Int> = this@buildList
|
||||
}
|
||||
buildList {
|
||||
val y: CharSequence = ""
|
||||
add(y)
|
||||
val x: MutableList<String> = this@buildList
|
||||
}
|
||||
buildList {
|
||||
add("")
|
||||
val x: MutableList<CharSequence> = this@buildList
|
||||
}
|
||||
buildList {
|
||||
add("")
|
||||
val x: StringBuilder = get(0)
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface A {
|
||||
fun foo(): MutableList<String>
|
||||
}
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
fun main() {
|
||||
buildList {
|
||||
add(<!CONSTANT_EXPECTED_TYPE_MISMATCH, CONSTANT_EXPECTED_TYPE_MISMATCH!>3<!>)
|
||||
object : A {
|
||||
override fun foo(): MutableList<String> = this@buildList
|
||||
}
|
||||
}
|
||||
buildList {
|
||||
add(<!CONSTANT_EXPECTED_TYPE_MISMATCH, CONSTANT_EXPECTED_TYPE_MISMATCH!>3<!>)
|
||||
val x: String = get(0)
|
||||
}
|
||||
buildList {
|
||||
add(<!TYPE_MISMATCH, TYPE_MISMATCH!>"3"<!>)
|
||||
val x: MutableList<Int> = this@buildList
|
||||
}
|
||||
buildList {
|
||||
val y: CharSequence = ""
|
||||
add(<!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>y<!>)
|
||||
val x: MutableList<String> = this@buildList
|
||||
}
|
||||
buildList {
|
||||
add("")
|
||||
val x: MutableList<CharSequence> = this@buildList
|
||||
}
|
||||
buildList {
|
||||
add(<!TYPE_MISMATCH, TYPE_MISMATCH!>""<!>)
|
||||
val x: StringBuilder = get(0)
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
@kotlin.ExperimentalStdlibApi public fun main(): kotlin.Unit
|
||||
|
||||
public interface A {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(): kotlin.collections.MutableList<kotlin.String>
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Generated
+16
@@ -12692,6 +12692,22 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class AddingConstraints {
|
||||
@Test
|
||||
public void testAllFilesPresentInAddingConstraints() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bySpecifiedReturnType.kt")
|
||||
public void testBySpecifiedReturnType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/addingConstraints/bySpecifiedReturnType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
Reference in New Issue
Block a user