[K2] Disappeared OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN (1)
Added error propagation for the type-aliased type. ^KT-59998
This commit is contained in:
committed by
Space Team
parent
5c7b586dbb
commit
445ed7abc9
+28
-13
@@ -8,18 +8,21 @@ package org.jetbrains.kotlin.fir.analysis.checkers.type
|
|||||||
import org.jetbrains.kotlin.KtRealSourceElementKind
|
import org.jetbrains.kotlin.KtRealSourceElementKind
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.loadExperimentalities
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.loadExperimentalitiesFromSupertype
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
|
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
@@ -30,18 +33,18 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
|
|||||||
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val source = typeRef.source
|
val source = typeRef.source
|
||||||
if (source?.kind !is KtRealSourceElementKind) return
|
if (source?.kind !is KtRealSourceElementKind) return
|
||||||
// coneTypeSafe filters out all delegatedTypeRefs from here
|
|
||||||
val coneType = typeRef.coneTypeSafe<ConeClassLikeType>() ?: return
|
val coneType = typeRef.coneTypeSafe<ConeClassLikeType>() ?: return
|
||||||
|
val symbol = typeRef.findSymbol(context.session) ?: return
|
||||||
|
|
||||||
val symbol = coneType.lookupTag.toSymbol(context.session) ?: return
|
val typeAliasExpandedSymbol = (symbol as? FirTypeAliasSymbol)?.resolvedExpandedTypeRef?.findSymbol(context.session)
|
||||||
symbol.lazyResolveToPhase(FirResolvePhase.STATUS)
|
val processedSymbol = typeAliasExpandedSymbol ?: symbol
|
||||||
val classId = symbol.classId
|
val classId = processedSymbol.classId
|
||||||
val lastAnnotationCall = context.callsOrAssignments.lastOrNull() as? FirAnnotation
|
val lastAnnotationCall = context.callsOrAssignments.lastOrNull() as? FirAnnotation
|
||||||
if (lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) {
|
if (lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) {
|
||||||
if (classId == OptInNames.REQUIRES_OPT_IN_CLASS_ID || classId == OptInNames.OPT_IN_CLASS_ID) {
|
if (classId == OptInNames.REQUIRES_OPT_IN_CLASS_ID || classId == OptInNames.OPT_IN_CLASS_ID) {
|
||||||
reporter.reportOn(source, OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
|
reporter.reportOn(source, OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
|
||||||
} else if (symbol is FirRegularClassSymbol &&
|
} else if (processedSymbol is FirRegularClassSymbol &&
|
||||||
symbol.fir.getAnnotationByClassId(OptInNames.REQUIRES_OPT_IN_CLASS_ID, context.session) != null
|
processedSymbol.fir.getAnnotationByClassId(OptInNames.REQUIRES_OPT_IN_CLASS_ID, context.session) != null
|
||||||
) {
|
) {
|
||||||
reporter.reportOn(source, OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN, context)
|
reporter.reportOn(source, OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN, context)
|
||||||
}
|
}
|
||||||
@@ -49,12 +52,24 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
|
|||||||
|
|
||||||
val isSupertypeRef = typeRef in (context.containingDeclarations.lastOrNull() as? FirClass)?.superTypeRefs.orEmpty()
|
val isSupertypeRef = typeRef in (context.containingDeclarations.lastOrNull() as? FirClass)?.superTypeRefs.orEmpty()
|
||||||
with(FirOptInUsageBaseChecker) {
|
with(FirOptInUsageBaseChecker) {
|
||||||
val classifierExperimentalities =
|
val experimentalities = mutableSetOf<FirOptInUsageBaseChecker.Experimentality>()
|
||||||
if (isSupertypeRef) symbol.loadExperimentalitiesFromSupertype(context)
|
experimentalities.addAll(symbol.loadClassifierExperimentalities(context, isSupertypeRef))
|
||||||
else symbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType = null)
|
if (typeAliasExpandedSymbol != null) experimentalities.addAll(typeAliasExpandedSymbol.loadClassifierExperimentalities(context, isSupertypeRef))
|
||||||
val experimentalities =
|
experimentalities.addAll(loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList()))
|
||||||
classifierExperimentalities + loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList())
|
|
||||||
reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirClassLikeSymbol<*>.loadClassifierExperimentalities(context: CheckerContext, isSupertypeRef: Boolean) =
|
||||||
|
if (isSupertypeRef) loadExperimentalitiesFromSupertype(context) else loadExperimentalities(
|
||||||
|
context,
|
||||||
|
fromSetter = false,
|
||||||
|
dispatchReceiverType = null
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun FirTypeRef.findSymbol(session: FirSession): FirClassLikeSymbol<*>? {
|
||||||
|
// coneTypeSafe filters out all delegatedTypeRefs from here
|
||||||
|
val coneType = coneTypeSafe<ConeClassLikeType>() ?: return null
|
||||||
|
return coneType.lookupTag.toSymbol(session)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -32,7 +32,7 @@ fun useDataClass(d: DataClass) {
|
|||||||
|
|
||||||
typealias My = <!OPT_IN_USAGE_ERROR!>Some<!>
|
typealias My = <!OPT_IN_USAGE_ERROR!>Some<!>
|
||||||
|
|
||||||
fun my(my: My) {}
|
fun my(my: <!OPT_IN_USAGE_ERROR!>My<!>) {}
|
||||||
|
|
||||||
fun your(my: <!OPT_IN_USAGE_ERROR!>Some<!>) {}
|
fun your(my: <!OPT_IN_USAGE_ERROR!>Some<!>) {}
|
||||||
|
|
||||||
@@ -70,6 +70,10 @@ typealias AList = ArrayList<I>
|
|||||||
@Marker
|
@Marker
|
||||||
typealias YourList = ArrayList<String>
|
typealias YourList = ArrayList<String>
|
||||||
|
|
||||||
|
fun my2(my: MyList) {}
|
||||||
|
|
||||||
|
fun my3(my: <!OPT_IN_USAGE_ERROR!>YourList<!>) {}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val x = <!OPT_IN_USAGE_ERROR!>listOf<!>(A(), B())
|
val x = <!OPT_IN_USAGE_ERROR!>listOf<!>(A(), B())
|
||||||
val y = MyList()
|
val y = MyList()
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ typealias AList = ArrayList<I>
|
|||||||
@Marker
|
@Marker
|
||||||
typealias YourList = ArrayList<String>
|
typealias YourList = ArrayList<String>
|
||||||
|
|
||||||
|
fun my2(my: <!OPT_IN_USAGE_ERROR!>MyList<!>) {}
|
||||||
|
|
||||||
|
fun my3(my: <!OPT_IN_USAGE_ERROR!>YourList<!>) {}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val x = <!OPT_IN_USAGE_ERROR!>listOf<!>(A(), B())
|
val x = <!OPT_IN_USAGE_ERROR!>listOf<!>(A(), B())
|
||||||
val y = <!OPT_IN_USAGE_ERROR!>MyList<!>()
|
val y = <!OPT_IN_USAGE_ERROR!>MyList<!>()
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package
|
|||||||
public val x: kotlin.String
|
public val x: kotlin.String
|
||||||
public fun main(): kotlin.Unit
|
public fun main(): kotlin.Unit
|
||||||
public fun my(/*0*/ my: My /* = Some */): kotlin.Unit
|
public fun my(/*0*/ my: My /* = Some */): kotlin.Unit
|
||||||
|
public fun my2(/*0*/ my: MyList /* = java.util.ArrayList<I> */): kotlin.Unit
|
||||||
|
public fun my3(/*0*/ my: YourList /* = java.util.ArrayList<kotlin.String> */): kotlin.Unit
|
||||||
public fun operatorContainerUsage(/*0*/ s: kotlin.String, /*1*/ a: AnotherContainer): kotlin.Unit
|
public fun operatorContainerUsage(/*0*/ s: kotlin.String, /*1*/ a: AnotherContainer): kotlin.Unit
|
||||||
public fun use(/*0*/ arg: NotExperimentalExtension): kotlin.Unit
|
public fun use(/*0*/ arg: NotExperimentalExtension): kotlin.Unit
|
||||||
public fun useDataClass(/*0*/ d: DataClass): kotlin.Unit
|
public fun useDataClass(/*0*/ d: DataClass): kotlin.Unit
|
||||||
|
|||||||
+5
-1
@@ -32,7 +32,7 @@ fun useDataClass(d: DataClass) {
|
|||||||
|
|
||||||
typealias My = <!OPT_IN_USAGE_ERROR!>Some<!>
|
typealias My = <!OPT_IN_USAGE_ERROR!>Some<!>
|
||||||
|
|
||||||
fun my(my: My) {}
|
fun my(my: <!OPT_IN_USAGE_ERROR!>My<!>) {}
|
||||||
|
|
||||||
fun your(my: <!OPT_IN_USAGE_ERROR!>Some<!>) {}
|
fun your(my: <!OPT_IN_USAGE_ERROR!>Some<!>) {}
|
||||||
|
|
||||||
@@ -78,6 +78,10 @@ fun main() {
|
|||||||
<!OPT_IN_USAGE_ERROR!>YourList<!>().add("")
|
<!OPT_IN_USAGE_ERROR!>YourList<!>().add("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun my2(my: MyList) {}
|
||||||
|
|
||||||
|
fun my3(my: <!OPT_IN_USAGE_ERROR!>YourList<!>) {}
|
||||||
|
|
||||||
@Marker
|
@Marker
|
||||||
class C {
|
class C {
|
||||||
operator fun getValue(x: Any?, y: Any?): String = ""
|
operator fun getValue(x: Any?, y: Any?): String = ""
|
||||||
|
|||||||
+4
@@ -78,6 +78,10 @@ fun main() {
|
|||||||
<!OPT_IN_USAGE_FUTURE_ERROR!>YourList<!>().add("")
|
<!OPT_IN_USAGE_FUTURE_ERROR!>YourList<!>().add("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun my2(my: <!OPT_IN_USAGE_FUTURE_ERROR!>MyList<!>) {}
|
||||||
|
|
||||||
|
fun my3(my: <!OPT_IN_USAGE_ERROR!>YourList<!>) {}
|
||||||
|
|
||||||
@Marker
|
@Marker
|
||||||
class C {
|
class C {
|
||||||
operator fun getValue(x: Any?, y: Any?): String = ""
|
operator fun getValue(x: Any?, y: Any?): String = ""
|
||||||
|
|||||||
+2
@@ -3,6 +3,8 @@ package
|
|||||||
public val x: kotlin.String
|
public val x: kotlin.String
|
||||||
public fun main(): kotlin.Unit
|
public fun main(): kotlin.Unit
|
||||||
public fun my(/*0*/ my: My /* = Some */): kotlin.Unit
|
public fun my(/*0*/ my: My /* = Some */): kotlin.Unit
|
||||||
|
public fun my2(/*0*/ my: MyList /* = java.util.ArrayList<I> */): kotlin.Unit
|
||||||
|
public fun my3(/*0*/ my: YourList /* = java.util.ArrayList<kotlin.String> */): kotlin.Unit
|
||||||
public fun operatorContainerUsage(/*0*/ s: kotlin.String, /*1*/ a: AnotherContainer): kotlin.Unit
|
public fun operatorContainerUsage(/*0*/ s: kotlin.String, /*1*/ a: AnotherContainer): kotlin.Unit
|
||||||
public fun use(/*0*/ arg: NotExperimentalExtension): kotlin.Unit
|
public fun use(/*0*/ arg: NotExperimentalExtension): kotlin.Unit
|
||||||
public fun useDataClass(/*0*/ d: DataClass): kotlin.Unit
|
public fun useDataClass(/*0*/ d: DataClass): kotlin.Unit
|
||||||
|
|||||||
+3
-3
@@ -26,8 +26,8 @@ fun f2(u: <!OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION!>OptIn?<!>) {}
|
|||||||
|
|
||||||
typealias Experimental0 = <!OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION!>RequiresOptIn<!>
|
typealias Experimental0 = <!OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION!>RequiresOptIn<!>
|
||||||
typealias OptIn0 = <!OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION!>OptIn<!>
|
typealias OptIn0 = <!OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION!>OptIn<!>
|
||||||
fun f3(e: Experimental0 /* TODO */) {}
|
fun f3(e: <!OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION!>Experimental0<!> /* TODO */) {}
|
||||||
fun f4(u: OptIn0 /* TODO */) {}
|
fun f4(u: <!OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION!>OptIn0<!> /* TODO */) {}
|
||||||
|
|
||||||
|
|
||||||
// Usages as ::class literals should be errors
|
// Usages as ::class literals should be errors
|
||||||
@@ -60,7 +60,7 @@ fun f8(): <!OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN!>
|
|||||||
|
|
||||||
typealias Marker0 = <!OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN!>Marker<!>
|
typealias Marker0 = <!OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN!>Marker<!>
|
||||||
|
|
||||||
fun f9(m: Marker0) {}
|
fun f9(m: <!OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN!>Marker0<!>) {}
|
||||||
|
|
||||||
|
|
||||||
// Usages of markers as qualifiers are errors as well (we can lift this restriction for select cases)
|
// Usages of markers as qualifiers are errors as well (we can lift this restriction for select cases)
|
||||||
|
|||||||
Reference in New Issue
Block a user