Resolution: extract projections from captured flexible type properly
#KT-54100 Fixed Related to KT-54196, KT-54198
This commit is contained in:
committed by
teamcity
parent
8517249776
commit
e9bb0f4fda
+6
@@ -35694,6 +35694,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInferenceWithRestrictions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVariableShouldNotBeFixed.kt")
|
||||
public void testTypeVariableShouldNotBeFixed() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/typeVariableShouldNotBeFixed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtension.kt")
|
||||
public void testUseInferenceInformationFromExtension() throws Exception {
|
||||
|
||||
+6
@@ -35694,6 +35694,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInferenceWithRestrictions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVariableShouldNotBeFixed.kt")
|
||||
public void testTypeVariableShouldNotBeFixed() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/typeVariableShouldNotBeFixed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtension.kt")
|
||||
public void testUseInferenceInformationFromExtension() throws Exception {
|
||||
|
||||
+6
@@ -35694,6 +35694,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInferenceWithRestrictions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVariableShouldNotBeFixed.kt")
|
||||
public void testTypeVariableShouldNotBeFixed() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/typeVariableShouldNotBeFixed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtension.kt")
|
||||
public void testUseInferenceInformationFromExtension() throws Exception {
|
||||
|
||||
+8
-2
@@ -204,9 +204,15 @@ class VariableFixationFinder(
|
||||
inline fun TypeSystemInferenceExtensionContext.isProperTypeForFixation(type: KotlinTypeMarker, isProper: (KotlinTypeMarker) -> Boolean) =
|
||||
isProper(type) && extractProjectionsForAllCapturedTypes(type).all(isProper)
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
fun TypeSystemInferenceExtensionContext.extractProjectionsForAllCapturedTypes(baseType: KotlinTypeMarker): Set<KotlinTypeMarker> {
|
||||
val simpleBaseType = baseType.asSimpleType()
|
||||
if (baseType.isFlexible()) {
|
||||
val flexibleType = baseType.asFlexibleType()!!
|
||||
return buildSet {
|
||||
addAll(extractProjectionsForAllCapturedTypes(flexibleType.lowerBound()))
|
||||
addAll(extractProjectionsForAllCapturedTypes(flexibleType.upperBound()))
|
||||
}
|
||||
}
|
||||
val simpleBaseType = baseType.asSimpleType()?.originalIfDefinitelyNotNullable()
|
||||
|
||||
return buildSet {
|
||||
val projectionType = if (simpleBaseType is CapturedTypeMarker) {
|
||||
|
||||
+1
-1
@@ -289,7 +289,7 @@ class NewConstraintSystemImpl(
|
||||
private fun isProperTypeImpl(type: KotlinTypeMarker): Boolean =
|
||||
!type.contains {
|
||||
val capturedType = it.asSimpleType()?.asCapturedType()
|
||||
// TODO: change NewCapturedType to markered one for FE-IR
|
||||
|
||||
val typeToCheck = if (capturedType is CapturedTypeMarker && capturedType.captureStatus() == CaptureStatus.FROM_EXPRESSION)
|
||||
capturedType.typeConstructorProjection().takeUnless { projection -> projection.isStarProjection() }?.getType()
|
||||
else
|
||||
|
||||
+2
-1
@@ -117,7 +117,8 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker {
|
||||
TypeProjectionImpl(typeConstructor.projection.projectionKind, substitutedInnerType),
|
||||
typeParameter = typeConstructor.typeParameter
|
||||
).also { it.initializeSupertypes(substitutedSuperTypes) },
|
||||
lowerType = if (capturedType.lowerType != null) substitutedInnerType else null
|
||||
lowerType = if (capturedType.lowerType != null) substitutedInnerType else null,
|
||||
isMarkedNullable = type.isMarkedNullable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
// FILE: spr/Expr.java
|
||||
package spr;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface Exec<E> {
|
||||
boolean run(@NotNull Model model, @NotNull Processor<? super E> params);
|
||||
}
|
||||
|
||||
// FILE: spr/foo.kt
|
||||
package spr
|
||||
|
||||
open class Processor<P> {
|
||||
fun process(t: P): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class Model
|
||||
|
||||
fun <C> context(p: Processor<in C>, exec: Exec<C>) {}
|
||||
|
||||
fun <M> materialize(): Processor<M> = TODO()
|
||||
|
||||
private fun foo(model: Model) {
|
||||
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER("M")!>materialize<!>().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER("T")!>apply<!> {
|
||||
context(
|
||||
this,
|
||||
Exec { m, p -> p.process(m) } // Note: Builder inference
|
||||
)
|
||||
}
|
||||
}
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
// FILE: spr/Expr.java
|
||||
package spr;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface Exec<E> {
|
||||
boolean run(@NotNull Model model, @NotNull Processor<? super E> params);
|
||||
}
|
||||
|
||||
// FILE: spr/foo.kt
|
||||
package spr
|
||||
|
||||
open class Processor<P> {
|
||||
fun process(t: P): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class Model
|
||||
|
||||
fun <C> context(p: Processor<in C>, exec: Exec<C>) {}
|
||||
|
||||
fun <M> materialize(): Processor<M> = TODO()
|
||||
|
||||
private fun foo(model: Model) {
|
||||
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materialize<!>().<!DEBUG_INFO_MISSING_UNRESOLVED!>apply<!> {
|
||||
context(
|
||||
<!NO_THIS!>this<!>,
|
||||
Exec { m, p -> p.process(m) } // Note: Builder inference
|
||||
)
|
||||
}
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
package
|
||||
|
||||
package spr {
|
||||
public fun </*0*/ C> context(/*0*/ p: spr.Processor<in C>, /*1*/ exec: spr.Exec<C>): kotlin.Unit
|
||||
private fun foo(/*0*/ model: spr.Model): kotlin.Unit
|
||||
public fun </*0*/ M> materialize(): spr.Processor<M>
|
||||
|
||||
public interface Exec</*0*/ E : kotlin.Any!> {
|
||||
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 abstract fun run(/*0*/ @org.jetbrains.annotations.NotNull model: spr.Model, /*1*/ @org.jetbrains.annotations.NotNull params: spr.Processor<in E!>): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Model {
|
||||
public constructor Model()
|
||||
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 open class Processor</*0*/ P> {
|
||||
public constructor Processor</*0*/ P>()
|
||||
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 final fun process(/*0*/ t: P): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
Generated
+6
@@ -35784,6 +35784,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInferenceWithRestrictions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeVariableShouldNotBeFixed.kt")
|
||||
public void testTypeVariableShouldNotBeFixed() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/typeVariableShouldNotBeFixed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtension.kt")
|
||||
public void testUseInferenceInformationFromExtension() throws Exception {
|
||||
|
||||
@@ -122,6 +122,7 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
}
|
||||
|
||||
override fun CapturedTypeMarker.lowerType(): KotlinTypeMarker? {
|
||||
// TODO: https://youtrack.jetbrains.com/issue/KT-54196 (old captured type here)
|
||||
require(this is NewCapturedType, this::errorMessage)
|
||||
return this.lowerType
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ class FlexibleTypeImpl(lowerBound: SimpleType, upperBound: SimpleType) : Flexibl
|
||||
|
||||
assert(!lowerBound.isFlexible()) { "Lower bound of a flexible type can not be flexible: $lowerBound" }
|
||||
assert(!upperBound.isFlexible()) { "Upper bound of a flexible type can not be flexible: $upperBound" }
|
||||
// TODO: https://youtrack.jetbrains.com/issue/KT-54198 (two captured types)
|
||||
assert(lowerBound != upperBound) { "Lower and upper bounds are equal: $lowerBound == $upperBound" }
|
||||
assert(KotlinTypeChecker.DEFAULT.isSubtypeOf(lowerBound, upperBound)) {
|
||||
"Lower bound $lowerBound of a flexible type must be a subtype of the upper bound $upperBound"
|
||||
|
||||
Reference in New Issue
Block a user