NI: avoid creating useless captured types during incorporation
^KT-37546 Fixed
This commit is contained in:
Vendored
+1
-1
@@ -6,5 +6,5 @@ FILE: definetelyNotNullForTypeParameter.kt
|
|||||||
}
|
}
|
||||||
public final fun <F : R|kotlin/Any|> foo(computable: R|Out<F?>|): R|kotlin/Unit|
|
public final fun <F : R|kotlin/Any|> foo(computable: R|Out<F?>|): R|kotlin/Unit|
|
||||||
public final fun <T : R|kotlin/Any|> bar(computable: R|Out<T?>|): R|kotlin/Unit| {
|
public final fun <T : R|kotlin/Any|> bar(computable: R|Out<T?>|): R|kotlin/Unit| {
|
||||||
R|/foo|<R|T?!!|>(R|/id|<R|T?|>(R|<local>/computable|))
|
R|/foo|<R|T|>(R|/id|<R|T?|>(R|<local>/computable|))
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -10278,6 +10278,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/approximateBeforeFixation.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/approximateBeforeFixation.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("avoidCreatingUselessCapturedTypes.kt")
|
||||||
|
public void testAvoidCreatingUselessCapturedTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/avoidCreatingUselessCapturedTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("cannotCaptureInProjection.kt")
|
@TestMetadata("cannotCaptureInProjection.kt")
|
||||||
public void testCannotCaptureInProjection() throws Exception {
|
public void testCannotCaptureInProjection() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/cannotCaptureInProjection.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/cannotCaptureInProjection.kt");
|
||||||
|
|||||||
+74
-30
@@ -113,50 +113,94 @@ class ConstraintIncorporator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Context.approximateIfNeededAndAddNewConstraint(
|
||||||
|
baseConstraint: Constraint,
|
||||||
|
type: KotlinTypeMarker,
|
||||||
|
targetVariable: TypeVariableMarker,
|
||||||
|
otherVariable: TypeVariableMarker,
|
||||||
|
otherConstraint: Constraint,
|
||||||
|
needApproximation: Boolean = true
|
||||||
|
) {
|
||||||
|
val typeWithSubstitution = baseConstraint.type.substitute(this, otherVariable, type)
|
||||||
|
val prepareType = { toSuper: Boolean ->
|
||||||
|
if (needApproximation) approximateCapturedTypes(typeWithSubstitution, toSuper) else typeWithSubstitution
|
||||||
|
}
|
||||||
|
|
||||||
|
when (baseConstraint.kind) {
|
||||||
|
ConstraintKind.EQUALITY -> {
|
||||||
|
addNewConstraint(targetVariable, baseConstraint, otherVariable, otherConstraint, typeWithSubstitution, isSubtype = false)
|
||||||
|
addNewConstraint(targetVariable, baseConstraint, otherVariable, otherConstraint, typeWithSubstitution, isSubtype = true)
|
||||||
|
}
|
||||||
|
ConstraintKind.UPPER -> {
|
||||||
|
addNewConstraint(targetVariable, baseConstraint, otherVariable, otherConstraint, prepareType(true), isSubtype = false)
|
||||||
|
}
|
||||||
|
ConstraintKind.LOWER -> {
|
||||||
|
addNewConstraint(targetVariable, baseConstraint, otherVariable, otherConstraint, prepareType(false), isSubtype = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun Context.generateNewConstraint(
|
private fun Context.generateNewConstraint(
|
||||||
targetVariable: TypeVariableMarker,
|
targetVariable: TypeVariableMarker,
|
||||||
baseConstraint: Constraint,
|
baseConstraint: Constraint,
|
||||||
otherVariable: TypeVariableMarker,
|
otherVariable: TypeVariableMarker,
|
||||||
otherConstraint: Constraint
|
otherConstraint: Constraint
|
||||||
) {
|
) {
|
||||||
val typeWithSubstitution = when (otherConstraint.kind) {
|
val isBaseGenericType = baseConstraint.type.argumentsCount() != 0
|
||||||
|
val isOtherCapturedType = otherConstraint.type.isCapturedType()
|
||||||
|
val (type, needApproximation) = when (otherConstraint.kind) {
|
||||||
ConstraintKind.EQUALITY -> {
|
ConstraintKind.EQUALITY -> {
|
||||||
baseConstraint.type.substitute(this, otherVariable, otherConstraint.type)
|
otherConstraint.type to true
|
||||||
}
|
}
|
||||||
ConstraintKind.UPPER -> {
|
ConstraintKind.UPPER -> {
|
||||||
val temporaryCapturedType = createCapturedType(
|
/*
|
||||||
createTypeArgument(otherConstraint.type, TypeVariance.OUT),
|
* Creating a captured type isn't needed due to its future approximation to `Nothing` or itself
|
||||||
listOf(otherConstraint.type),
|
* Example:
|
||||||
null,
|
* targetVariable = TypeVariable(A)
|
||||||
CaptureStatus.FOR_INCORPORATION
|
* baseConstraint = LOWER(TypeVariable(B))
|
||||||
)
|
* otherConstraint = UPPER(Number)
|
||||||
baseConstraint.type.substitute(this, otherVariable, temporaryCapturedType)
|
* incorporatedConstraint = Approx(CapturedType(out Number)) <: TypeVariable(A) => Nothing <: TypeVariable(A)
|
||||||
|
* TODO: implement this for generics and captured types
|
||||||
|
*/
|
||||||
|
if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isOtherCapturedType) {
|
||||||
|
nothingType() to false
|
||||||
|
} else if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isOtherCapturedType) {
|
||||||
|
otherConstraint.type to false
|
||||||
|
} else {
|
||||||
|
createCapturedType(
|
||||||
|
createTypeArgument(otherConstraint.type, TypeVariance.OUT),
|
||||||
|
listOf(otherConstraint.type),
|
||||||
|
null,
|
||||||
|
CaptureStatus.FOR_INCORPORATION
|
||||||
|
) to true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ConstraintKind.LOWER -> {
|
ConstraintKind.LOWER -> {
|
||||||
val temporaryCapturedType = createCapturedType(
|
/*
|
||||||
createTypeArgument(otherConstraint.type, TypeVariance.IN),
|
* Creating a captured type isn't needed due to its future approximation to `Any?` or itself
|
||||||
emptyList(),
|
* Example:
|
||||||
otherConstraint.type,
|
* targetVariable = TypeVariable(A)
|
||||||
CaptureStatus.FOR_INCORPORATION
|
* baseConstraint = UPPER(TypeVariable(B))
|
||||||
)
|
* otherConstraint = LOWER(Number)
|
||||||
baseConstraint.type.substitute(this, otherVariable, temporaryCapturedType)
|
* incorporatedConstraint = TypeVariable(A) <: Approx(CapturedType(in Number)) => TypeVariable(A) <: Any?
|
||||||
|
* TODO: implement this for generics and captured types
|
||||||
|
*/
|
||||||
|
if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isOtherCapturedType) {
|
||||||
|
nullableAnyType() to false
|
||||||
|
} else if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isOtherCapturedType) {
|
||||||
|
otherConstraint.type to false
|
||||||
|
} else {
|
||||||
|
createCapturedType(
|
||||||
|
createTypeArgument(otherConstraint.type, TypeVariance.IN),
|
||||||
|
emptyList(),
|
||||||
|
otherConstraint.type,
|
||||||
|
CaptureStatus.FOR_INCORPORATION
|
||||||
|
) to true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
when (baseConstraint.kind) {
|
approximateIfNeededAndAddNewConstraint(baseConstraint, type, targetVariable, otherVariable, otherConstraint, needApproximation)
|
||||||
ConstraintKind.EQUALITY -> {
|
|
||||||
addNewConstraint(targetVariable, baseConstraint, otherVariable, otherConstraint, typeWithSubstitution, isSubtype = true)
|
|
||||||
addNewConstraint(targetVariable, baseConstraint, otherVariable, otherConstraint, typeWithSubstitution, isSubtype = false)
|
|
||||||
}
|
|
||||||
ConstraintKind.UPPER -> {
|
|
||||||
val generatedConstraintType = approximateCapturedTypes(typeWithSubstitution, toSuper = true)
|
|
||||||
addNewConstraint(targetVariable, baseConstraint, otherVariable, otherConstraint, generatedConstraintType, isSubtype = false)
|
|
||||||
}
|
|
||||||
ConstraintKind.LOWER -> {
|
|
||||||
val generatedConstraintType = approximateCapturedTypes(typeWithSubstitution, toSuper = false)
|
|
||||||
addNewConstraint(targetVariable, baseConstraint, otherVariable, otherConstraint, generatedConstraintType, isSubtype = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Context.addNewConstraint(
|
private fun Context.addNewConstraint(
|
||||||
|
|||||||
Vendored
+2238
File diff suppressed because it is too large
Load Diff
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public object Entities {
|
||||||
|
private constructor Entities()
|
||||||
|
public final val map: kotlin.collections.Map<kotlin.String, kotlin.Int>
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -10285,6 +10285,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/approximateBeforeFixation.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/approximateBeforeFixation.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("avoidCreatingUselessCapturedTypes.kt")
|
||||||
|
public void testAvoidCreatingUselessCapturedTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/avoidCreatingUselessCapturedTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("cannotCaptureInProjection.kt")
|
@TestMetadata("cannotCaptureInProjection.kt")
|
||||||
public void testCannotCaptureInProjection() throws Exception {
|
public void testCannotCaptureInProjection() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/cannotCaptureInProjection.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/cannotCaptureInProjection.kt");
|
||||||
|
|||||||
Generated
+5
@@ -10280,6 +10280,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/approximateBeforeFixation.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/approximateBeforeFixation.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("avoidCreatingUselessCapturedTypes.kt")
|
||||||
|
public void testAvoidCreatingUselessCapturedTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/avoidCreatingUselessCapturedTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("cannotCaptureInProjection.kt")
|
@TestMetadata("cannotCaptureInProjection.kt")
|
||||||
public void testCannotCaptureInProjection() throws Exception {
|
public void testCannotCaptureInProjection() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/cannotCaptureInProjection.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/cannotCaptureInProjection.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user