[FIR] Add FINAL_UPPER_BOUND checker
This commit is contained in:
+5
-5
@@ -38,15 +38,15 @@ fun test(z: Int, c: Char) {}
|
||||
|
||||
typealias BA = A
|
||||
|
||||
fun <T> kek(t: T) where T : (String) -> Any?, T : Char {}
|
||||
fun <T> kek(t: T) where T : () -> Boolean, T : String {}
|
||||
fun <T : Int> kek(t: T) {}
|
||||
fun <T> kek(t: T) where T : (String) -> Any?, T : <!FINAL_UPPER_BOUND!>Char<!> {}
|
||||
fun <T> kek(t: T) where T : () -> Boolean, T : <!FINAL_UPPER_BOUND!>String<!> {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Int<!>> kek(t: T) {}
|
||||
|
||||
fun lol(a: Array<Int>) {}
|
||||
fun lol(a: Array<Boolean>) {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun <T> mem(t: T)<!> where T : () -> Boolean, T : String {}
|
||||
<!CONFLICTING_OVERLOADS!>fun <T> mem(t: T)<!> where T : String, T : () -> Boolean {}
|
||||
<!CONFLICTING_OVERLOADS!>fun <T> mem(t: T)<!> where T : () -> Boolean, T : <!FINAL_UPPER_BOUND!>String<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun <T> mem(t: T)<!> where T : <!FINAL_UPPER_BOUND!>String<!>, T : () -> Boolean {}
|
||||
|
||||
class M {
|
||||
companion <!REDECLARATION!>object<!> {}
|
||||
|
||||
+4
-4
@@ -14,7 +14,7 @@ open class D() : B() {
|
||||
override var test: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>Char<!> = '\n'
|
||||
}
|
||||
|
||||
class E<T : Double>(val value: T) : B() {
|
||||
class E<T : <!FINAL_UPPER_BOUND!>Double<!>>(val value: T) : B() {
|
||||
override var test: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>T<!> = value
|
||||
}
|
||||
|
||||
@@ -22,14 +22,14 @@ open class F<T : Number>(val value: T) {
|
||||
open var rest: T = value
|
||||
}
|
||||
|
||||
class G<E : Double>(val balue: E) : F<E>(balue) {
|
||||
class G<E : <!FINAL_UPPER_BOUND!>Double<!>>(val balue: E) : F<E>(balue) {
|
||||
override var rest: E = balue
|
||||
}
|
||||
|
||||
class H<E : String>(val balue: E) : <!INAPPLICABLE_CANDIDATE!>F<E><!>(balue) {
|
||||
class H<E : <!FINAL_UPPER_BOUND!>String<!>>(val balue: E) : <!INAPPLICABLE_CANDIDATE!>F<E><!>(balue) {
|
||||
override var rest: E = balue // no report because of INAPPLICABLE_CANDIDATE
|
||||
}
|
||||
|
||||
class M<E : String>(val balue: E) : F<Double>(3.14) {
|
||||
class M<E : <!FINAL_UPPER_BOUND!>String<!>>(val balue: E) : F<Double>(3.14) {
|
||||
override var rest: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>E<!> = balue
|
||||
}
|
||||
|
||||
+4
-4
@@ -15,7 +15,7 @@ open class D() : B() {
|
||||
override fun test(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Char<!> = '\n'
|
||||
}
|
||||
|
||||
class E<T : Double>(val value: T) : B() {
|
||||
class E<T : <!FINAL_UPPER_BOUND!>Double<!>>(val value: T) : B() {
|
||||
override fun test(): T = value
|
||||
}
|
||||
|
||||
@@ -23,15 +23,15 @@ open class F<T : Number>(val value: T) {
|
||||
open fun rest(): T = value
|
||||
}
|
||||
|
||||
class G<E : Double>(val balue: E) : F<E>(balue) {
|
||||
class G<E : <!FINAL_UPPER_BOUND!>Double<!>>(val balue: E) : F<E>(balue) {
|
||||
override fun rest(): E = balue
|
||||
}
|
||||
|
||||
class H<E : String>(val balue: E) : <!INAPPLICABLE_CANDIDATE!>F<E><!>(balue) {
|
||||
class H<E : <!FINAL_UPPER_BOUND!>String<!>>(val balue: E) : <!INAPPLICABLE_CANDIDATE!>F<E><!>(balue) {
|
||||
override fun rest(): E = balue // no report because of INAPPLICABLE_CANDIDATE
|
||||
}
|
||||
|
||||
class M<E : String>(val balue: E) : F<Double>(3.14) {
|
||||
class M<E : <!FINAL_UPPER_BOUND!>String<!>>(val balue: E) : F<Double>(3.14) {
|
||||
override fun rest(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>E<!> = balue
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -35,6 +35,7 @@ fun main(args: Array<String>) {
|
||||
alias<FirRegularClass>("RegularClassChecker")
|
||||
alias<FirConstructor>("ConstructorChecker")
|
||||
alias<FirFile>("FileChecker")
|
||||
alias<FirTypeParameter>("FirTypeParameterChecker")
|
||||
|
||||
additional(
|
||||
fieldName = "controlFlowAnalyserCheckers",
|
||||
|
||||
+4
@@ -289,6 +289,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val TYPE_PARAMETER_AS_REIFIED by error<FirSourceElement, PsiElement> {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
|
||||
val FINAL_UPPER_BOUND by warning<FirSourceElement, PsiElement> {
|
||||
parameter<ConeKotlinType>("type")
|
||||
}
|
||||
}
|
||||
|
||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
||||
|
||||
+4
@@ -33,6 +33,8 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
get() = _constructorCheckers
|
||||
override val fileCheckers: Set<FirFileChecker>
|
||||
get() = _fileCheckers
|
||||
override val typeParameterCheckers: Set<FirTypeParameterChecker>
|
||||
get() = _typeParameterCheckers
|
||||
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
|
||||
get() = _controlFlowAnalyserCheckers
|
||||
override val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker>
|
||||
@@ -47,6 +49,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
private val _regularClassCheckers: MutableSet<FirRegularClassChecker> = mutableSetOf()
|
||||
private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf()
|
||||
private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf()
|
||||
private val _typeParameterCheckers: MutableSet<FirTypeParameterChecker> = mutableSetOf()
|
||||
private val _controlFlowAnalyserCheckers: MutableSet<FirControlFlowChecker> = mutableSetOf()
|
||||
private val _variableAssignmentCfaBasedCheckers: MutableSet<AbstractFirPropertyInitializationChecker> = mutableSetOf()
|
||||
|
||||
@@ -61,6 +64,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
_regularClassCheckers += checkers.regularClassCheckers
|
||||
_constructorCheckers += checkers.constructorCheckers
|
||||
_fileCheckers += checkers.fileCheckers
|
||||
_typeParameterCheckers += checkers.typeParameterCheckers
|
||||
_controlFlowAnalyserCheckers += checkers.controlFlowAnalyserCheckers
|
||||
_variableAssignmentCfaBasedCheckers += checkers.variableAssignmentCfaBasedCheckers
|
||||
}
|
||||
|
||||
+2
@@ -28,6 +28,7 @@ abstract class DeclarationCheckers {
|
||||
open val regularClassCheckers: Set<FirRegularClassChecker> = emptySet()
|
||||
open val constructorCheckers: Set<FirConstructorChecker> = emptySet()
|
||||
open val fileCheckers: Set<FirFileChecker> = emptySet()
|
||||
open val typeParameterCheckers: Set<FirTypeParameterChecker> = emptySet()
|
||||
|
||||
open val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = emptySet()
|
||||
open val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker> = emptySet()
|
||||
@@ -41,4 +42,5 @@ abstract class DeclarationCheckers {
|
||||
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> get() = regularClassCheckers + memberDeclarationCheckers + basicDeclarationCheckers + classCheckers
|
||||
@CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> get() = constructorCheckers + functionCheckers + basicDeclarationCheckers + memberDeclarationCheckers
|
||||
@CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> get() = fileCheckers + basicDeclarationCheckers
|
||||
@CheckersComponentInternal internal val allTypeParameterCheckers: Set<FirTypeParameterChecker> get() = typeParameterCheckers + basicDeclarationCheckers
|
||||
}
|
||||
|
||||
+2
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
|
||||
typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration>
|
||||
typealias FirMemberDeclarationChecker = FirDeclarationChecker<FirMemberDeclaration>
|
||||
@@ -29,3 +30,4 @@ typealias FirClassChecker = FirDeclarationChecker<FirClass<*>>
|
||||
typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
|
||||
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
|
||||
typealias FirFileChecker = FirDeclarationChecker<FirFile>
|
||||
typealias FirTypeParameterChecker = FirDeclarationChecker<FirTypeParameter>
|
||||
|
||||
@@ -214,6 +214,7 @@ object FirErrors {
|
||||
val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error0<FirSourceElement, KtClassOrObject>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE by error1<FirSourceElement, KtNamedDeclaration, FirTypeParameterSymbol>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val TYPE_PARAMETER_AS_REIFIED by error1<FirSourceElement, PsiElement, FirTypeParameterSymbol>()
|
||||
val FINAL_UPPER_BOUND by warning1<FirSourceElement, PsiElement, ConeKotlinType>()
|
||||
|
||||
// Reflection
|
||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<FirSourceElement, KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+1
-3
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
||||
@@ -199,9 +200,6 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
||||
else -> true
|
||||
}
|
||||
|
||||
fun KotlinTypeMarker.isSupertypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?) =
|
||||
type != null && AbstractTypeChecker.isSubtypeOf(context, type, this)
|
||||
|
||||
private fun simpleTypeStatement(realVar: RealVariable, exactType: Boolean, type: ConeKotlinType): MutableTypeStatement {
|
||||
return MutableTypeStatement(
|
||||
realVar,
|
||||
|
||||
@@ -5,13 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer.isSupertypeOf
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
||||
@@ -30,16 +28,16 @@ import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtModifierList
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
|
||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal fun FirClass<*>.unsubstitutedScope(context: CheckerContext) =
|
||||
@@ -321,3 +319,81 @@ val FirValueParameter.hasValOrVar: Boolean
|
||||
val source = this.source ?: return false
|
||||
return source.getChild(VAL_VAR_TOKEN_SET) != null
|
||||
}
|
||||
|
||||
fun KotlinTypeMarker.isSupertypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?) =
|
||||
type != null && AbstractTypeChecker.isSubtypeOf(context, type, this)
|
||||
|
||||
fun KotlinTypeMarker.isSubtypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?) =
|
||||
type != null && AbstractTypeChecker.isSubtypeOf(context, this, type)
|
||||
|
||||
fun ConeKotlinType.canHaveSubtypes(session: FirSession): Boolean {
|
||||
if (this.isMarkedNullable) {
|
||||
return true
|
||||
}
|
||||
val clazz = toRegularClass(session) ?: return true
|
||||
if (clazz.isEnumClass || clazz.isExpect || clazz.modality != Modality.FINAL) {
|
||||
return true
|
||||
}
|
||||
|
||||
clazz.typeParameters.forEachIndexed { idx, typeParameterRef ->
|
||||
val typeParameter = typeParameterRef.symbol.fir
|
||||
val typeProjection = typeArguments[idx]
|
||||
|
||||
if (typeProjection.isStarProjection) {
|
||||
return true
|
||||
}
|
||||
|
||||
val argument = typeProjection.type!! //safe because it is not a star
|
||||
|
||||
when (typeParameter.variance) {
|
||||
Variance.INVARIANT ->
|
||||
when (typeProjection.kind) {
|
||||
ProjectionKind.INVARIANT ->
|
||||
if (lowerThanBound(session.typeContext, argument, typeParameter) || argument.canHaveSubtypes(session)) {
|
||||
return true
|
||||
}
|
||||
ProjectionKind.IN ->
|
||||
if (lowerThanBound(session.typeContext, argument, typeParameter)) {
|
||||
return true
|
||||
}
|
||||
ProjectionKind.OUT ->
|
||||
if (argument.canHaveSubtypes(session)) {
|
||||
return true
|
||||
}
|
||||
ProjectionKind.STAR ->
|
||||
return true
|
||||
}
|
||||
Variance.IN_VARIANCE ->
|
||||
if (typeProjection.kind != ProjectionKind.OUT) {
|
||||
if (lowerThanBound(session.typeContext, argument, typeParameter)) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if (argument.canHaveSubtypes(session)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
Variance.OUT_VARIANCE ->
|
||||
if (typeProjection.kind != ProjectionKind.IN) {
|
||||
if (argument.canHaveSubtypes(session)) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if (lowerThanBound(session.typeContext, argument, typeParameter)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinType, typeParameter: FirTypeParameter): Boolean {
|
||||
typeParameter.bounds.forEach { boundTypeRef ->
|
||||
if (argument != boundTypeRef.coneType && argument.isSubtypeOf(context, boundTypeRef.coneType)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.canHaveSubtypes
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
|
||||
object FirTypeParameterBoundsChecker : FirTypeParameterChecker() {
|
||||
|
||||
override fun check(declaration: FirTypeParameter, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val containingDeclaration = context.containingDeclarations.lastOrNull()
|
||||
if (containingDeclaration is FirConstructor) return
|
||||
if (containingDeclaration is FirSimpleFunction && containingDeclaration.isOverride) return
|
||||
if (containingDeclaration is FirProperty && containingDeclaration.isOverride) return
|
||||
|
||||
declaration.symbol.fir.bounds.forEach { bound ->
|
||||
if (!bound.coneType.canHaveSubtypes(context.session)) {
|
||||
reporter.reportOn(bound.source, FirErrors.FINAL_UPPER_BOUND, bound.coneType, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -61,7 +61,7 @@ class DeclarationCheckersDiagnosticComponent(
|
||||
}
|
||||
|
||||
override fun visitTypeParameter(typeParameter: FirTypeParameter, data: CheckerContext) {
|
||||
checkers.allBasicDeclarationCheckers.check(typeParameter, data, reporter)
|
||||
checkers.allTypeParameterCheckers.check(typeParameter, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: CheckerContext) {
|
||||
|
||||
+6
@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPRESSION_OF_NUL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_WITH_BACKING_FIELD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FINAL_UPPER_BOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_PARAMETER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GENERIC_THROWABLE_SUBCLASS
|
||||
@@ -438,6 +439,11 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
)
|
||||
|
||||
map.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead", SYMBOL)
|
||||
map.put(
|
||||
FINAL_UPPER_BOUND,
|
||||
"''{0}'' is a final type, and thus a value of the type parameter is predetermined",
|
||||
RENDER_TYPE
|
||||
)
|
||||
|
||||
// Reflection
|
||||
map.put(
|
||||
|
||||
+4
@@ -87,4 +87,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
override val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker> = setOf(
|
||||
FirPropertyInitializationAnalyzer,
|
||||
)
|
||||
|
||||
override val typeParameterCheckers: Set<FirTypeParameterChecker> = setOf(
|
||||
FirTypeParameterBoundsChecker,
|
||||
)
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,4 +40,4 @@ fun test() {
|
||||
|
||||
fun <T : Any> foo() {}
|
||||
fun <T : Int?> bar() {}
|
||||
fun <T : Int> Int.buzz() : Unit {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Int<!>> Int.buzz() : Unit {}
|
||||
|
||||
@@ -43,12 +43,12 @@ fun test() {
|
||||
|
||||
class Foo() {}
|
||||
|
||||
class Bar<T : Foo>
|
||||
class Bar<T : <!FINAL_UPPER_BOUND!>Foo<!>>
|
||||
|
||||
class Buzz<T> where T : Bar<Int>, T : <!UNRESOLVED_REFERENCE!>nioho<!>
|
||||
class Buzz<T> where T : <!FINAL_UPPER_BOUND!>Bar<Int><!>, T : <!UNRESOLVED_REFERENCE!>nioho<!>
|
||||
|
||||
class X<T : Foo>
|
||||
class Y<T> where T : Foo, T : Bar<Foo>
|
||||
class X<T : <!FINAL_UPPER_BOUND!>Foo<!>>
|
||||
class Y<T> where T : <!FINAL_UPPER_BOUND!>Foo<!>, T : <!FINAL_UPPER_BOUND!>Bar<Foo><!>
|
||||
|
||||
fun <T> test2(t : T)
|
||||
where
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ fun <T> takeFun(f: (T) -> Unit) {}
|
||||
fun <T, R> callFun(f: (T) -> R): R = TODO()
|
||||
|
||||
fun <T> foo(s: T) {}
|
||||
fun <T : Int> fooInt(s: T) {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Int<!>> fooInt(s: T) {}
|
||||
|
||||
open class Wrapper<T>(val value: T)
|
||||
fun <T, R : Wrapper<in T>> createWrapper(s: T): R = TODO()
|
||||
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
// Issues: KT-25105
|
||||
|
||||
class Message1
|
||||
class Task<T>
|
||||
object Message2
|
||||
enum class Message3
|
||||
data class Message4(val x: Int)
|
||||
|
||||
sealed class Message5<T> {
|
||||
open fun <A : T> execute() {}
|
||||
}
|
||||
|
||||
interface Manager<T> {
|
||||
fun <A : T> execute1(task: Task<A>) {}
|
||||
fun <T : Int> execute2(task: T) {}
|
||||
fun <T : Message2> execute3() {}
|
||||
fun <A : T> execute4() {}
|
||||
fun <A : T> execute5() {}
|
||||
val <A : T> A.x get() = 10
|
||||
var <A : T> A.y
|
||||
get() = 10
|
||||
set(value) {}
|
||||
}
|
||||
|
||||
object MessageManager1 : Manager<Message1> {
|
||||
override fun <T : Message1> execute1(task: Task<T>) {}
|
||||
override fun <T : Int> execute2(task: T) {}
|
||||
override fun <T : Message2> execute3() {}
|
||||
}
|
||||
|
||||
object MessageManager2 : Manager<Message3> {
|
||||
override fun <T : Message3> execute4() {}
|
||||
}
|
||||
|
||||
object MessageManager3 : Manager<Message4> {
|
||||
override fun <T : Message4> execute5() {}
|
||||
}
|
||||
|
||||
class MessageManager4 : Manager<Message1> {
|
||||
override fun <T : Message1> execute1(task: Task<T>) {}
|
||||
override fun <T : Int> execute2(task: T) {}
|
||||
override fun <T : Message2> execute3() {}
|
||||
}
|
||||
|
||||
class MessageManager5 : Manager<Message3> {
|
||||
override fun <T : Message3> execute4() {}
|
||||
}
|
||||
|
||||
class MessageManager6 : Manager<Message4> {
|
||||
override fun <T : Message4> execute5() {}
|
||||
}
|
||||
|
||||
interface MessageManager7 : Manager<Message4> {
|
||||
override fun <T : Message4> execute5() {}
|
||||
}
|
||||
|
||||
interface MessageManager8 : Manager<Message1> {
|
||||
override fun <T : Message1> execute1(task: Task<T>) {}
|
||||
override fun <T : Int> execute2(task: T) {}
|
||||
override fun <T : Message2> execute3() {}
|
||||
}
|
||||
|
||||
interface MessageManager9 : Manager<Message3> {
|
||||
override fun <T : Message3> execute4() {}
|
||||
}
|
||||
|
||||
object MessageManager10 : Message5<Int>() {
|
||||
override fun <T : Int> execute() {}
|
||||
}
|
||||
|
||||
class MessageManager11<A> : Message5<Message5<A>>() {
|
||||
override fun <T : Message5<A>> execute() {}
|
||||
}
|
||||
|
||||
data class MessageManager12(val x: Int) : Message5<Message2>() {
|
||||
override fun <T : Message2> execute() {}
|
||||
}
|
||||
|
||||
sealed class MessageManager13<A> : Message5<A>() {
|
||||
override fun <T : A> execute() {}
|
||||
}
|
||||
|
||||
class MessageManager14 : Manager<Message2> {
|
||||
override val <T : Message2> T.x get() = 10
|
||||
override var <T : Message2> T.y
|
||||
get() = 10
|
||||
set(value) {}
|
||||
}
|
||||
|
||||
object MessageManager15 : Manager<Int> {
|
||||
override val <T : Int> T.x get() = 10
|
||||
override var <T : Int> T.y
|
||||
get() = 10
|
||||
set(value) {}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
// Issues: KT-25105
|
||||
|
||||
+18
-18
@@ -10,9 +10,9 @@ data class Message4(val x: Int)
|
||||
interface Manager<T> {}
|
||||
|
||||
object MessageManager1 : Manager<Message1> {
|
||||
fun <T : Message1> execute1(task: Task<T>) {}
|
||||
fun <T : Int> execute2(task: T) {}
|
||||
fun <T : Message2> execute3() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message1<!>> execute1(task: Task<T>) {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Int<!>> execute2(task: T) {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message2<!>> execute3() {}
|
||||
}
|
||||
|
||||
object MessageManager2 : Manager<Message3> {
|
||||
@@ -20,13 +20,13 @@ object MessageManager2 : Manager<Message3> {
|
||||
}
|
||||
|
||||
object MessageManager3 : Manager<Message4> {
|
||||
fun <T : Message4> execute5() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message4<!>> execute5() {}
|
||||
}
|
||||
|
||||
class MessageManager4 : Manager<Message1> {
|
||||
fun <T : Message1> execute1(task: Task<T>) {}
|
||||
fun <T : Int> execute2(task: T) {}
|
||||
fun <T : Message2> execute3() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message1<!>> execute1(task: Task<T>) {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Int<!>> execute2(task: T) {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message2<!>> execute3() {}
|
||||
}
|
||||
|
||||
class MessageManager5 : Manager<Message3> {
|
||||
@@ -34,17 +34,17 @@ class MessageManager5 : Manager<Message3> {
|
||||
}
|
||||
|
||||
class MessageManager6 : Manager<Message4> {
|
||||
fun <T : Message4> execute5() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message4<!>> execute5() {}
|
||||
}
|
||||
|
||||
interface MessageManager7 : Manager<Message4> {
|
||||
fun <T : Message4> execute5() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message4<!>> execute5() {}
|
||||
}
|
||||
|
||||
interface MessageManager8 : Manager<Message1> {
|
||||
fun <T : Message1> execute1(task: Task<T>) {}
|
||||
fun <T : Int> execute2(task: T) {}
|
||||
fun <T : Message2> execute3() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message1<!>> execute1(task: Task<T>) {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Int<!>> execute2(task: T) {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message2<!>> execute3() {}
|
||||
}
|
||||
|
||||
interface MessageManager9 : Manager<Message3> {
|
||||
@@ -52,7 +52,7 @@ interface MessageManager9 : Manager<Message3> {
|
||||
}
|
||||
|
||||
object MessageManager10 : <!UNRESOLVED_REFERENCE!>Message5<Int><!>() {
|
||||
fun <T : Int> execute() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Int<!>> execute() {}
|
||||
}
|
||||
|
||||
class MessageManager11<A> : <!UNRESOLVED_REFERENCE!>Message5<<!UNRESOLVED_REFERENCE!>Message5<A><!>><!>() {
|
||||
@@ -60,7 +60,7 @@ class MessageManager11<A> : <!UNRESOLVED_REFERENCE!>Message5<<!UNRESOLVED_REFERE
|
||||
}
|
||||
|
||||
data class MessageManager12(val x: Int) : <!UNRESOLVED_REFERENCE!>Message5<Message2><!>() {
|
||||
fun <T : Message2> execute() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Message2<!>> execute() {}
|
||||
}
|
||||
|
||||
sealed class MessageManager13<A> : <!UNRESOLVED_REFERENCE!>Message5<A><!>() {
|
||||
@@ -68,15 +68,15 @@ sealed class MessageManager13<A> : <!UNRESOLVED_REFERENCE!>Message5<A><!>() {
|
||||
}
|
||||
|
||||
class MessageManager14 : Manager<Message2> {
|
||||
val <T : Message2> T.x get() = 10
|
||||
var <T : Message2> T.y
|
||||
val <T : <!FINAL_UPPER_BOUND!>Message2<!>> T.x get() = 10
|
||||
var <T : <!FINAL_UPPER_BOUND!>Message2<!>> T.y
|
||||
get() = 10
|
||||
set(value) {}
|
||||
}
|
||||
|
||||
object MessageManager15 : Manager<Int> {
|
||||
val <T : Int> T.x get() = 10
|
||||
var <T : Int> T.y
|
||||
val <T : <!FINAL_UPPER_BOUND!>Int<!>> T.x get() = 10
|
||||
var <T : <!FINAL_UPPER_BOUND!>Int<!>> T.y
|
||||
get() = 10
|
||||
set(value) {}
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ fun testCaptured(cSub: SubInv<out Number>, cInv: Inv<out Number>) {
|
||||
|
||||
fun testVariableWithBound() {
|
||||
fun <K : Number> createWithNumberBound(): Inv<K> = TODO()
|
||||
fun <K : Int> createWithIntBound(): Inv<K> = TODO()
|
||||
fun <K : <!FINAL_UPPER_BOUND!>Int<!>> createWithIntBound(): Inv<K> = TODO()
|
||||
|
||||
val c1 = select(SubInv<Int>(), createWithNumberBound())
|
||||
|
||||
|
||||
+1
-1
@@ -15,4 +15,4 @@ enum class E1
|
||||
class A5<T> where T : C1, T : E1
|
||||
|
||||
object O1
|
||||
class A6<T> where T : O1, T : C2
|
||||
class A6<T> where T : <!FINAL_UPPER_BOUND!>O1<!>, T : C2
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ fun <A : Array<Any>> f1() {}
|
||||
fun <T, A : Array<out T>> f2() {}
|
||||
fun <S, T : S, A> f3() where A : Array<out S>, A : Array<out T> {}
|
||||
|
||||
fun <T : IntArray> f4() {}
|
||||
fun <T : <!FINAL_UPPER_BOUND!>IntArray<!>> f4() {}
|
||||
|
||||
fun <T> f5() where T : Array<Any> {}
|
||||
|
||||
|
||||
Vendored
+5
-5
@@ -110,15 +110,15 @@ fun <T : Number> T.case_19_4(): Boolean? {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 20
|
||||
fun <T : String> T?.case_20_1(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_20_1(): Boolean {
|
||||
contract { returns(true) implies (this@case_20_1 != null) }
|
||||
return this@case_20_1 != null
|
||||
}
|
||||
fun <T : String> T?.case_20_2(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_20_2(): Boolean {
|
||||
contract { returns(true) implies (this@case_20_2 == null) }
|
||||
return this@case_20_2 == null
|
||||
}
|
||||
fun <T : String> T?.case_20_3(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_20_3(): Boolean {
|
||||
contract { returns(false) implies (this@case_20_3 != null) }
|
||||
return !(this@case_20_3 != null)
|
||||
}
|
||||
@@ -132,11 +132,11 @@ fun <T : String?> T.case_21_2(): Boolean {
|
||||
contract { returns(true) implies (this@case_21_2 == null) }
|
||||
return this@case_21_2 == null
|
||||
}
|
||||
fun <T : String> T?.case_21_5(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_21_5(): Boolean? {
|
||||
contract { returnsNotNull() implies (this@case_21_5 != null) }
|
||||
return if (this@case_21_5 != null) true else null
|
||||
}
|
||||
fun <T : String> T?.case_21_7(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_21_7(): Boolean? {
|
||||
contract { returns(null) implies (this@case_21_7 != null) }
|
||||
return if (this@case_21_7 != null) null else true
|
||||
}
|
||||
|
||||
Vendored
+6
-6
@@ -20,11 +20,11 @@ fun <T : Number> T.case_2() {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun <T : String> T?.case_3_1() {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_3_1() {
|
||||
contract { returns() implies (this@case_3_1 == null) }
|
||||
if (!(this@case_3_1 == null)) throw Exception()
|
||||
}
|
||||
fun <T : String> T?.case_3_2() {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_3_2() {
|
||||
contract { returns() implies (this@case_3_2 != null) }
|
||||
if (!(this@case_3_2 != null)) throw Exception()
|
||||
}
|
||||
@@ -76,19 +76,19 @@ fun <T : Number> T.case_6_4(): Boolean? {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 7
|
||||
fun <T : String> T?.case_7_1(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_1(): Boolean {
|
||||
contract { returns(true) implies (this@case_7_1 == null) }
|
||||
return this@case_7_1 == null
|
||||
}
|
||||
fun <T : String> T?.case_7_2(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_2(): Boolean {
|
||||
contract { returns(false) implies (this@case_7_2 != null) }
|
||||
return !(this@case_7_2 != null)
|
||||
}
|
||||
fun <T : String> T?.case_7_3(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_3(): Boolean? {
|
||||
contract { returnsNotNull() implies (this@case_7_3 != null) }
|
||||
return if (this@case_7_3 != null) true else null
|
||||
}
|
||||
fun <T : String> T?.case_7_4(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_4(): Boolean? {
|
||||
contract { returns(null) implies (this@case_7_4 != null) }
|
||||
return if (this@case_7_4 != null) null else true
|
||||
}
|
||||
|
||||
Vendored
+13
-13
@@ -20,11 +20,11 @@ fun <T : Number> T.case_2() {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun <T : String> T?.case_3_1() {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_3_1() {
|
||||
contract { returns() implies (this@case_3_1 != null) }
|
||||
if (!(this@case_3_1 != null)) throw Exception()
|
||||
}
|
||||
fun <T : String> T?.case_3_2() {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_3_2() {
|
||||
contract { returns() implies (this@case_3_2 == null) }
|
||||
if (!(this@case_3_2 == null)) throw Exception()
|
||||
}
|
||||
@@ -76,47 +76,47 @@ fun <T : Number> T.case_6_4(): Boolean? {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 7
|
||||
fun <T : String> T?.case_7_1(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_1(): Boolean {
|
||||
contract { returns(true) implies (this@case_7_1 != null) }
|
||||
return this@case_7_1 != null
|
||||
}
|
||||
fun <T : String> T?.case_7_2(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_2(): Boolean {
|
||||
contract { returns(true) implies (this@case_7_2 == null) }
|
||||
return this@case_7_2 == null
|
||||
}
|
||||
fun <T : String> T?.case_7_3(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_3(): Boolean? {
|
||||
contract { returnsNotNull() implies (this@case_7_3 == null) }
|
||||
return if (this@case_7_3 == null) true else null
|
||||
}
|
||||
fun <T : String> T?.case_7_4(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_4(): Boolean? {
|
||||
contract { returns(null) implies (this@case_7_4 == null) }
|
||||
return if (this@case_7_4 == null) null else true
|
||||
}
|
||||
fun <T : String> T?.case_7_5(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_5(): Boolean {
|
||||
contract { returns(false) implies (this@case_7_5 == null) }
|
||||
return !(this@case_7_5 == null)
|
||||
}
|
||||
fun <T : String> T?.case_7_6(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_6(): Boolean? {
|
||||
contract { returnsNotNull() implies (this@case_7_6 != null) }
|
||||
return if (this@case_7_6 != null) true else null
|
||||
}
|
||||
fun <T : String> T?.case_7_7(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_7(): Boolean? {
|
||||
contract { returns(null) implies (this@case_7_7 != null) }
|
||||
return if (this@case_7_7 != null) null else true
|
||||
}
|
||||
fun <T : String> T?.case_7_8(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_8(): Boolean {
|
||||
contract { returns(false) implies (this@case_7_8 != null) }
|
||||
return !(this@case_7_8 != null)
|
||||
}
|
||||
fun <T : String> T?.case_7_9(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_9(): Boolean {
|
||||
contract { returns(false) implies (this@case_7_9 == null) }
|
||||
return !(this@case_7_9 == null)
|
||||
}
|
||||
fun <T : String> T?.case_7_10(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_10(): Boolean? {
|
||||
contract { returnsNotNull() implies (this@case_7_10 == null) }
|
||||
return if (this@case_7_10 == null) true else null
|
||||
}
|
||||
fun <T : String> T?.case_7_11(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_7_11(): Boolean? {
|
||||
contract { returns(null) implies (this@case_7_11 == null) }
|
||||
return if (this@case_7_11 == null) null else true
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
import kotlin.contracts.*
|
||||
|
||||
// TESTCASE NUMBER: 1
|
||||
fun <T : Boolean>T.case_1(): Boolean? {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Boolean<!>>T.case_1(): Boolean? {
|
||||
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns(null) implies (!this@case_1)<!> }
|
||||
return if (!this) null else true
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ fun Boolean?.case_1(): Boolean {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun <T : Boolean>T?.case_2(): Boolean {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Boolean<!>>T?.case_2(): Boolean {
|
||||
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns(true) implies (this@case_2 != null && this@case_2 !is Nothing && this@case_2)<!> }
|
||||
return this != null && this !is Nothing && this
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ fun <T : Number?> T.case_1() {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun <T : Number, K : String> T?.case_2(value_1: K?) {
|
||||
fun <T : Number, K : <!FINAL_UPPER_BOUND!>String<!>> T?.case_2(value_1: K?) {
|
||||
contract { returns() implies (this@case_2 is T && value_1 is K) }
|
||||
if (!(this@case_2 is T && value_1 is K)) throw Exception()
|
||||
}
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ class case_4 : ClassLevel3() {
|
||||
return this == null
|
||||
}
|
||||
|
||||
fun <T : Boolean>T.case_4_2() {
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Boolean<!>>T.case_4_2() {
|
||||
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (!this@case_4_2)<!> }
|
||||
if (this) throw Exception()
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ inline fun <reified T>case_3(x: Any?) {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 4
|
||||
inline fun <reified T : Boolean>case_4(x: Any?) {
|
||||
inline fun <reified T : <!FINAL_UPPER_BOUND!>Boolean<!>>case_4(x: Any?) {
|
||||
if (x is Int is T == null) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>.<!UNRESOLVED_REFERENCE!>inv<!>()
|
||||
|
||||
@@ -97,8 +97,8 @@ fun case_9() {
|
||||
* UNEXPECTED BEHAVIOUR
|
||||
* ISSUES: KT-22175
|
||||
*/
|
||||
fun <T : String> T?.case_10() = this
|
||||
fun <T : Int> T?.case_10() = this
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_10() = this
|
||||
fun <T : <!FINAL_UPPER_BOUND!>Int<!>> T?.case_10() = this
|
||||
fun case_10() {
|
||||
var x: Int? = 10
|
||||
x = null
|
||||
@@ -106,7 +106,7 @@ fun case_10() {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 11
|
||||
fun <T : String> T?.case_11() = this
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> T?.case_11() = this
|
||||
fun case_11() {
|
||||
var x: Int? = 10
|
||||
x = null
|
||||
|
||||
+7
@@ -881,6 +881,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.FINAL_UPPER_BOUND) { firDiagnostic ->
|
||||
FinalUpperBoundImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
||||
ExtensionInClassReferenceNotAllowedImpl(
|
||||
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration),
|
||||
|
||||
+5
@@ -628,6 +628,11 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val typeParameter: KtTypeParameterSymbol
|
||||
}
|
||||
|
||||
abstract class FinalUpperBound : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = FinalUpperBound::class
|
||||
abstract val type: KtType
|
||||
}
|
||||
|
||||
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
||||
abstract val referencedDeclaration: KtCallableSymbol
|
||||
|
||||
+8
@@ -1010,6 +1010,14 @@ internal class TypeParameterAsReifiedImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class FinalUpperBoundImpl(
|
||||
override val type: KtType,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.FinalUpperBound(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExtensionInClassReferenceNotAllowedImpl(
|
||||
override val referencedDeclaration: KtCallableSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
|
||||
Reference in New Issue
Block a user