Opt-in: forbid/deprecate constructor call with default arguments under marker
#KT-55074 Fixed
This commit is contained in:
committed by
Space Team
parent
b92ce68f32
commit
8ddc535caf
+9
-16
@@ -150,13 +150,21 @@ object FirOptInUsageBaseChecker {
|
|||||||
if (fir is FirCallableDeclaration) {
|
if (fir is FirCallableDeclaration) {
|
||||||
val parentClassSymbol = fir.containingClassLookupTag()?.toSymbol(session) as? FirRegularClassSymbol
|
val parentClassSymbol = fir.containingClassLookupTag()?.toSymbol(session) as? FirRegularClassSymbol
|
||||||
if (fir is FirConstructor) {
|
if (fir is FirConstructor) {
|
||||||
|
// For other callable we check dispatch receiver type instead
|
||||||
parentClassSymbol?.loadExperimentalities(
|
parentClassSymbol?.loadExperimentalities(
|
||||||
context, result, visited, fromSetter = false, dispatchReceiverType = null, fromSupertype = false
|
context, result, visited, fromSetter = false, dispatchReceiverType = null, fromSupertype = false
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
fir.loadOverridableSpecificExperimentalities(context, visited, result)
|
// Without coneTypeSafe v fails in MT test (FirRenderer.kt)
|
||||||
|
fir.returnTypeRef.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
|
||||||
|
fir.receiverParameter?.typeRef?.coneType.addExperimentalities(context, result, visited)
|
||||||
}
|
}
|
||||||
dispatchReceiverType?.addExperimentalities(context, result, visited)
|
dispatchReceiverType?.addExperimentalities(context, result, visited)
|
||||||
|
if (fir is FirFunction) {
|
||||||
|
fir.valueParameters.forEach {
|
||||||
|
it.returnTypeRef.coneType.addExperimentalities(context, result, visited)
|
||||||
|
}
|
||||||
|
}
|
||||||
if (fromSetter && this is FirPropertySymbol) {
|
if (fromSetter && this is FirPropertySymbol) {
|
||||||
setterSymbol?.loadExperimentalities(
|
setterSymbol?.loadExperimentalities(
|
||||||
context, result, visited, fromSetter = false, dispatchReceiverType, fromSupertype = false
|
context, result, visited, fromSetter = false, dispatchReceiverType, fromSupertype = false
|
||||||
@@ -194,21 +202,6 @@ object FirOptInUsageBaseChecker {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirCallableDeclaration.loadOverridableSpecificExperimentalities(
|
|
||||||
context: CheckerContext,
|
|
||||||
visited: MutableSet<FirDeclaration>,
|
|
||||||
result: SmartSet<Experimentality>
|
|
||||||
) {
|
|
||||||
// Without coneTypeSafe v fails in MT test (FirRenderer.kt)
|
|
||||||
returnTypeRef.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
|
|
||||||
receiverParameter?.typeRef?.coneType.addExperimentalities(context, result, visited)
|
|
||||||
if (this is FirSimpleFunction) {
|
|
||||||
valueParameters.forEach {
|
|
||||||
it.returnTypeRef.coneType.addExperimentalities(context, result, visited)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ConeKotlinType?.addExperimentalities(
|
private fun ConeKotlinType?.addExperimentalities(
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
result: SmartSet<Experimentality>,
|
result: SmartSet<Experimentality>,
|
||||||
|
|||||||
@@ -224,14 +224,15 @@ class OptInUsageChecker(project: Project) : CallChecker {
|
|||||||
moduleAnnotationsResolver, context, languageVersionSettings, visited
|
moduleAnnotationsResolver, context, languageVersionSettings, visited
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (this is FunctionDescriptor) {
|
}
|
||||||
valueParameters.forEach {
|
if (this is FunctionDescriptor) {
|
||||||
result.addAll(
|
valueParameters.forEach {
|
||||||
it.type.loadOptIns(
|
result.addAll(
|
||||||
moduleAnnotationsResolver, context, languageVersionSettings, visited
|
it.type.loadOptIns(
|
||||||
)
|
moduleAnnotationsResolver, context, languageVersionSettings, visited,
|
||||||
|
warningsOnly = this is ConstructorDescriptor
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,19 +259,20 @@ class OptInUsageChecker(project: Project) : CallChecker {
|
|||||||
moduleAnnotationsResolver: ModuleAnnotationsResolver,
|
moduleAnnotationsResolver: ModuleAnnotationsResolver,
|
||||||
context: BindingContext,
|
context: BindingContext,
|
||||||
languageVersionSettings: LanguageVersionSettings,
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
visitedClassifiers: MutableSet<DeclarationDescriptor>
|
visitedClassifiers: MutableSet<DeclarationDescriptor>,
|
||||||
|
warningsOnly: Boolean = false
|
||||||
): Set<OptInDescription> =
|
): Set<OptInDescription> =
|
||||||
when {
|
when {
|
||||||
this?.isError != false -> emptySet()
|
this?.isError != false -> emptySet()
|
||||||
this is AbbreviatedType -> abbreviation.constructor.declarationDescriptor?.loadOptIns(
|
this is AbbreviatedType -> abbreviation.constructor.declarationDescriptor?.loadOptIns(
|
||||||
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers,
|
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers,
|
||||||
useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures)
|
useFutureError = warningsOnly || !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures)
|
||||||
).orEmpty() + expandedType.loadOptIns(
|
).orEmpty() + expandedType.loadOptIns(
|
||||||
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers
|
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers
|
||||||
)
|
)
|
||||||
else -> constructor.declarationDescriptor?.loadOptIns(
|
else -> constructor.declarationDescriptor?.loadOptIns(
|
||||||
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers,
|
moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers,
|
||||||
useFutureError = !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures)
|
useFutureError = warningsOnly || !languageVersionSettings.supportsFeature(LanguageFeature.OptInContagiousSignatures)
|
||||||
).orEmpty() + arguments.flatMap {
|
).orEmpty() + arguments.flatMap {
|
||||||
if (it.isStarProjection) emptySet()
|
if (it.isStarProjection) emptySet()
|
||||||
else it.type.loadOptIns(moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers)
|
else it.type.loadOptIns(moduleAnnotationsResolver, context, languageVersionSettings, visitedClassifiers)
|
||||||
|
|||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
@RequiresOptIn
|
||||||
|
annotation class Marker
|
||||||
|
|
||||||
|
@Marker
|
||||||
|
class Some(val x: Int)
|
||||||
|
|
||||||
|
class Other(val x: Int) {
|
||||||
|
@OptIn(Marker::class)
|
||||||
|
constructor(some: Some): this(some.x)
|
||||||
|
|
||||||
|
@Marker
|
||||||
|
constructor(): this(42)
|
||||||
|
|
||||||
|
@OptIn(Marker::class)
|
||||||
|
constructor(y: Long, some: Some? = null): this(some?.x ?: y.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(some: <!OPT_IN_USAGE_ERROR!>Some<!>? = null) {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val o1 = <!OPT_IN_USAGE_ERROR!>Other<!>()
|
||||||
|
val o2 = <!OPT_IN_USAGE_ERROR!>Other<!>(<!OPT_IN_USAGE_ERROR!>Some<!>(0))
|
||||||
|
val o3 = <!OPT_IN_USAGE_ERROR!>Other<!>(444L)
|
||||||
|
<!OPT_IN_USAGE_ERROR!>foo<!>()
|
||||||
|
<!OPT_IN_USAGE_ERROR!>foo<!>(null)
|
||||||
|
}
|
||||||
+6
-3
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
@RequiresOptIn
|
@RequiresOptIn
|
||||||
annotation class Marker
|
annotation class Marker
|
||||||
|
|
||||||
@@ -16,8 +15,12 @@ class Other(val x: Int) {
|
|||||||
constructor(y: Long, some: Some? = null): this(some?.x ?: y.toInt())
|
constructor(y: Long, some: Some? = null): this(some?.x ?: y.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun foo(some: <!OPT_IN_USAGE_ERROR!>Some<!>? = null) {}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val o1 = <!OPT_IN_USAGE_ERROR!>Other<!>()
|
val o1 = <!OPT_IN_USAGE_ERROR!>Other<!>()
|
||||||
val o2 = Other(<!OPT_IN_USAGE_ERROR!>Some<!>(0))
|
val o2 = <!OPT_IN_USAGE_FUTURE_ERROR!>Other<!>(<!OPT_IN_USAGE_ERROR!>Some<!>(0))
|
||||||
val o3 = Other(444L)
|
val o3 = <!OPT_IN_USAGE_FUTURE_ERROR!>Other<!>(444L)
|
||||||
|
<!OPT_IN_USAGE_ERROR!>foo<!>()
|
||||||
|
<!OPT_IN_USAGE_ERROR!>foo<!>(null)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -1,5 +1,6 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ some: Some? = ...): kotlin.Unit
|
||||||
public fun test(): kotlin.Unit
|
public fun test(): kotlin.Unit
|
||||||
|
|
||||||
@kotlin.RequiresOptIn public final annotation class Marker : kotlin.Annotation {
|
@kotlin.RequiresOptIn public final annotation class Marker : kotlin.Annotation {
|
||||||
|
|||||||
Reference in New Issue
Block a user