[FIR] Support @OnlyInputTypes annotation

^KT-54807 Fixed
This commit is contained in:
Dmitriy Novozhilov
2022-11-08 12:17:20 +02:00
committed by Space Team
parent 5cc08fb314
commit 1b27d60307
48 changed files with 98 additions and 484 deletions
@@ -1419,6 +1419,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR) { firDiagnostic ->
TypeInferenceOnlyInputTypesErrorImpl(
firSymbolBuilder.classifierBuilder.buildTypeParameterSymbol(firDiagnostic.a),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.THROWABLE_TYPE_MISMATCH) { firDiagnostic ->
ThrowableTypeMismatchImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
@@ -1021,6 +1021,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val isMismatchDueToNullability: Boolean
}
abstract class TypeInferenceOnlyInputTypesError : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = TypeInferenceOnlyInputTypesError::class
abstract val typeParameter: KtTypeParameterSymbol
}
abstract class ThrowableTypeMismatch : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = ThrowableTypeMismatch::class
abstract val actualType: KtType
@@ -1224,6 +1224,12 @@ internal class TypeMismatchImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.TypeMismatch(), KtAbstractFirDiagnostic<PsiElement>
internal class TypeInferenceOnlyInputTypesErrorImpl(
override val typeParameter: KtTypeParameterSymbol,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.TypeInferenceOnlyInputTypesError(), KtAbstractFirDiagnostic<PsiElement>
internal class ThrowableTypeMismatchImpl(
override val actualType: KtType,
override val isMismatchDueToNullability: Boolean,
@@ -449,6 +449,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<Boolean>("isMismatchDueToNullability")
}
val TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR by error<PsiElement>() {
parameter<FirTypeParameterSymbol>("typeParameter")
}
val THROWABLE_TYPE_MISMATCH by error<PsiElement> {
parameter<ConeKotlinType>("actualType")
parameter<Boolean>("isMismatchDueToNullability")
@@ -330,6 +330,7 @@ object FirErrors {
val NONE_APPLICABLE by error1<PsiElement, Collection<FirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val INAPPLICABLE_CANDIDATE by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val TYPE_MISMATCH by error3<PsiElement, ConeKotlinType, ConeKotlinType, Boolean>()
val TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR by error1<PsiElement, FirTypeParameterSymbol>()
val THROWABLE_TYPE_MISMATCH by error2<PsiElement, ConeKotlinType, Boolean>()
val CONDITION_TYPE_MISMATCH by error2<PsiElement, ConeKotlinType, Boolean>()
val ARGUMENT_TYPE_MISMATCH by error3<PsiElement, ConeKotlinType, ConeKotlinType, Boolean>()
@@ -134,7 +134,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTO
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_INHERITANCE_HIERARCHY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DANGEROUS_CHARACTERS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_OVERRIDE_CONFLICT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG_PARAMETER
@@ -257,6 +256,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_CHARACT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_LEFT_COMPONENT_OF_INTERSECTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INC_DEC_SHOULD_NOT_RETURN_UNIT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_UNSUCCESSFUL_FORK
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION
@@ -499,6 +499,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPECHECKER_HAS_R
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_CANT_BE_USED_FOR_CONST_VAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_ENUM
@@ -1010,6 +1011,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
)
map.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", TO_STRING, TO_STRING, NOT_RENDERED)
map.put(
TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR,
"Type inference failed. The value of the type parameter {0} should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.",
SYMBOL
)
map.put(THROWABLE_TYPE_MISMATCH, "Throwable type mismatch: actual type is {0}", TO_STRING, NOT_RENDERED)
map.put(CONDITION_TYPE_MISMATCH, "Condition type mismatch: inferred type is {0} but Boolean was expected", TO_STRING, NOT_RENDERED)
map.put(
@@ -442,6 +442,13 @@ private fun ConstraintSystemError.toDiagnostic(
)
}
is OnlyInputTypesDiagnostic -> {
FirErrors.TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR.createOn(
source,
(typeVariable as ConeTypeParameterBasedTypeVariable).typeParameterSymbol
)
}
else -> null
}
}
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeReceiverConstraintPosition
import org.jetbrains.kotlin.fir.resolve.inference.preprocessCallableReference
import org.jetbrains.kotlin.fir.resolve.inference.preprocessLambdaArgument
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
@@ -32,6 +34,7 @@ import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.components.VariableFixationFinder
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.CaptureStatus
@@ -251,7 +254,7 @@ fun Candidate.resolvePlainArgumentType(
isDispatch: Boolean,
useNullableArgumentType: Boolean = false
) {
val position = SimpleConstraintSystemConstraintPosition //TODO
val position = if (isReceiver) ConeReceiverConstraintPosition(argument) else ConeArgumentConstraintPosition(argument)
val session = context.session
val capturedType = prepareCapturedType(argumentType, context)
@@ -348,7 +351,7 @@ private fun checkApplicabilityForArgumentType(
argument: FirExpression,
argumentTypeBeforeCapturing: ConeKotlinType,
expectedType: ConeKotlinType?,
position: SimpleConstraintSystemConstraintPosition,
position: ConstraintPosition,
isReceiver: Boolean,
isDispatch: Boolean,
sink: CheckerSink,
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.resolve.inference.model.ConeFixVariableConstrain
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemUtilContext
import org.jetbrains.kotlin.resolve.calls.inference.components.PostponedArgumentInputTypesResolver
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
@@ -27,8 +28,8 @@ object ConeConstraintSystemUtilContext : ConstraintSystemUtilContext {
}
override fun TypeVariableMarker.hasOnlyInputTypesAttribute(): Boolean {
// TODO
return false
if (this !is ConeTypeParameterBasedTypeVariable) return false
return typeParameterSymbol.resolvedAnnotationClassIds.any { it == StandardClassIds.Annotations.OnlyInputTypes }
}
override fun KotlinTypeMarker.unCapture(): KotlinTypeMarker {
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.inference.model
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.types.model.TypeVariableMarker
@@ -31,4 +32,6 @@ class ConeLambdaArgumentConstraintPosition(
class ConeBuilderInferenceSubstitutionConstraintPosition(initialConstraint: InitialConstraint) :
BuilderInferenceSubstitutionConstraintPosition<Nothing?, InitialConstraint>(null, initialConstraint) // TODO
BuilderInferenceSubstitutionConstraintPosition<Nothing?, InitialConstraint>(null, initialConstraint) // TODO
class ConeReceiverConstraintPosition(receiver: FirExpression) : ReceiverConstraintPosition<FirExpression>(receiver)
@@ -1,3 +1,5 @@
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
// FIR status: Disabling of StrictOnlyInputTypesChecks is not supported by FIR
// WITH_STDLIB
// !LANGUAGE: -StrictOnlyInputTypesChecks
@@ -79,4 +81,4 @@ fun box(): String {
poll81()
poll91()
return "OK"
}
}
@@ -1,3 +1,5 @@
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
// FIR status: Disabling of StrictOnlyInputTypesChecks is not supported by FIR
// WITH_STDLIB
// !LANGUAGE: -StrictOnlyInputTypesChecks
@@ -79,4 +81,4 @@ fun box(): String {
poll81()
poll91()
return "OK"
}
}
@@ -1,3 +1,5 @@
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
// FIR status: Disabling of StrictOnlyInputTypesChecks is not supported by FIR
// WITH_STDLIB
// SKIP_TXT
// !LANGUAGE: -StrictOnlyInputTypesChecks
@@ -1,3 +1,5 @@
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
// FIR status: Disabling of StrictOnlyInputTypesChecks is not supported by FIR
// WITH_STDLIB
// !LANGUAGE: -StrictOnlyInputTypesChecks
@@ -1,3 +1,5 @@
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
// FIR status: Disabling of StrictOnlyInputTypesChecks is not supported by FIR
// WITH_STDLIB
// !LANGUAGE: -StrictOnlyInputTypesChecks
@@ -444,7 +444,7 @@ fun poll8(): Flow<String> {
fun poll81(): Flow<String> {
return flow {
val inv = ::bar2 in setOf(::foo2)
val inv = ::bar2 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo2)
<!UNRESOLVED_REFERENCE!>inv<!>()
}
}
@@ -458,7 +458,7 @@ fun poll82(): Flow<String> {
fun poll83(): Flow<String> {
return flow {
val inv = ::bar4 in setOf(::foo4)
val inv = ::bar4 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo4)
inv
}
}
@@ -486,7 +486,7 @@ fun poll86(): Flow<String> {
fun poll87(): Flow<String> {
return flow {
val inv = ::Foo7 <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>in<!> setOf(foo7())
val inv = ::Foo7 <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(foo7())
inv
}
}
@@ -57,14 +57,14 @@ fun poll75(): Flow<String> {
fun poll81(): Flow<String> {
return flow {
val inv = ::bar2 in setOf(::foo2)
val inv = ::bar2 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo2)
<!UNRESOLVED_REFERENCE!>inv<!>()
}
}
fun poll83(): Flow<String> {
return flow {
val inv = ::bar4 in setOf(::foo4)
val inv = ::bar4 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo4)
inv
}
}
@@ -22,14 +22,14 @@ class Flow<out R>(private val block: suspend FlowCollector<R>.() -> Unit)
fun poll81(): Flow<String> {
return flow {
val inv = ::bar2 in setOf(::foo2)
val inv = ::bar2 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo2)
<!UNRESOLVED_REFERENCE!>inv<!>()
}
}
fun poll83(): Flow<String> {
return flow {
val inv = ::bar4 in setOf(::foo4)
val inv = ::bar4 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo4)
inv
}
}
@@ -446,7 +446,7 @@ fun poll8(): Flow<String> {
fun poll81(): Flow<String> {
return flow {
val inv = ::bar2 in setOf(::foo2)
val inv = ::bar2 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo2)
<!UNRESOLVED_REFERENCE!>inv<!>()
}
}
@@ -460,7 +460,7 @@ fun poll82(): Flow<String> {
fun poll83(): Flow<String> {
return flow {
val inv = ::bar4 in setOf(::foo4)
val inv = ::bar4 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo4)
inv
}
}
@@ -488,7 +488,7 @@ fun poll86(): Flow<String> {
fun poll87(): Flow<String> {
return flow {
val inv = ::Foo7 <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>in<!> setOf(foo7())
val inv = ::Foo7 <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(foo7())
inv
}
}
@@ -279,7 +279,7 @@ fun poll8() {
}
fun poll81() {
val inv = ::bar2 in setOf(::foo2)
val inv = ::bar2 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(::foo2)
<!UNRESOLVED_REFERENCE!>inv<!>()
}
@@ -309,7 +309,7 @@ fun poll86() {
}
fun poll87() {
val inv = ::Foo7 <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>in<!> setOf(foo7())
val inv = ::Foo7 <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>in<!> setOf(foo7())
inv
}
@@ -1,20 +0,0 @@
// See also KT-10386
interface A
class B : A
fun foo1(list: List<A>, arg: B?): Boolean {
// Type mismatch
return arg in list // resolved to extension
}
fun foo2(list: List<A>, arg: B?): Boolean {
// FAKE: no cast needed
return arg as A? in list
}
fun foo3(list: List<A>, arg: B?): Boolean {
// No warning but KNPE risk
return arg!! in list
}
// But
fun foo4(list: List<A>, arg: B): Boolean {
// Ok
return arg in list
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// See also KT-10386
interface A
class B : A
@@ -1,29 +0,0 @@
import java.util.*
fun foo() {
val al = ArrayList<String>()
al.size
al.contains(1)
al.contains("")
al.remove("")
al.removeAt(1)
val hs = HashSet<String>()
hs.size
hs.contains(1)
hs.contains("")
hs.remove("")
val hm = HashMap<String, Int>()
hm.size
hm.containsKey(1)
hm.containsKey("")
hm[1]
hm[""]
hm.remove("")
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
import java.util.*
fun foo() {
val al = ArrayList<String>()
@@ -1,12 +0,0 @@
// !DIAGNOSTICS: -INVISIBLE_MEMBER -INVISIBLE_REFERENCE -UNUSED_PARAMETER
interface Parent
object ChildA : Parent
object ChildB : Parent
fun <@kotlin.internal.OnlyInputTypes T> select(a: T, b: T) {}
fun test() {
select(ChildA, ChildB) // should be error
select<Any>(ChildA, ChildB) // should be ok
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -INVISIBLE_MEMBER -INVISIBLE_REFERENCE -UNUSED_PARAMETER
interface Parent
@@ -1,21 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
open class Base()
class CX : Base()
class CY : Base()
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <@kotlin.internal.OnlyInputTypes T> foo(a: T, b: T) {}
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <@kotlin.internal.OnlyInputTypes T : Any> fooA(a: T, b: T) {}
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <@kotlin.internal.OnlyInputTypes T : Base> fooB(a: T, b: T) {}
fun usage(x: CX, y: CY) {
foo(x, y) // expected err, got err
fooA(x, y) // expected err, got ok
fooB(x, y) // expected err, got ok
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
open class Base()
@@ -1,30 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// ISSUE: KT-29307
fun test_1(map: Map<String, String>) {
val x = map[42] // OK
}
open class A
class B : A()
fun test_2(map: Map<A, String>) {
val x = map[42]
}
fun test_3(m: Map<*, String>) {
val x = m[42] // should be ok
}
fun test_4(m: Map<out Number, String>) {
val x = m.get(42) // should be ok
}
fun test_5(map: Map<B, Int>, a: A) {
map.get(a)
}
fun test_6(map: Map<A, Int>, b: B) {
map.get(b)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE
// ISSUE: KT-29307
@@ -1,46 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.contains1(element: T): Boolean = null!!
class In<in T>
class Out<out T>
class Inv<T>
fun test_1(list: List<In<Number>>, x: In<Number>, y: In<Int>, z: In<Any>) {
list.contains1(x)
list.contains1(y)
list.contains1(z)
}
fun test_2(list: List<In<Int>>, x: In<Int>, y: In<Number>, z: In<Any>) {
list.contains1(x)
list.contains1(y)
list.contains1(z)
}
fun test_3(list: List<Out<Number>>, x: Out<Number>, y: Out<Int>, z: Out<Any>) {
list.contains1(x)
list.contains1(y)
list.contains1(z)
}
fun test_4(list: List<Out<Int>>, x: Out<Int>, y: Out<Number>, z: Out<Any>) {
list.contains1(x)
list.contains1(y)
list.contains1(z)
}
fun test_5(list: List<Inv<Number>>, x: Inv<Number>, y: Inv<Int>, z: Inv<Any>) {
list.contains1(x)
list.contains1(y)
list.contains1(z)
}
fun test_6(list: List<Inv<Int>>, x: Inv<Int>, y: Inv<Number>, z: Inv<Any>) {
list.contains1(x)
list.contains1(y)
list.contains1(z)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@@ -17,9 +17,9 @@ public fun <K, V> Map<K, V>.get1(key: Any?): Int = null!!
public fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.get1(key: K): V? = null!!
fun test(map: Map<Int, String>) {
val a: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>listOf(1).contains1("")<!>
val a: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>listOf(1).<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>contains1<!>("")<!>
val b: Boolean = listOf(1).contains1(1)
val c: String? = map.get1("")
val c: String? = map.<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>get1<!>("")
val d: String? = map.get1(1)
}
@@ -1,112 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// Issue: KT-26698
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.contains1(element: T): Boolean = null!!
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.foo(element: T): T = null!!
class Inv<T>
class Inv2<T, R>
class In<in T>
class Out<out T>
// -------------------------------------------------------
fun test_0(x: Inv2<in Number, out Number>, list: List<Inv2<Any, Int>>) {
list.foo(x)
}
// ------------------------- Inv -------------------------
fun test_1(x: Inv<Number>, list: List<Inv<Number>>) {
list.contains1(x)
}
fun test_2(x: Inv<Number>, list: List<Inv<Int>>) {
list.contains1(x)
}
fun test_3(x: Inv<Number>, list: List<Inv<Any>>) {
list.contains1(x)
}
fun test_4(x: Inv<in Number>, list: List<Inv<Any>>) {
list.contains1(x)
}
fun test_5(x: Inv<in Number>, list: List<Inv<Number>>) {
list.contains1(x)
}
fun test_6(x: Inv<in Number>, list: List<Inv<Int>>) {
list.contains1(x)
}
fun test_7(x: Inv<out Number>, list: List<Inv<Any>>) {
list.contains1(x)
}
fun test_8(x: Inv<out Number>, list: List<Inv<Number>>) {
list.contains1(x)
}
fun test_9(x: Inv<out Number>, list: List<Inv<Int>>) {
list.contains1(x)
}
// ------------------------- In -------------------------
fun test_11(x: In<Number>, list: List<In<Number>>) {
list.contains1(x)
}
fun test_12(x: In<Number>, list: List<In<Int>>) {
list.contains1(x)
}
fun test_13(x: In<Number>, list: List<In<Any>>) {
list.contains1(x)
}
// ------------------------- Out -------------------------
fun test_21(x: Out<Number>, list: List<Out<Number>>) {
list.contains1(x)
}
fun test_22(x: Out<Number>, list: List<Out<Int>>) {
list.contains1(x)
}
fun test_23(x: Out<Number>, list: List<Out<Any>>) {
list.contains1(x)
}
// --------------------------------------------------------
fun test_31(x: Inv<Number>, list: List<Inv<in Number>>) {
list.contains1(x)
}
fun test_32(x: Inv<Number>, list: List<Inv<in Int>>) {
list.contains1(x)
}
fun test_33(x: Inv<Number>, list: List<Inv<in Any>>) {
list.contains1(x)
}
fun test_34(x: Inv<Number>, list: List<Inv<out Number>>) {
list.contains1(x)
}
fun test_35(x: Inv<Number>, list: List<Inv<out Int>>) {
list.contains1(x)
}
fun test_36(x: Inv<Number>, list: List<Inv<out Any>>) {
list.contains1(x)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// Issue: KT-26698
@@ -43,11 +43,11 @@ fun testOK(first: First, bound: Bound, second: Second) {
}
fun testFail(first: First, bound: Bound, second: Second) {
strictSelect(InvB(first), InvB(bound))
strictSelect(Inv(first), Inv(bound))
strictSelect(Out(first), Out(second))
strictSelect(In(first), In(second))
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>strictSelect<!>(InvB(first), InvB(bound))
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>strictSelect<!>(Inv(first), Inv(bound))
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>strictSelect<!>(Out(first), Out(second))
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>strictSelect<!>(In(first), In(second))
strictSelect(InB(first), InB(second))
strictSelect(Out(Inv(first)), Out(Inv(second)))
strictSelect(In(Inv(first)), In(Inv(second)))
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>strictSelect<!>(Out(Inv(first)), Out(Inv(second)))
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>strictSelect<!>(In(Inv(first)), In(Inv(second)))
}
@@ -9,5 +9,5 @@ class First : Common
class Second : Common
fun test(first: First, second: Second) {
select(first, second)
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!>select<!>(first, second)
}
@@ -1,24 +0,0 @@
//!DIAGNOSTICS: -UNUSED_PARAMETER
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <@kotlin.internal.OnlyInputTypes T> assertEquals1(t1: T, t2: T) {}
open class A
class B: A()
class C: A()
class D
fun test1(a: A, b: B, c: C) {
assertEquals1(a, b)
assertEquals1(b, c)
assertEquals1(3, 3)
assertEquals1(1 or 2, 2 or 1)
}
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <@kotlin.internal.OnlyInputTypes T> expect1(expected: T, block: () -> T) {}
fun test() {
expect1(2) { byteArrayOf(1, 2, 3).indexOf(3) }
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
//!DIAGNOSTICS: -UNUSED_PARAMETER
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@@ -1,79 +0,0 @@
// !LANGUAGE: -ProhibitConcurrentHashMapContains
// FULL_JDK
class A : java.util.concurrent.ConcurrentHashMap<String, Int>() {
operator fun contains(x: Char): Boolean = true
}
class B : java.util.concurrent.ConcurrentHashMap<String, Int>() {
override fun contains(value: Any?): Boolean {
return super.contains(value)
}
}
class C : java.util.concurrent.ConcurrentHashMap<String, Int>() {
operator override fun contains(value: Any?): Boolean {
return super.contains(value)
}
}
fun main() {
val hm = java.util.concurrent.ConcurrentHashMap<String, Int>()
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>in<!> hm
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>!in<!> hm
1 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>!in<!> hm
2 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>in<!> hm
hm.contains("")
hm.contains(1)
"" in (hm as Map<String, Int>)
"" !in (hm as Map<String, Int>)
1 in (hm as Map<String, Int>)
1 !in (hm as Map<String, Int>)
val a = A()
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>in<!> a
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>!in<!> a
1 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>!in<!> a
2 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>in<!> a
' ' in a
' ' !in a
a.contains("")
a.contains(1)
"" in (a as Map<String, Int>)
"" !in (a as Map<String, Int>)
1 in (a as Map<String, Int>)
1 !in (a as Map<String, Int>)
val b = B()
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>in<!> b
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>!in<!> b
1 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>!in<!> b
2 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>in<!> b
b.contains("")
b.contains(1)
"" in (b as Map<String, Int>)
"" !in (b as Map<String, Int>)
1 in (b as Map<String, Int>)
1 !in (b as Map<String, Int>)
// Actually, we could've allow calls here because the owner explicitly declared as operator, but semantics is still weird
val c = C()
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>in<!> c
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>!in<!> c
1 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>!in<!> c
2 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_WARNING!>in<!> c
c.contains("")
c.contains(1)
"" in (c as Map<String, Int>)
"" !in (c as Map<String, Int>)
1 in (c as Map<String, Int>)
1 !in (c as Map<String, Int>)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitConcurrentHashMapContains
// FULL_JDK
@@ -1,78 +0,0 @@
// !LANGUAGE: +ProhibitConcurrentHashMapContains
// FULL_JDK
class A : java.util.concurrent.ConcurrentHashMap<String, Int>() {
operator fun contains(x: Char): Boolean = true
}
class B : java.util.concurrent.ConcurrentHashMap<String, Int>() {
override fun contains(value: Any?): Boolean {
return super.contains(value)
}
}
class C : java.util.concurrent.ConcurrentHashMap<String, Int>() {
operator override fun contains(value: Any?): Boolean {
return super.contains(value)
}
}
fun main() {
val hm = java.util.concurrent.ConcurrentHashMap<String, Int>()
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>in<!> hm
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>!in<!> hm
1 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>!in<!> hm
2 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>in<!> hm
hm.contains("")
hm.contains(1)
"" in (hm as Map<String, Int>)
"" !in (hm as Map<String, Int>)
1 in (hm as Map<String, Int>)
1 !in (hm as Map<String, Int>)
val a = A()
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>in<!> a
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>!in<!> a
1 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>!in<!> a
2 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>in<!> a
' ' in a
' ' !in a
a.contains("")
a.contains(1)
"" in (a as Map<String, Int>)
"" !in (a as Map<String, Int>)
1 in (a as Map<String, Int>)
1 !in (a as Map<String, Int>)
val b = B()
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>in<!> b
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>!in<!> b
1 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>!in<!> b
2 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>in<!> b
b.contains("")
b.contains(1)
"" in (b as Map<String, Int>)
"" !in (b as Map<String, Int>)
1 in (b as Map<String, Int>)
1 !in (b as Map<String, Int>)
// Actually, we could've allow calls here because the owner explicitly declared as operator, but semantics is still weird
val c = C()
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>in<!> c
"" <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>!in<!> c
1 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>!in<!> c
2 <!CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR!>in<!> c
c.contains("")
c.contains(1)
"" in (c as Map<String, Int>)
"" !in (c as Map<String, Int>)
1 in (c as Map<String, Int>)
1 !in (c as Map<String, Int>)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +ProhibitConcurrentHashMapContains
// FULL_JDK
@@ -19,7 +19,7 @@ open class Case1<K : Number> {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.get(0)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.size
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.isEmpty()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>[null]
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!><!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>[null]<!>
}
}
}
@@ -19,7 +19,7 @@ open class Case1<K : Number> {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.get(0)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.size
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.isEmpty()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>[null]
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!><!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>[null]<!>
}
}
}
@@ -19,7 +19,7 @@ open class Case1<K : Number> {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.get(0)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.size
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>.isEmpty()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>[null]
<!TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR!><!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & M & L & K & T!!")!>x<!>[null]<!>
}
}
}
@@ -163,6 +163,8 @@ object StandardClassIds {
val FlexibleNullability = "FlexibleNullability".internalIrId()
val EnhancedNullability = "EnhancedNullability".jvmInternalId()
val OnlyInputTypes = "OnlyInputTypes".internalId()
val RestrictsSuspension = "RestrictsSuspension".coroutinesId()
val WasExperimental = "WasExperimental".baseId()
@@ -96,7 +96,7 @@ class TypeTest {
)
}
@Suppress("RemoveExplicitTypeArguments", "TYPE_INFERENCE_ONLY_INPUT_TYPES_WARNING")
@Suppress("RemoveExplicitTypeArguments", "TYPE_INFERENCE_ONLY_INPUT_TYPES_WARNING", "TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR")
@Test
fun `test - equals`() {
assertEquals(extrasTypeOf<List<Int>>(), extrasTypeOf<List<Int>>())