[FIR] Add CYCLIC_GENERIC_UPPER_BOUND check
This commit is contained in:
committed by
TeamCityServer
parent
03215f4e0a
commit
2b8c22c08a
@@ -9,9 +9,9 @@ interface B {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface G<X> {
|
interface G<X> {
|
||||||
val <X> boo: Double where X : A, X : B
|
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>X<!>> boo: Double where X : A, X : B
|
||||||
val <A> bal: Double where A : B
|
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>A<!>> bal: Double where A : B
|
||||||
val <Y> bas: Double where Y : B, <!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>X<!> : B
|
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>Y<!>> bas: Double where Y : B, <!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>X<!> : B
|
||||||
}
|
}
|
||||||
|
|
||||||
class C() : A(), B
|
class C() : A(), B
|
||||||
@@ -66,4 +66,4 @@ val t1 = test2<A>(<!ARGUMENT_TYPE_MISMATCH!>A()<!>)
|
|||||||
val t2 = test2<B>(<!ARGUMENT_TYPE_MISMATCH!>C()<!>)
|
val t2 = test2<B>(<!ARGUMENT_TYPE_MISMATCH!>C()<!>)
|
||||||
val t3 = test2<C>(C())
|
val t3 = test2<C>(C())
|
||||||
|
|
||||||
val <T, B : T> x : Int = 0
|
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>T<!>, <!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>B : T<!>> x : Int = 0
|
||||||
|
|||||||
+2
@@ -330,6 +330,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
parameter<ConeKotlinType>("expected")
|
parameter<ConeKotlinType>("expected")
|
||||||
parameter<ConeKotlinType>("actual")
|
parameter<ConeKotlinType>("actual")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val CYCLIC_GENERIC_UPPER_BOUND by error<FirSourceElement, PsiElement>()
|
||||||
}
|
}
|
||||||
|
|
||||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ object FirErrors {
|
|||||||
val TYPE_PARAMETERS_NOT_ALLOWED by error0<FirSourceElement, KtDeclaration>()
|
val TYPE_PARAMETERS_NOT_ALLOWED by error0<FirSourceElement, KtDeclaration>()
|
||||||
val TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER by error0<FirSourceElement, KtTypeParameter>()
|
val TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER by error0<FirSourceElement, KtTypeParameter>()
|
||||||
val RETURN_TYPE_MISMATCH by error2<FirSourceElement, KtExpression, ConeKotlinType, ConeKotlinType>(SourceElementPositioningStrategies.WHOLE_ELEMENT)
|
val RETURN_TYPE_MISMATCH by error2<FirSourceElement, KtExpression, ConeKotlinType, ConeKotlinType>(SourceElementPositioningStrategies.WHOLE_ELEMENT)
|
||||||
|
val CYCLIC_GENERIC_UPPER_BOUND by error0<FirSourceElement, PsiElement>()
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<FirSourceElement, KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<FirSourceElement, KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
|||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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 kotlinx.collections.immutable.PersistentList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
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.resolve.diagnostics.ConeCyclicTypeBound
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
|
object FirCyclicTypeBoundsChecker : FirMemberDeclarationChecker() {
|
||||||
|
|
||||||
|
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration is FirConstructor || declaration is FirTypeAlias) return
|
||||||
|
|
||||||
|
val processed = mutableSetOf<Name>()
|
||||||
|
val cycles = mutableSetOf<Name>()
|
||||||
|
val graph = declaration.typeParameters.map { param ->
|
||||||
|
param.symbol.name to param.symbol.fir.bounds.flatMap { extractTypeParamNames(it) }.toSet()
|
||||||
|
}.toMap()
|
||||||
|
|
||||||
|
declaration.typeParameters.forEach { param ->
|
||||||
|
if (!processed.contains(param.symbol.name)) {
|
||||||
|
findCycles(
|
||||||
|
persistentListOf(),
|
||||||
|
param.symbol.name,
|
||||||
|
processed,
|
||||||
|
mutableSetOf(),
|
||||||
|
cycles
|
||||||
|
) { name -> graph.getOrDefault(name, emptySet()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cycles.isNotEmpty()) {
|
||||||
|
declaration.typeParameters
|
||||||
|
.filter { cycles.contains(it.symbol.name) }
|
||||||
|
.forEach { param ->
|
||||||
|
val targets = if (declaration is FirRegularClass) {
|
||||||
|
param.symbol.fir.originalBounds().filter { cycles.contains(extractTypeParamName(it.coneType)) }
|
||||||
|
.mapNotNull { it.source }
|
||||||
|
} else {
|
||||||
|
listOf(param.source)
|
||||||
|
}
|
||||||
|
targets.forEach {
|
||||||
|
reporter.reportOn(it, FirErrors.CYCLIC_GENERIC_UPPER_BOUND, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirTypeParameter.originalBounds() = bounds.flatMap { it.unwrapBound() }
|
||||||
|
|
||||||
|
private fun FirTypeRef.unwrapBound(): List<FirTypeRef> =
|
||||||
|
if (this is FirErrorTypeRef && diagnostic is ConeCyclicTypeBound) {
|
||||||
|
(diagnostic as ConeCyclicTypeBound).bounds
|
||||||
|
} else {
|
||||||
|
listOf(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun extractTypeParamNames(ref: FirTypeRef): Set<Name> =
|
||||||
|
ref.unwrapBound().mapNotNull { extractTypeParamName(it.coneType) }.toSet()
|
||||||
|
|
||||||
|
private fun extractTypeParamName(type: ConeKotlinType): Name? = type.safeAs<ConeTypeParameterType>()?.lookupTag?.name
|
||||||
|
|
||||||
|
private fun findCycles(
|
||||||
|
path: PersistentList<Name>,
|
||||||
|
node: Name,
|
||||||
|
processed: MutableSet<Name>,
|
||||||
|
visited: MutableSet<Name>,
|
||||||
|
cycles: MutableSet<Name>,
|
||||||
|
graph: (Name) -> Set<Name>
|
||||||
|
) {
|
||||||
|
processed.add(node)
|
||||||
|
if (visited.add(node)) {
|
||||||
|
val newPath = path.add(node)
|
||||||
|
graph(node).forEach { nextNode ->
|
||||||
|
findCycles(newPath, nextNode, processed, visited, cycles, graph)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cycles.addAll(path.dropWhile { it != node })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+3
@@ -70,6 +70,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_DE
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_GETTER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_GETTER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NON_CONST_INITIALIZER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NON_CONST_INITIALIZER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS
|
||||||
@@ -509,6 +510,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
|
|
||||||
map.put(RETURN_TYPE_MISMATCH, "Return type mismatch: expected {0}, actual {1}", RENDER_TYPE, RENDER_TYPE)
|
map.put(RETURN_TYPE_MISMATCH, "Return type mismatch: expected {0}, actual {1}", RENDER_TYPE, RENDER_TYPE)
|
||||||
|
|
||||||
|
map.put(CYCLIC_GENERIC_UPPER_BOUND, "Type parameter has cyclic upper bounds")
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
map.put(
|
map.put(
|
||||||
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
||||||
|
|||||||
+1
@@ -26,6 +26,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirExposedVisibilityDeclarationChecker,
|
FirExposedVisibilityDeclarationChecker,
|
||||||
FirSealedSupertypeChecker,
|
FirSealedSupertypeChecker,
|
||||||
FirTypeAliasChecker,
|
FirTypeAliasChecker,
|
||||||
|
FirCyclicTypeBoundsChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val functionCheckers: Set<FirFunctionChecker> = setOf(
|
override val functionCheckers: Set<FirFunctionChecker> = setOf(
|
||||||
|
|||||||
+6
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.diagnostics
|
package org.jetbrains.kotlin.fir.resolve.diagnostics
|
||||||
|
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||||
@@ -114,6 +116,10 @@ class ConeTypeParameterInQualifiedAccess(val symbol: FirTypeParameterSymbol) : C
|
|||||||
override val reason: String get() = "Type parameter ${symbol.fir.name} in qualified access"
|
override val reason: String get() = "Type parameter ${symbol.fir.name} in qualified access"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ConeCyclicTypeBound(val symbol: FirTypeParameterSymbol, val bounds: ImmutableList<FirTypeRef>) : ConeDiagnostic() {
|
||||||
|
override val reason: String get() = "Type parameter ${symbol.fir.name} has cyclic bounds"
|
||||||
|
}
|
||||||
|
|
||||||
private fun describeSymbol(symbol: AbstractFirBasedSymbol<*>): String {
|
private fun describeSymbol(symbol: AbstractFirBasedSymbol<*>): String {
|
||||||
return when (symbol) {
|
return when (symbol) {
|
||||||
is FirClassLikeSymbol<*> -> symbol.classId.asString()
|
is FirClassLikeSymbol<*> -> symbol.classId.asString()
|
||||||
|
|||||||
+7
-2
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||||
|
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
@@ -12,9 +13,11 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeCyclicTypeBound
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||||
|
|
||||||
class FirTypeResolveProcessor(
|
class FirTypeResolveProcessor(
|
||||||
@@ -140,9 +143,11 @@ class FirTypeResolveTransformer(
|
|||||||
for (typeParameter in typeParametersOwner.typeParameters) {
|
for (typeParameter in typeParametersOwner.typeParameters) {
|
||||||
if (typeParameter !is FirTypeParameter) continue
|
if (typeParameter !is FirTypeParameter) continue
|
||||||
if (hasSupertypePathToParameter(typeParameter, typeParameter, mutableSetOf())) {
|
if (hasSupertypePathToParameter(typeParameter, typeParameter, mutableSetOf())) {
|
||||||
// TODO: Report diagnostic somewhere
|
val errorType = buildErrorTypeRef {
|
||||||
|
diagnostic = ConeCyclicTypeBound(typeParameter.symbol, typeParameter.bounds.toImmutableList())
|
||||||
|
}
|
||||||
typeParameter.replaceBounds(
|
typeParameter.replaceBounds(
|
||||||
listOf(session.builtinTypes.nullableAnyType)
|
listOf(errorType)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
fun <T : F?, F : T?> foo1() {}
|
|
||||||
|
|
||||||
fun <T : F?, F : E, E : F?> foo2() {}
|
|
||||||
|
|
||||||
fun <T, F> foo3() where T : F?, F : T {}
|
|
||||||
|
|
||||||
fun <T, F, E> foo4() where T : F?, F : E, E : F? {}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T : F?<!>, <!CYCLIC_GENERIC_UPPER_BOUND!>F : T?<!>> foo1() {}
|
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T : F?<!>, <!CYCLIC_GENERIC_UPPER_BOUND!>F : T?<!>> foo1() {}
|
||||||
|
|
||||||
fun <T : F?, <!CYCLIC_GENERIC_UPPER_BOUND!>F : E<!>, <!CYCLIC_GENERIC_UPPER_BOUND!>E : F?<!>> foo2() {}
|
fun <T : F?, <!CYCLIC_GENERIC_UPPER_BOUND!>F : E<!>, <!CYCLIC_GENERIC_UPPER_BOUND!>E : F?<!>> foo2() {}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
class A1<T : F?, F : T?>
|
|
||||||
|
|
||||||
class A2<T : F?, F : E, E : F?>
|
|
||||||
|
|
||||||
class A3<T, F> where T : F?, F : T?
|
|
||||||
|
|
||||||
class A4<T, F, E> where T : F?, F : E, E : F
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
class A1<T : <!CYCLIC_GENERIC_UPPER_BOUND!>F?<!>, F : <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>>
|
class A1<T : <!CYCLIC_GENERIC_UPPER_BOUND!>F?<!>, F : <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>>
|
||||||
|
|
||||||
class A2<T : F?, F : <!CYCLIC_GENERIC_UPPER_BOUND!>E<!>, E : <!CYCLIC_GENERIC_UPPER_BOUND!>F?<!>>
|
class A2<T : F?, F : <!CYCLIC_GENERIC_UPPER_BOUND!>E<!>, E : <!CYCLIC_GENERIC_UPPER_BOUND!>F?<!>>
|
||||||
|
|||||||
Vendored
+1
-1
@@ -7,7 +7,7 @@ interface Foo<F> {
|
|||||||
|
|
||||||
fun <S> select(vararg args: S): S = TODO()
|
fun <S> select(vararg args: S): S = TODO()
|
||||||
|
|
||||||
class Bar<B : B> : Foo<B> {
|
class Bar<B : <!CYCLIC_GENERIC_UPPER_BOUND!>B<!>> : Foo<B> {
|
||||||
val v = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>select(
|
val v = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>select(
|
||||||
getSum(),
|
getSum(),
|
||||||
42
|
42
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
|
||||||
fun <T: T?> foo() {}
|
|
||||||
val <T: T?> prop
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
// !DIAGNOSTICS: -MUST_BE_INITIALIZED -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
||||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> foo() {}
|
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> foo() {}
|
||||||
val <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> prop
|
val <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> prop
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
class MyClass<T: T?>
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
class MyClass<T: <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>>
|
class MyClass<T: <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>>
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
class MyClass<T: T>
|
|
||||||
+1
@@ -1 +1,2 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
class MyClass<T: <!CYCLIC_GENERIC_UPPER_BOUND!>T<!>>
|
class MyClass<T: <!CYCLIC_GENERIC_UPPER_BOUND!>T<!>>
|
||||||
-5
@@ -1,5 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED_OR_BE_ABSTRACT -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
|
||||||
class My {
|
|
||||||
fun <T: T?> foo() {}
|
|
||||||
val <T: T?> prop: T
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED_OR_BE_ABSTRACT -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
// !DIAGNOSTICS: -MUST_BE_INITIALIZED_OR_BE_ABSTRACT -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
||||||
class My {
|
class My {
|
||||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> foo() {}
|
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> foo() {}
|
||||||
|
|||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
|
||||||
fun <T: T> foo() {}
|
|
||||||
val <T: T?> prop: T
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
// !DIAGNOSTICS: -MUST_BE_INITIALIZED -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
||||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T<!>> foo() {}
|
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T<!>> foo() {}
|
||||||
val <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> prop: T
|
val <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> prop: T
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// !LANGUAGE: +NewInference
|
// !LANGUAGE: +NewInference
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
class Base<T : T> : HashSet<T>() {
|
class Base<T : <!CYCLIC_GENERIC_UPPER_BOUND!>T<!>> : HashSet<T>() {
|
||||||
fun foo() {
|
fun foo() {
|
||||||
super.remove(<!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
super.remove(<!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -1018,6 +1018,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.CYCLIC_GENERIC_UPPER_BOUND) { firDiagnostic ->
|
||||||
|
CyclicGenericUpperBoundImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
||||||
ExtensionInClassReferenceNotAllowedImpl(
|
ExtensionInClassReferenceNotAllowedImpl(
|
||||||
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration),
|
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration),
|
||||||
|
|||||||
+4
@@ -723,6 +723,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val actual: KtType
|
abstract val actual: KtType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class CyclicGenericUpperBound : KtFirDiagnostic<KtTypeParameter>() {
|
||||||
|
override val diagnosticClass get() = CyclicGenericUpperBound::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
||||||
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
||||||
abstract val referencedDeclaration: KtCallableSymbol
|
abstract val referencedDeclaration: KtCallableSymbol
|
||||||
|
|||||||
+7
@@ -1168,6 +1168,13 @@ internal class ReturnTypeMismatchImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class CyclicGenericUpperBoundImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.CyclicGenericUpperBound(), KtAbstractFirDiagnostic<KtTypeParameter> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class ExtensionInClassReferenceNotAllowedImpl(
|
internal class ExtensionInClassReferenceNotAllowedImpl(
|
||||||
override val referencedDeclaration: KtCallableSymbol,
|
override val referencedDeclaration: KtCallableSymbol,
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
|||||||
Reference in New Issue
Block a user