[NI] discriminate Nothing for reified parameters

Related issues: KT-32836, KT-35728
This commit is contained in:
Pavel Kirpichenkov
2020-01-14 12:40:19 +03:00
parent a16b21a7cc
commit 4a29de3716
14 changed files with 222 additions and 7 deletions
@@ -10708,6 +10708,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/inference/nothingType/complexDependancyOnVariableWithTrivialConstraint.kt");
}
@TestMetadata("discriminateNothingForReifiedParameter.kt")
public void testDiscriminateNothingForReifiedParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/discriminateNothingForReifiedParameter.kt");
}
@TestMetadata("discriminatedNothingAndSmartCast.kt")
public void testDiscriminatedNothingAndSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/discriminatedNothingAndSmartCast.kt");
}
@TestMetadata("generateConstraintWithInnerNothingType.kt")
public void testGenerateConstraintWithInnerNothingType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/generateConstraintWithInnerNothingType.kt");
@@ -22,11 +22,8 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirec
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.types.AbstractTypeApproximator
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
class ResultTypeResolver(
val typeApproximator: AbstractTypeApproximator,
@@ -35,6 +32,7 @@ class ResultTypeResolver(
interface Context : TypeSystemInferenceExtensionContext {
fun isProperType(type: KotlinTypeMarker): Boolean
fun buildNotFixedVariablesToStubTypesSubstitutor(): TypeSubstitutorMarker
fun isReified(variable: TypeVariableMarker): Boolean
}
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker {
@@ -85,6 +83,7 @@ class ResultTypeResolver(
}
if (!trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType)) {
if (resultType.isNullableType() && checkSingleLowerNullabilityConstraint(filteredConstraints)) return false
if (isReified(variableWithConstraints.typeVariable)) return false
}
return true
@@ -33,6 +33,7 @@ class VariableFixationFinder(
interface Context : TypeSystemInferenceExtensionContext {
val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
val postponedTypeVariables: List<TypeVariableMarker>
fun isReified(variable: TypeVariableMarker): Boolean
}
data class VariableForFixation(
@@ -56,6 +57,7 @@ class VariableFixationFinder(
WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS, // proper trivial constraint from arguments, Nothing <: T
RELATED_TO_ANY_OUTPUT_TYPE,
READY_FOR_FIXATION,
READY_FOR_FIXATION_REIFIED,
}
private fun Context.getTypeVariableReadiness(
@@ -68,6 +70,7 @@ class VariableFixationFinder(
hasDependencyToOtherTypeVariables(variable) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY
variableHasTrivialOrNonProperConstraints(variable) -> TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS
dependencyProvider.isVariableRelatedToAnyOutputType(variable) -> TypeVariableFixationReadiness.RELATED_TO_ANY_OUTPUT_TYPE
isReified(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_REIFIED
else -> TypeVariableFixationReadiness.READY_FOR_FIXATION
}
@@ -121,4 +124,6 @@ class VariableFixationFinder(
private fun Context.isProperType(type: KotlinTypeMarker): Boolean =
!type.contains { notFixedTypeVariables.containsKey(it.typeConstructor()) }
private fun Context.isReified(variable: TypeConstructorMarker): Boolean =
notFixedTypeVariables[variable]?.typeVariable?.let { isReified(it) } ?: false
}
@@ -341,6 +341,12 @@ class NewConstraintSystemImpl(
return storage.buildNotFixedVariablesToNonSubtypableTypesSubstitutor(this)
}
// ResultTypeResolver.Context, VariableFixationFinder.Context
override fun isReified(variable: TypeVariableMarker): Boolean {
if (variable !is TypeVariableFromCallableDescriptor) return false
return variable.originalTypeParameter.isReified
}
override fun bindingStubsForPostponedVariables(): Map<TypeVariableMarker, StubTypeMarker> {
checkState(State.BUILDING, State.COMPLETION)
// TODO: SUB
@@ -0,0 +1,53 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNREACHABLE_CODE
interface Bound
fun <T : Bound> take(t: T?): T = t ?: TODO()
inline fun <reified T : Bound> takeReified(t: T?): T = t ?: TODO()
inline fun <reified T> takeReifiedUnbound(t: T?): T = t ?: TODO()
fun <M : Bound> materialize(): M = TODO()
inline fun <reified M : Bound> materializeReified(): M = TODO()
inline fun <reified M> materializeReifiedUnbound(): M = TODO()
fun <T> select(a: T, b: T): T = TODO()
fun test1() {
take(null)
}
fun test2() {
takeReified(null)
}
fun test3() {
takeReifiedUnbound(null)
}
fun test4(): Bound = takeReifiedUnbound(null)
fun test5(): Bound? = select(
null,
materialize()
)
fun test6() {
select(
null,
materializeReified()
)
}
fun test7(): Bound? =
select(
null,
materializeReifiedUnbound()
)
fun test8() {
select(
null,
materializeReifiedUnbound()
)
}
@@ -0,0 +1,53 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNREACHABLE_CODE
interface Bound
fun <T : Bound> take(t: T?): T = t ?: TODO()
inline fun <reified T : Bound> takeReified(t: T?): T = t ?: TODO()
inline fun <reified T> takeReifiedUnbound(t: T?): T = t ?: TODO()
fun <M : Bound> materialize(): M = TODO()
inline fun <reified M : Bound> materializeReified(): M = TODO()
inline fun <reified M> materializeReifiedUnbound(): M = TODO()
fun <T> select(a: T, b: T): T = TODO()
fun test1() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!><!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>take<!>(null)<!>
}
fun test2() {
<!DEBUG_INFO_EXPRESSION_TYPE("Bound")!>takeReified(null)<!>
}
fun test3() {
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>takeReifiedUnbound<!>(null)
}
fun test4(): Bound = <!DEBUG_INFO_EXPRESSION_TYPE("Bound")!>takeReifiedUnbound(null)<!>
fun test5(): Bound? = select(
null,
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>materialize<!>()
)
fun test6() {
select(
null,
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, IMPLICIT_NOTHING_AS_TYPE_PARAMETER, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>materializeReified<!>()
)
}
fun test7(): Bound? =
select(
null,
<!DEBUG_INFO_EXPRESSION_TYPE("Bound?")!>materializeReifiedUnbound()<!>
)
fun test8() {
select(
null,
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>materializeReifiedUnbound<!>()
)
}
@@ -0,0 +1,23 @@
package
public fun </*0*/ M : Bound> materialize(): M
public inline fun </*0*/ reified M : Bound> materializeReified(): M
public inline fun </*0*/ reified M> materializeReifiedUnbound(): M
public fun </*0*/ T> select(/*0*/ a: T, /*1*/ b: T): T
public fun </*0*/ T : Bound> take(/*0*/ t: T?): T
public inline fun </*0*/ reified T : Bound> takeReified(/*0*/ t: T?): T
public inline fun </*0*/ reified T> takeReifiedUnbound(/*0*/ t: T?): T
public fun test1(): kotlin.Unit
public fun test2(): kotlin.Unit
public fun test3(): kotlin.Unit
public fun test4(): Bound
public fun test5(): Bound?
public fun test6(): kotlin.Unit
public fun test7(): Bound?
public fun test8(): kotlin.Unit
public interface Bound {
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,19 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
interface ExpectedType
inline fun <reified M> parse(): M? = TODO()
fun test(s: String?, silent: Boolean) {
val result: ExpectedType =
if (s != null) {
parse() ?: TODO()
} else if (silent) {
return
} else {
throw Exception()
}
s.<!INAPPLICABLE_CANDIDATE!>length<!>
}
@@ -0,0 +1,19 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
interface ExpectedType
inline fun <reified M> parse(): M? = TODO()
fun test(s: String?, silent: Boolean) {
val result: ExpectedType =
if (s != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("ExpectedType?")!>parse()<!> ?: TODO()
} else <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>if (silent) {
return
} else {
throw Exception()
}<!>
<!DEBUG_INFO_SMARTCAST!>s<!>.length
}
@@ -0,0 +1,10 @@
package
public inline fun </*0*/ reified M> parse(): M?
public fun test(/*0*/ s: kotlin.String?, /*1*/ silent: kotlin.Boolean): kotlin.Unit
public interface ExpectedType {
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
}
@@ -1,5 +1,4 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !WITH_NEW_INFERENCE
inline fun <reified T> parse(json: String): T? = TODO()
+1 -2
View File
@@ -1,5 +1,4 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !WITH_NEW_INFERENCE
inline fun <reified T> parse(json: String): T? = TODO()
@@ -7,7 +6,7 @@ class MyType
fun parseMyData(json: String): MyType =
try {
<!NI;REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, NI;REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>parse<!>(json) // error with new inf only: Cannot use 'Nothing?' as reified type parameter
parse(json) // error with new inf only: Cannot use 'Nothing?' as reified type parameter
?: throw IllegalArgumentException("Can't parse")
} catch (e: Exception) {
throw IllegalArgumentException("Can't parse")
@@ -10715,6 +10715,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/complexDependancyOnVariableWithTrivialConstraint.kt");
}
@TestMetadata("discriminateNothingForReifiedParameter.kt")
public void testDiscriminateNothingForReifiedParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/discriminateNothingForReifiedParameter.kt");
}
@TestMetadata("discriminatedNothingAndSmartCast.kt")
public void testDiscriminatedNothingAndSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/discriminatedNothingAndSmartCast.kt");
}
@TestMetadata("generateConstraintWithInnerNothingType.kt")
public void testGenerateConstraintWithInnerNothingType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/generateConstraintWithInnerNothingType.kt");
@@ -10710,6 +10710,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/inference/nothingType/complexDependancyOnVariableWithTrivialConstraint.kt");
}
@TestMetadata("discriminateNothingForReifiedParameter.kt")
public void testDiscriminateNothingForReifiedParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/discriminateNothingForReifiedParameter.kt");
}
@TestMetadata("discriminatedNothingAndSmartCast.kt")
public void testDiscriminatedNothingAndSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/discriminatedNothingAndSmartCast.kt");
}
@TestMetadata("generateConstraintWithInnerNothingType.kt")
public void testGenerateConstraintWithInnerNothingType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/generateConstraintWithInnerNothingType.kt");