[FIR] Fix false positive USELESS_CAST on stub types, ^KT-50293 Fixed
This commit is contained in:
+5
-1
@@ -38,7 +38,11 @@ object FirUselessTypeOperationCallChecker : FirTypeOperatorCallChecker() {
|
||||
when (expression.operation) {
|
||||
FirOperation.IS -> reporter.reportOn(expression.source, FirErrors.USELESS_IS_CHECK, true, context)
|
||||
FirOperation.NOT_IS -> reporter.reportOn(expression.source, FirErrors.USELESS_IS_CHECK, false, context)
|
||||
FirOperation.AS, FirOperation.SAFE_AS -> reporter.reportOn(expression.source, FirErrors.USELESS_CAST, context)
|
||||
FirOperation.AS, FirOperation.SAFE_AS -> {
|
||||
if ((arg.typeRef as? FirResolvedTypeRef)?.isFromStubType != true) {
|
||||
reporter.reportOn(expression.source, FirErrors.USELESS_CAST, context)
|
||||
}
|
||||
}
|
||||
else -> throw AssertionError("Should not be here: ${expression.operation}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +322,7 @@ fun FirTypeRef.withReplacedConeType(
|
||||
type = newType
|
||||
annotations += this@withReplacedConeType.annotations
|
||||
delegatedTypeRef = this@withReplacedConeType.delegatedTypeRef
|
||||
isFromStubType = this@withReplacedConeType.type is ConeStubType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ internal class FirErrorFunctionImpl(
|
||||
override val symbol: FirErrorFunctionSymbol,
|
||||
) : FirErrorFunction() {
|
||||
override var status: FirDeclarationStatus = FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
|
||||
override var returnTypeRef: FirTypeRef = FirErrorTypeRefImpl(null, null, diagnostic)
|
||||
override var returnTypeRef: FirTypeRef = FirErrorTypeRefImpl(null, null, diagnostic, false)
|
||||
override val receiverTypeRef: FirTypeRef? get() = null
|
||||
override var controlFlowGraphReference: FirControlFlowGraphReference? = null
|
||||
override val body: FirBlock? get() = null
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ internal class FirErrorPropertyImpl(
|
||||
) : FirErrorProperty() {
|
||||
override val typeParameters: List<FirTypeParameterRef> get() = emptyList()
|
||||
override var status: FirDeclarationStatus = FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
|
||||
override var returnTypeRef: FirTypeRef = FirErrorTypeRefImpl(null, null, diagnostic)
|
||||
override var returnTypeRef: FirTypeRef = FirErrorTypeRefImpl(null, null, diagnostic, false)
|
||||
override val receiverTypeRef: FirTypeRef? get() = null
|
||||
override val initializer: FirExpression? get() = null
|
||||
override val delegate: FirExpression? get() = null
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ internal class FirErrorExpressionImpl(
|
||||
override val diagnostic: ConeDiagnostic,
|
||||
override var expression: FirExpression?,
|
||||
) : FirErrorExpression() {
|
||||
override var typeRef: FirTypeRef = FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic))
|
||||
override var typeRef: FirTypeRef = FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic), false)
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
typeRef.accept(visitor, data)
|
||||
|
||||
@@ -22,6 +22,7 @@ abstract class FirErrorTypeRef : FirResolvedTypeRef(), FirDiagnosticHolder {
|
||||
abstract override val annotations: List<FirAnnotation>
|
||||
abstract override val type: ConeKotlinType
|
||||
abstract override val delegatedTypeRef: FirTypeRef?
|
||||
abstract override val isFromStubType: Boolean
|
||||
abstract override val diagnostic: ConeDiagnostic
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitErrorTypeRef(this, data)
|
||||
|
||||
@@ -20,6 +20,7 @@ abstract class FirResolvedTypeRef : FirTypeRef() {
|
||||
abstract override val annotations: List<FirAnnotation>
|
||||
abstract val type: ConeKotlinType
|
||||
abstract val delegatedTypeRef: FirTypeRef?
|
||||
abstract val isFromStubType: Boolean
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedTypeRef(this, data)
|
||||
|
||||
|
||||
+3
@@ -30,6 +30,7 @@ class FirResolvedTypeRefBuilder : FirAnnotationContainerBuilder {
|
||||
override val annotations: MutableList<FirAnnotation> = mutableListOf()
|
||||
lateinit var type: ConeKotlinType
|
||||
var delegatedTypeRef: FirTypeRef? = null
|
||||
var isFromStubType: Boolean = false
|
||||
|
||||
@OptIn(FirImplementationDetail::class)
|
||||
override fun build(): FirResolvedTypeRef {
|
||||
@@ -38,6 +39,7 @@ class FirResolvedTypeRefBuilder : FirAnnotationContainerBuilder {
|
||||
annotations,
|
||||
type,
|
||||
delegatedTypeRef,
|
||||
isFromStubType,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -61,5 +63,6 @@ inline fun buildResolvedTypeRefCopy(original: FirResolvedTypeRef, init: FirResol
|
||||
copyBuilder.annotations.addAll(original.annotations)
|
||||
copyBuilder.type = original.type
|
||||
copyBuilder.delegatedTypeRef = original.delegatedTypeRef
|
||||
copyBuilder.isFromStubType = original.isFromStubType
|
||||
return copyBuilder.apply(init).build()
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ class FirResolvedTypeRefImpl @FirImplementationDetail constructor(
|
||||
override val annotations: MutableList<FirAnnotation>,
|
||||
override val type: ConeKotlinType,
|
||||
override var delegatedTypeRef: FirTypeRef?,
|
||||
override val isFromStubType: Boolean,
|
||||
) : FirResolvedTypeRef() {
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
annotations.forEach { it.accept(visitor, data) }
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ class FirErrorTypeRefBuilder : FirAnnotationContainerBuilder {
|
||||
source,
|
||||
type,
|
||||
delegatedTypeRef,
|
||||
diagnostic,
|
||||
diagnostic
|
||||
)
|
||||
} else {
|
||||
FirErrorTypeRefImpl(
|
||||
|
||||
@@ -19,11 +19,16 @@ internal class FirErrorTypeRefImpl(
|
||||
override val type: ConeKotlinType,
|
||||
override var delegatedTypeRef: FirTypeRef?,
|
||||
override val diagnostic: ConeDiagnostic,
|
||||
override val isFromStubType: Boolean = false
|
||||
) : FirErrorTypeRef() {
|
||||
constructor(source: KtSourceElement?, delegatedTypeRef: FirTypeRef?, diagnostic: ConeDiagnostic) : this(
|
||||
constructor(source: KtSourceElement?, delegatedTypeRef: FirTypeRef?, diagnostic: ConeDiagnostic,
|
||||
isFromStubType: Boolean = false
|
||||
) : this(
|
||||
source,
|
||||
ConeErrorType(diagnostic),
|
||||
delegatedTypeRef, diagnostic
|
||||
delegatedTypeRef,
|
||||
diagnostic,
|
||||
isFromStubType
|
||||
)
|
||||
|
||||
override val annotations: MutableList<FirAnnotation> = mutableListOf()
|
||||
|
||||
@@ -34,6 +34,9 @@ sealed class FirImplicitBuiltinTypeRef(
|
||||
override val delegatedTypeRef: FirTypeRef?
|
||||
get() = null
|
||||
|
||||
override val isFromStubType: Boolean
|
||||
get() = false
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
|
||||
+1
@@ -265,6 +265,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
|
||||
|
||||
builder(resolvedTypeRef) {
|
||||
defaultNull("delegatedTypeRef")
|
||||
default("isFromStubType", "false")
|
||||
withCopy()
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -224,7 +224,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
"getter", "setter",
|
||||
withGetter = true
|
||||
)
|
||||
default("returnTypeRef", "FirErrorTypeRefImpl(null, null, diagnostic)")
|
||||
default("returnTypeRef", "FirErrorTypeRefImpl(null, null, diagnostic, false)")
|
||||
useTypes(errorTypeRefImplType)
|
||||
}
|
||||
|
||||
@@ -421,13 +421,13 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
|
||||
impl(errorExpression) {
|
||||
default("typeRef", "FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic))")
|
||||
default("typeRef", "FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic), false)")
|
||||
useTypes(errorTypeRefImplType, coneStubDiagnosticType)
|
||||
}
|
||||
|
||||
impl(errorFunction) {
|
||||
defaultNull("receiverTypeRef", "body", withGetter = true)
|
||||
default("returnTypeRef", "FirErrorTypeRefImpl(null, null, diagnostic)")
|
||||
default("returnTypeRef", "FirErrorTypeRefImpl(null, null, diagnostic, false)")
|
||||
useTypes(errorTypeRefImplType)
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -637,6 +637,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
resolvedTypeRef.configure {
|
||||
+field("type", coneKotlinTypeType)
|
||||
+field("delegatedTypeRef", typeRef, nullable = true)
|
||||
+booleanField("isFromStubType")
|
||||
}
|
||||
|
||||
typeRefWithNullability.configure {
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
// WITH_STDLIB
|
||||
// For FIR: see KT-50293
|
||||
|
||||
fun main() {
|
||||
val list = buildList {
|
||||
add("one")
|
||||
add("two")
|
||||
|
||||
val secondParameter = get(1)
|
||||
println(secondParameter <!USELESS_CAST!>as String<!>) // WARNING: [CAST_NEVER_SUCCEEDS] This cast can never succeed
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
// For FIR: see KT-50293
|
||||
// ISSUE: KT-50293
|
||||
|
||||
fun main() {
|
||||
val list = buildList {
|
||||
@@ -7,6 +8,6 @@ fun main() {
|
||||
add("two")
|
||||
|
||||
val secondParameter = get(1)
|
||||
println(secondParameter as String) // WARNING: [CAST_NEVER_SUCCEEDS] This cast can never succeed
|
||||
println(secondParameter as String)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user