[FIR] Fix false positive errors on Throws::class, Throws()
^KT-63794 Fixed
This commit is contained in:
committed by
Space Team
parent
8dcd4efbc1
commit
3d77d09260
+48
-7
@@ -11,11 +11,8 @@ import org.jetbrains.kotlin.fir.declarations.*
|
|||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.scopes.CallableCopyTypeCalculator
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.TypeAliasConstructorsSubstitutingScope
|
import org.jetbrains.kotlin.fir.scopes.impl.TypeAliasConstructorsSubstitutingScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.scopeForClass
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
@@ -86,7 +83,12 @@ fun FirScope.getSingleVisibleClassifier(
|
|||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = classifierSymbol
|
result = classifierSymbol
|
||||||
} else {
|
} else {
|
||||||
isAmbiguousResult = true
|
val checkResult = checkUnambiguousClassifiers(result!!, classifierSymbol, session)
|
||||||
|
if (checkResult.shouldReplaceResult) {
|
||||||
|
result = classifierSymbol
|
||||||
|
} else {
|
||||||
|
isAmbiguousResult = checkResult.isAmbiguousResult
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,8 +139,12 @@ private fun FirScope.getFirstClassifierOrNull(
|
|||||||
}
|
}
|
||||||
result != null -> {
|
result != null -> {
|
||||||
if (isSuccessResult == isSuccessCandidate) {
|
if (isSuccessResult == isSuccessCandidate) {
|
||||||
// results are similar => ambiguity
|
val checkResult = checkUnambiguousClassifiers(result!!.symbol, symbol, session)
|
||||||
isAmbiguousResult = true
|
if (checkResult.shouldReplaceResult) {
|
||||||
|
result = SymbolWithSubstitutor(symbol, substitutor)
|
||||||
|
} else {
|
||||||
|
isAmbiguousResult = checkResult.isAmbiguousResult
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// ignore unsuccessful result if we have successful one
|
// ignore unsuccessful result if we have successful one
|
||||||
}
|
}
|
||||||
@@ -154,6 +160,41 @@ private fun FirScope.getFirstClassifierOrNull(
|
|||||||
return result.takeUnless { isAmbiguousResult }
|
return result.takeUnless { isAmbiguousResult }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class CheckUnambiguousClassifiersResult(val shouldReplaceResult: Boolean, val isAmbiguousResult: Boolean)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle special cases when classifiers don't cause ambiguity (`Throws`)
|
||||||
|
*
|
||||||
|
* The following output options are possible:
|
||||||
|
* * `shouldReplaceResult = true, isAmbiguousResult = false` means successful disambiguation
|
||||||
|
* but the previous result should be replaced with the new one (typically class symbol wins typealias)
|
||||||
|
* * `shouldReplaceResult = false, isAmbiguousResult = false` means successful disambiguation
|
||||||
|
* but the new result should be discarded
|
||||||
|
* * `shouldReplaceResult = false, isAmbiguousResult = true` means unsuccessful disambiguation
|
||||||
|
* and both results become irrelevant
|
||||||
|
*/
|
||||||
|
private fun checkUnambiguousClassifiers(
|
||||||
|
foundClassifierSymbol: FirClassifierSymbol<*>,
|
||||||
|
newClassifierSymbol: FirClassifierSymbol<*>,
|
||||||
|
session: FirSession,
|
||||||
|
): CheckUnambiguousClassifiersResult {
|
||||||
|
val classTypealiasesThatDontCauseAmbiguity = session.platformClassMapper.classTypealiasesThatDontCauseAmbiguity
|
||||||
|
|
||||||
|
if (foundClassifierSymbol is FirTypeAliasSymbol && newClassifierSymbol is FirRegularClassSymbol &&
|
||||||
|
classTypealiasesThatDontCauseAmbiguity[newClassifierSymbol.classId] == foundClassifierSymbol.classId
|
||||||
|
) {
|
||||||
|
return CheckUnambiguousClassifiersResult(shouldReplaceResult = true, isAmbiguousResult = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newClassifierSymbol is FirTypeAliasSymbol && foundClassifierSymbol is FirRegularClassSymbol &&
|
||||||
|
classTypealiasesThatDontCauseAmbiguity[foundClassifierSymbol.classId] == newClassifierSymbol.classId
|
||||||
|
) {
|
||||||
|
return CheckUnambiguousClassifiersResult(shouldReplaceResult = false, isAmbiguousResult = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return CheckUnambiguousClassifiersResult(shouldReplaceResult = false, isAmbiguousResult = true)
|
||||||
|
}
|
||||||
|
|
||||||
private fun processSyntheticConstructors(
|
private fun processSyntheticConstructors(
|
||||||
matchedSymbol: FirClassLikeSymbol<*>,
|
matchedSymbol: FirClassLikeSymbol<*>,
|
||||||
processor: (FirFunctionSymbol<*>) -> Unit,
|
processor: (FirFunctionSymbol<*>) -> Unit,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// FIR_IDENTICAL
|
// FIR_IDENTICAL
|
||||||
|
// ISSUE: KT-63794
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
// FILE: main1.kt
|
// FILE: main1.kt
|
||||||
package abc1
|
package abc1
|
||||||
@@ -163,3 +164,10 @@ fun foo3() {}
|
|||||||
fun foo5(x: Throws) {}
|
fun foo5(x: Throws) {}
|
||||||
fun foo6(x: kotlin.Throws) {}
|
fun foo6(x: kotlin.Throws) {}
|
||||||
fun foo7(x: kotlin.jvm.Throws) {}
|
fun foo7(x: kotlin.jvm.Throws) {}
|
||||||
|
|
||||||
|
// FILE: main10.kt
|
||||||
|
|
||||||
|
val x: Throws? = null
|
||||||
|
val y = Throws()
|
||||||
|
val z = Throws::exceptionClasses
|
||||||
|
val w = Throws::class
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
|
public val w: kotlin.reflect.KClass<kotlin.Throws /* = kotlin.jvm.Throws */>
|
||||||
|
public val x: kotlin.Throws? /* = kotlin.jvm.Throws? */ = null
|
||||||
|
public val y: kotlin.Throws /* = kotlin.jvm.Throws */
|
||||||
|
public val z: kotlin.reflect.KProperty1<kotlin.Throws /* = kotlin.jvm.Throws */, kotlin.Array<out kotlin.reflect.KClass<out kotlin.Throwable>>>
|
||||||
|
|
||||||
package abc1 {
|
package abc1 {
|
||||||
@kotlin.Throws /* = kotlin.jvm.Throws */(exceptionClasses = {java.lang.Exception::class}) public fun foo1(): kotlin.Unit
|
@kotlin.Throws /* = kotlin.jvm.Throws */(exceptionClasses = {java.lang.Exception::class}) public fun foo1(): kotlin.Unit
|
||||||
@kotlin.Throws /* = kotlin.jvm.Throws */(exceptionClasses = {java.lang.Exception::class}) public fun foo2(): kotlin.Unit
|
@kotlin.Throws /* = kotlin.jvm.Throws */(exceptionClasses = {java.lang.Exception::class}) public fun foo2(): kotlin.Unit
|
||||||
|
|||||||
Reference in New Issue
Block a user