[FE] Implement discussed rules to report empty intersection errors
This commit is contained in:
committed by
teamcity
parent
b96708c3e2
commit
5bfe6cd20a
+47
-3
@@ -8,12 +8,12 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
|||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedAtomWithRevisableExpectedType
|
import org.jetbrains.kotlin.resolve.calls.model.PostponedAtomWithRevisableExpectedType
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
|
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker.isRelatedBySubtypingTo
|
||||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
|
||||||
|
|
||||||
abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Context, ResultTypeResolver.Context {
|
abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Context, ResultTypeResolver.Context {
|
||||||
abstract val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
|
abstract val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
|
||||||
@@ -37,6 +37,50 @@ abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Contex
|
|||||||
abstract fun couldBeResolvedWithUnrestrictedBuilderInference(): Boolean
|
abstract fun couldBeResolvedWithUnrestrictedBuilderInference(): Boolean
|
||||||
abstract fun processForkConstraints()
|
abstract fun processForkConstraints()
|
||||||
|
|
||||||
|
private fun TypeConstructorMarker.isDefinitelyClass() = isClassTypeConstructor() && !isInterface()
|
||||||
|
|
||||||
|
private fun KotlinTypeMarker.containsTypeParameter() = contains { it.typeConstructor().isTypeParameterTypeConstructor() }
|
||||||
|
|
||||||
|
fun Collection<KotlinTypeMarker>.isEmptyIntersection(constraintSystem: NewConstraintSystem?): Boolean {
|
||||||
|
val indexedComponents = withIndex()
|
||||||
|
return indexedComponents.any firstTypes@{ (i, first) ->
|
||||||
|
val firstTypeConstructor = first.typeConstructor()
|
||||||
|
indexedComponents.any secondTypes@{ (j, second) ->
|
||||||
|
if (i >= j) return@secondTypes false
|
||||||
|
|
||||||
|
val secondTypeConstructor = second.typeConstructor()
|
||||||
|
|
||||||
|
if (!firstTypeConstructor.isDefinitelyClass() && !firstTypeConstructor.isTypeParameterTypeConstructor())
|
||||||
|
return@secondTypes false
|
||||||
|
if (!secondTypeConstructor.isDefinitelyClass() && !secondTypeConstructor.isTypeParameterTypeConstructor())
|
||||||
|
return@secondTypes false
|
||||||
|
|
||||||
|
if (!first.containsTypeParameter() && !second.containsTypeParameter()) {
|
||||||
|
return@secondTypes !isRelatedBySubtypingTo(this@ConstraintSystemCompletionContext, first, second)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraintSystem == null) return false
|
||||||
|
|
||||||
|
val completerContext = constraintSystem.asConstraintSystemCompleterContext()
|
||||||
|
val substitutionMap = completerContext.allTypeVariables.entries.associate { (key, value) ->
|
||||||
|
val typeParameter = (key as TypeVariableTypeConstructorMarker).typeParameter
|
||||||
|
require(typeParameter != null) {
|
||||||
|
"Constraint system for checking type parameters for intersection emptiness" +
|
||||||
|
"should be build with type variables which refer to those type parameters"
|
||||||
|
}
|
||||||
|
typeParameter.getTypeConstructor() to value.defaultType()
|
||||||
|
}
|
||||||
|
val substitutor = typeSubstitutorByTypeConstructor(substitutionMap)
|
||||||
|
|
||||||
|
completerContext.getBuilder().addSubtypeConstraint(
|
||||||
|
substitutor.safeSubstitute(first), substitutor.safeSubstitute(second), TypeParametersIntersectionEmptyCheckingPosition
|
||||||
|
)
|
||||||
|
|
||||||
|
constraintSystem.hasContradiction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun <A : PostponedResolvedAtomMarker> analyzeArgumentWithFixedParameterTypes(
|
fun <A : PostponedResolvedAtomMarker> analyzeArgumentWithFixedParameterTypes(
|
||||||
languageVersionSettings: LanguageVersionSettings,
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
postponedArguments: List<A>,
|
postponedArguments: List<A>,
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ fun test() {
|
|||||||
callFun<String, Wrapper<String>>(::createWrapper)
|
callFun<String, Wrapper<String>>(::createWrapper)
|
||||||
callFun<Int, Wrapper<Number>>(::createWrapper)
|
callFun<Int, Wrapper<Number>>(::createWrapper)
|
||||||
callFun<String, Wrapper<*>>(::createWrapper)
|
callFun<String, Wrapper<*>>(::createWrapper)
|
||||||
callFun<String, Wrapper<Int>>(::createWrapper)
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>callFun<!><String, Wrapper<Int>>(::createWrapper)
|
||||||
|
|
||||||
callFun<Int, Wrapper<Int>>(::createWrapper).baz(::foo)
|
callFun<Int, Wrapper<Int>>(::createWrapper).baz(::foo)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ fun test() {
|
|||||||
callFun<String, Wrapper<String>>(::createWrapper)
|
callFun<String, Wrapper<String>>(::createWrapper)
|
||||||
callFun<Int, Wrapper<Number>>(::createWrapper)
|
callFun<Int, Wrapper<Number>>(::createWrapper)
|
||||||
callFun<String, Wrapper<*>>(::createWrapper)
|
callFun<String, Wrapper<*>>(::createWrapper)
|
||||||
callFun<String, Wrapper<Int>>(::createWrapper)
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>callFun<!><String, Wrapper<Int>>(::createWrapper)
|
||||||
|
|
||||||
callFun<Int, Wrapper<Int>>(::createWrapper).baz(::foo)
|
callFun<Int, Wrapper<Int>>(::createWrapper).baz(::foo)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+5
-5
@@ -70,7 +70,7 @@ fun main() {
|
|||||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
|
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
|
||||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2(::takeInt)))
|
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2(::takeInt)))
|
||||||
select(id1 { x: Inv<out Number> -> TODO() }, id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>it<!>.x.inv() }, id1 { x: Inv<Int> -> TODO() })
|
select(id1 { x: Inv<out Number> -> TODO() }, id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>it<!>.x.inv() }, id1 { x: Inv<Int> -> TODO() })
|
||||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Number> & Inv<kotlin.Int>")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>select<!>(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Number> & Inv<kotlin.Int>")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
||||||
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
|
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
|
||||||
|
|
||||||
// Disambiguating callable references by other callable references without overloads
|
// Disambiguating callable references by other callable references without overloads
|
||||||
@@ -164,10 +164,10 @@ fun main() {
|
|||||||
select({ x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
|
select({ x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
|
||||||
|
|
||||||
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types
|
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
|
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
|
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
|
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
|
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
|
||||||
|
|
||||||
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types; dependent type parameters
|
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types; dependent type parameters
|
||||||
takeLambdasWithDirectlyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
|
takeLambdasWithDirectlyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
|
||||||
|
|||||||
Vendored
+5
-5
@@ -70,7 +70,7 @@ fun main() {
|
|||||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
|
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
|
||||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2(::takeInt)))
|
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2(::takeInt)))
|
||||||
select(id1 { x: Inv<out Number> -> TODO() }, id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>it<!>.x.inv() }, id1 { x: Inv<Int> -> TODO() })
|
select(id1 { x: Inv<out Number> -> TODO() }, id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>it<!>.x.inv() }, id1 { x: Inv<Int> -> TODO() })
|
||||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("{Inv<Int> & Inv<Number>}")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>select<!>(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("{Inv<Int> & Inv<Number>}")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
||||||
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
|
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
|
||||||
|
|
||||||
// Disambiguating callable references by other callable references without overloads
|
// Disambiguating callable references by other callable references without overloads
|
||||||
@@ -164,10 +164,10 @@ fun main() {
|
|||||||
select({ x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
|
select({ x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
|
||||||
|
|
||||||
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types
|
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
|
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
|
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
|
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
|
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
|
||||||
|
|
||||||
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types; dependent type parameters
|
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types; dependent type parameters
|
||||||
takeLambdasWithDirectlyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
|
takeLambdasWithDirectlyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||||
interface Base
|
interface Base
|
||||||
|
|
||||||
@@ -9,5 +10,5 @@ fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
|||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val func: (DoesNotImplementBase) -> Unit = { }
|
val func: (DoesNotImplementBase) -> Unit = { }
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
interface Base
|
||||||
|
|
||||||
|
interface DoesNotImplementBase
|
||||||
|
|
||||||
|
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val func: (DoesNotImplementBase) -> Unit = { }
|
||||||
|
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface Base {
|
||||||
|
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 interface DoesNotImplementBase {
|
||||||
|
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,11 @@
|
|||||||
|
open class Base
|
||||||
|
open class DoesNotImplementBase
|
||||||
|
|
||||||
|
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val func: (DoesNotImplementBase) -> Unit = { }
|
||||||
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
open class Base
|
||||||
|
open class DoesNotImplementBase
|
||||||
|
|
||||||
|
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val func: (DoesNotImplementBase) -> Unit = { }
|
||||||
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
|
||||||
|
public open class Base {
|
||||||
|
public constructor Base()
|
||||||
|
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 DoesNotImplementBase {
|
||||||
|
public constructor DoesNotImplementBase()
|
||||||
|
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
-3
@@ -1,6 +1,4 @@
|
|||||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
open class Base
|
||||||
interface Base
|
|
||||||
|
|
||||||
class DoesNotImplementBase
|
class DoesNotImplementBase
|
||||||
|
|
||||||
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
open class Base
|
||||||
|
class DoesNotImplementBase
|
||||||
|
|
||||||
|
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val func: (DoesNotImplementBase) -> Unit = { }
|
||||||
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
|
||||||
|
public open class Base {
|
||||||
|
public constructor Base()
|
||||||
|
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 DoesNotImplementBase {
|
||||||
|
public constructor DoesNotImplementBase()
|
||||||
|
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 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
interface Base
|
||||||
|
|
||||||
|
class DoesNotImplementBase
|
||||||
|
|
||||||
|
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val func: (DoesNotImplementBase) -> Unit = { }
|
||||||
|
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface Base {
|
||||||
|
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 DoesNotImplementBase {
|
||||||
|
public constructor DoesNotImplementBase()
|
||||||
|
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 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
interface Base
|
||||||
|
|
||||||
|
open class DoesNotImplementBase
|
||||||
|
|
||||||
|
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val func: (DoesNotImplementBase) -> Unit = { }
|
||||||
|
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface Base {
|
||||||
|
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 DoesNotImplementBase {
|
||||||
|
public constructor DoesNotImplementBase()
|
||||||
|
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
-1
@@ -14,7 +14,7 @@ val a1: A = select(
|
|||||||
{ a: Int -> myPrint(a + this.length + 2) }
|
{ a: Int -> myPrint(a + this.length + 2) }
|
||||||
)
|
)
|
||||||
|
|
||||||
val a2 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>select<!>(
|
val a2 = select(
|
||||||
{ a: Int -> myPrint(a + this.length + 1) },
|
{ a: Int -> myPrint(a + this.length + 1) },
|
||||||
fun CharSequence.(a: Int) { myPrint(a + this.length + 2) },
|
fun CharSequence.(a: Int) { myPrint(a + this.length + 2) },
|
||||||
{ a: Int -> myPrint(a + this.length + 3) }
|
{ a: Int -> myPrint(a + this.length + 3) }
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ val a1: A = select(
|
|||||||
{ a: Int -> myPrint(a + this.length + 2) }
|
{ a: Int -> myPrint(a + this.length + 2) }
|
||||||
)
|
)
|
||||||
|
|
||||||
val a2 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>select<!>(
|
val a2 = select(
|
||||||
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 1) },
|
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 1) },
|
||||||
fun CharSequence.(a: Int) { myPrint(a + this.length + 2) },
|
fun CharSequence.(a: Int) { myPrint(a + this.length + 2) },
|
||||||
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 3) }
|
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 3) }
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
|
||||||
|
|
||||||
abstract class Bar<T>
|
|
||||||
|
|
||||||
class Foo<T> : Bar<T>(), Comparable<Foo<*>> {
|
|
||||||
override fun compareTo(other: Foo<*>): Int = TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
infix fun <T : Comparable<T>, S : T?> Bar<in S>.test(t: T) { }
|
|
||||||
infix fun <T : Comparable<T>, S : T?> Bar<in S>.test(other: Bar<in S>) {}
|
|
||||||
|
|
||||||
fun checkFunctions(exp1: Foo<Int?>, exp2: Foo<Int>) {
|
|
||||||
exp1.<!OVERLOAD_RESOLUTION_AMBIGUITY!>test<!>(exp2)
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
abstract class Bar<T>
|
abstract class Bar<T>
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ fun testElvis(a: Int?, b: Int?) {
|
|||||||
if (a != null) {
|
if (a != null) {
|
||||||
doInt(b ?: a)
|
doInt(b ?: a)
|
||||||
}
|
}
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>doList<!>(getList() ?: emptyListOfA()) //should be an error
|
doList(getList() ?: emptyListOfA()) //should be an error
|
||||||
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
|
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ fun testElvis(a: Int?, b: Int?) {
|
|||||||
if (a != null) {
|
if (a != null) {
|
||||||
doInt(b ?: <!DEBUG_INFO_SMARTCAST!>a<!>)
|
doInt(b ?: <!DEBUG_INFO_SMARTCAST!>a<!>)
|
||||||
}
|
}
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>doList<!>(getList() ?: emptyListOfA()) //should be an error
|
doList(getList() ?: emptyListOfA()) //should be an error
|
||||||
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
|
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ fun <T: A> emptyNullableListOfA(): List<T>? = null
|
|||||||
//-------------------------------
|
//-------------------------------
|
||||||
|
|
||||||
fun testExclExcl() {
|
fun testExclExcl() {
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>doList<!>(emptyNullableListOfA()!!) //should be an error here
|
doList(emptyNullableListOfA()!!) //should be an error here
|
||||||
val l: List<Int> = <!INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>id(emptyNullableListOfA()!!)<!>
|
val l: List<Int> = <!INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>id(emptyNullableListOfA()!!)<!>
|
||||||
|
|
||||||
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
|
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ fun <T: A> emptyNullableListOfA(): List<T>? = null
|
|||||||
//-------------------------------
|
//-------------------------------
|
||||||
|
|
||||||
fun testExclExcl() {
|
fun testExclExcl() {
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>doList<!>(emptyNullableListOfA()!!) //should be an error here
|
doList(emptyNullableListOfA()!!) //should be an error here
|
||||||
val l: List<Int> = <!TYPE_MISMATCH!><!TYPE_MISMATCH!>id<!>(<!TYPE_MISMATCH!>emptyNullableListOfA<!>()<!TYPE_MISMATCH!>!!<!>)<!>
|
val l: List<Int> = <!TYPE_MISMATCH!><!TYPE_MISMATCH!>id<!>(<!TYPE_MISMATCH!>emptyNullableListOfA<!>()<!TYPE_MISMATCH!>!!<!>)<!>
|
||||||
|
|
||||||
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
|
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
class Expression<T>(val x: T)
|
||||||
|
|
||||||
|
class GreaterOp(val expr1: Expression<*>, val expr2: Expression<*>)
|
||||||
|
|
||||||
|
fun <T : Comparable<T>, S : T?> Expression<in S>.greater(other: T): GreaterOp =
|
||||||
|
GreaterOp(this, Expression(other))
|
||||||
|
|
||||||
|
fun foo(countExpr: Expression<Long>) {
|
||||||
|
countExpr.greater(0)
|
||||||
|
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>greater<!>("0")
|
||||||
|
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>greater<!><String, Nothing>("0")
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
class Expression<T>(val x: T)
|
class Expression<T>(val x: T)
|
||||||
|
|
||||||
class GreaterOp(val expr1: Expression<*>, val expr2: Expression<*>)
|
class GreaterOp(val expr1: Expression<*>, val expr2: Expression<*>)
|
||||||
@@ -8,6 +7,6 @@ fun <T : Comparable<T>, S : T?> Expression<in S>.greater(other: T): GreaterOp =
|
|||||||
|
|
||||||
fun foo(countExpr: Expression<Long>) {
|
fun foo(countExpr: Expression<Long>) {
|
||||||
countExpr.greater(0)
|
countExpr.greater(0)
|
||||||
countExpr.greater("0")
|
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>greater<!>("0")
|
||||||
countExpr.greater<String, Nothing>("0")
|
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>greater<!><String, Nothing>("0")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,26 +178,6 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
|
|
||||||
fun KotlinTypeMarker.isFinal(): Boolean
|
fun KotlinTypeMarker.isFinal(): Boolean
|
||||||
|
|
||||||
fun Collection<KotlinTypeMarker>.isEmptyIntersection(): Boolean {
|
|
||||||
val expandedTypes = buildSet {
|
|
||||||
for (type in this@isEmptyIntersection) {
|
|
||||||
val typeConstructor = type.typeConstructor()
|
|
||||||
when {
|
|
||||||
typeConstructor.isClassTypeConstructor() -> add(type)
|
|
||||||
typeConstructor.isTypeParameterTypeConstructor() -> addAll(typeConstructor.supertypes())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.takeIf { it.isNotEmpty() } ?: return false
|
|
||||||
|
|
||||||
return expandedTypes.any { first ->
|
|
||||||
expandedTypes.any { second ->
|
|
||||||
first !== second &&
|
|
||||||
first.isFinal() &&
|
|
||||||
!AbstractTypeChecker.isSubtypeOf(this@TypeSystemInferenceExtensionContext, first, second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker
|
fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker
|
||||||
fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker
|
fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user