FIR checker: report UNSAFE_CALL for overloaded function calls
Previously if an unsafe call is to an overloaded function, FIR checkers report NONE_APPLICABLE. This change instead report them as UNSAFE_CALL or its variants.
This commit is contained in:
committed by
Mikhail Glukhikh
parent
92df1f575a
commit
454ae3b17a
+1
-1
@@ -165,7 +165,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
||||
source,
|
||||
FirErrors.COMPONENT_FUNCTION_AMBIGUITY,
|
||||
diagnostic.name,
|
||||
diagnostic.candidates,
|
||||
diagnostic.candidates.map { it.symbol },
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
+2
-2
@@ -95,9 +95,9 @@ object FirForLoopChecker : FirBlockChecker() {
|
||||
is FirErrorNamedReference -> {
|
||||
when (val diagnostic = calleeReference.diagnostic) {
|
||||
is ConeAmbiguityError -> if (diagnostic.applicability.isSuccess) {
|
||||
reporter.reportOn(reportSource, ambiguityFactory, diagnostic.candidates, context)
|
||||
reporter.reportOn(reportSource, ambiguityFactory, diagnostic.candidates.map { it.symbol }, context)
|
||||
} else if (noneApplicableFactory != null) {
|
||||
reporter.reportOn(reportSource, noneApplicableFactory, diagnostic.candidates, context)
|
||||
reporter.reportOn(reportSource, noneApplicableFactory, diagnostic.candidates.map { it.symbol }, context)
|
||||
}
|
||||
is ConeUnresolvedNameError -> {
|
||||
reporter.reportOn(reportSource, missingFactory, context)
|
||||
|
||||
+16
-21
@@ -16,9 +16,10 @@ import org.jetbrains.kotlin.fir.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
private fun ConeDiagnostic.toFirDiagnostic(
|
||||
@@ -30,10 +31,14 @@ private fun ConeDiagnostic.toFirDiagnostic(
|
||||
is ConeUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.name.asString())
|
||||
is ConeUnresolvedQualifierError -> FirErrors.UNRESOLVED_REFERENCE.on(source, this.qualifier)
|
||||
is ConeHiddenCandidateError -> FirErrors.HIDDEN.on(source, this.candidateSymbol)
|
||||
is ConeAmbiguityError -> if (!this.applicability.isSuccess) {
|
||||
FirErrors.NONE_APPLICABLE.on(source, this.candidates)
|
||||
is ConeAmbiguityError -> if (this.applicability.isSuccess) {
|
||||
FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY.on(source, this.candidates.map { it.symbol })
|
||||
} else if (this.applicability == CandidateApplicability.UNSAFE_CALL) {
|
||||
val candidate = candidates.first { it.currentApplicability == CandidateApplicability.UNSAFE_CALL }
|
||||
val unsafeCall = candidate.diagnostics.firstIsInstance<UnsafeCall>()
|
||||
mapUnsafeCallError(candidate, unsafeCall, source, qualifiedAccessSource)
|
||||
} else {
|
||||
FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY.on(source, this.candidates)
|
||||
FirErrors.NONE_APPLICABLE.on(source, this.candidates.map { it.symbol })
|
||||
}
|
||||
is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.on(source, this.candidates)
|
||||
is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.on(source)
|
||||
@@ -71,30 +76,20 @@ fun ConeDiagnostic.toFirDiagnostics(
|
||||
return listOfNotNull(toFirDiagnostic(source, qualifiedAccessSource))
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isEffectivelyNotNull(): Boolean {
|
||||
return when (this) {
|
||||
is ConeClassLikeType -> !isMarkedNullable
|
||||
is ConeTypeParameterType -> !isMarkedNullable && lookupTag.typeParameterSymbol.fir.bounds.any {
|
||||
it.coneTypeSafe<ConeKotlinType>()?.isEffectivelyNotNull() == true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapUnsafeCallError(
|
||||
diagnostic: ConeInapplicableCandidateError,
|
||||
source: FirSourceElement,
|
||||
candidate: Candidate,
|
||||
rootCause: UnsafeCall,
|
||||
source: FirSourceElement,
|
||||
qualifiedAccessSource: FirSourceElement?,
|
||||
): FirDiagnostic<*> {
|
||||
if (diagnostic.candidate.callInfo.isImplicitInvoke) {
|
||||
if (candidate.callInfo.isImplicitInvoke) {
|
||||
return FirErrors.UNSAFE_IMPLICIT_INVOKE_CALL.on(source, rootCause.actualType)
|
||||
}
|
||||
|
||||
val candidateFunction = diagnostic.candidate.symbol.fir as? FirSimpleFunction
|
||||
val candidateFunction = candidate.symbol.fir as? FirSimpleFunction
|
||||
val candidateFunctionName = candidateFunction?.name
|
||||
val left = diagnostic.candidate.callInfo.explicitReceiver
|
||||
val right = diagnostic.candidate.callInfo.argumentList.arguments.singleOrNull()
|
||||
val left = candidate.callInfo.explicitReceiver
|
||||
val right = candidate.callInfo.argumentList.arguments.singleOrNull()
|
||||
if (left != null && right != null &&
|
||||
source.elementType == KtNodeTypes.OPERATION_REFERENCE &&
|
||||
(candidateFunction?.isOperator == true || candidateFunction?.isInfix == true)
|
||||
@@ -145,7 +140,7 @@ private fun mapInapplicableCandidateError(
|
||||
rootCause.argument.source ?: source,
|
||||
rootCause.argument.name.asString()
|
||||
)
|
||||
is UnsafeCall -> mapUnsafeCallError(diagnostic, source, rootCause, qualifiedAccessSource)
|
||||
is UnsafeCall -> mapUnsafeCallError(diagnostic.candidate, rootCause, source, qualifiedAccessSource)
|
||||
else -> null
|
||||
}
|
||||
}.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) }
|
||||
|
||||
@@ -1258,7 +1258,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
|
||||
+"Ambiguity: "
|
||||
br
|
||||
for (candidate in diagnostic.candidates) {
|
||||
describeVerbose(candidate)
|
||||
describeVerbose(candidate.symbol)
|
||||
br
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ class FirCallResolver(
|
||||
if (resolvedCallableReferenceAtom.hasBeenPostponed) {
|
||||
val errorReference = buildErrorReference(
|
||||
info,
|
||||
ConeAmbiguityError(info.name, applicability, reducedCandidates.map { it.symbol }),
|
||||
ConeAmbiguityError(info.name, applicability, reducedCandidates),
|
||||
callableReferenceAccess.source
|
||||
)
|
||||
resolvedCallableReferenceAtom.resultingReference = errorReference
|
||||
@@ -530,7 +530,7 @@ class FirCallResolver(
|
||||
|
||||
candidates.size > 1 -> buildErrorReference(
|
||||
callInfo,
|
||||
ConeAmbiguityError(name, applicability, candidates.map { it.symbol }),
|
||||
ConeAmbiguityError(name, applicability, candidates),
|
||||
source
|
||||
)
|
||||
|
||||
|
||||
+3
-2
@@ -57,8 +57,9 @@ class ConeArgumentTypeMismatchCandidateError(
|
||||
get() = "Type mismatch. Expected: $expectedType, Actual: $actualType"
|
||||
}
|
||||
|
||||
class ConeAmbiguityError(val name: Name, val applicability: CandidateApplicability, val candidates: Collection<AbstractFirBasedSymbol<*>>) : ConeDiagnostic() {
|
||||
override val reason: String get() = "Ambiguity: $name, ${candidates.map { describeSymbol(it) }}"
|
||||
class ConeAmbiguityError(val name: Name, val applicability: CandidateApplicability, val candidates: Collection<Candidate>) :
|
||||
ConeDiagnostic() {
|
||||
override val reason: String get() = "Ambiguity: $name, ${candidates.map { describeSymbol(it.symbol) }}"
|
||||
}
|
||||
|
||||
class ConeOperatorAmbiguityError(val candidates: Collection<AbstractFirBasedSymbol<*>>) : ConeDiagnostic() {
|
||||
|
||||
@@ -6,9 +6,9 @@ class A() {
|
||||
fun f(): Unit {
|
||||
var x: Int? = 1
|
||||
x = null
|
||||
x <!NONE_APPLICABLE!>+<!> 1
|
||||
x <!NONE_APPLICABLE!>plus<!> 1
|
||||
x <!NONE_APPLICABLE!><<!> 1
|
||||
x <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
x <!UNSAFE_CALL!>plus<!> 1
|
||||
x <!UNSAFE_OPERATOR_CALL!><<!> 1
|
||||
x <!UNRESOLVED_REFERENCE!>+=<!> 1
|
||||
|
||||
x == 1
|
||||
@@ -22,7 +22,7 @@ fun f(): Unit {
|
||||
x === 1
|
||||
x !== 1
|
||||
|
||||
x<!NONE_APPLICABLE!>..<!>2
|
||||
x<!UNSAFE_OPERATOR_CALL!>..<!>2
|
||||
<!ARGUMENT_TYPE_MISMATCH!>x<!> in 1..2
|
||||
|
||||
val y : Boolean? = true
|
||||
|
||||
+6
-6
@@ -44,7 +44,7 @@ fun test() {
|
||||
|
||||
if (out == null || out.println(0) == Unit) {
|
||||
out?.println(1)
|
||||
out.<!NONE_APPLICABLE!>println<!>(1)
|
||||
out<!UNSAFE_CALL!>.<!>println(1)
|
||||
}
|
||||
else {
|
||||
out.println(2)
|
||||
@@ -66,11 +66,11 @@ fun test() {
|
||||
|
||||
if (1 == 2 || out != null && out.println(1) == Unit) {
|
||||
out?.println(2);
|
||||
out.<!NONE_APPLICABLE!>println<!>(2);
|
||||
out<!UNSAFE_CALL!>.<!>println(2);
|
||||
}
|
||||
else {
|
||||
out?.println(3)
|
||||
out.<!NONE_APPLICABLE!>println<!>(3)
|
||||
out<!UNSAFE_CALL!>.<!>println(3)
|
||||
}
|
||||
|
||||
out?.println()
|
||||
@@ -103,7 +103,7 @@ fun test() {
|
||||
|
||||
if (out == null || out.println(0) == Unit) {
|
||||
out?.println(1)
|
||||
out.<!NONE_APPLICABLE!>println<!>(1)
|
||||
out<!UNSAFE_CALL!>.<!>println(1)
|
||||
}
|
||||
else {
|
||||
out.println(2)
|
||||
@@ -127,11 +127,11 @@ fun test() {
|
||||
|
||||
if (1 == 2 || out != null && out.println(1) == Unit) {
|
||||
out?.println(2);
|
||||
out.<!NONE_APPLICABLE!>println<!>(2);
|
||||
out<!UNSAFE_CALL!>.<!>println(2);
|
||||
}
|
||||
else {
|
||||
out?.println(3)
|
||||
out.<!NONE_APPLICABLE!>println<!>(3)
|
||||
out<!UNSAFE_CALL!>.<!>println(3)
|
||||
}
|
||||
|
||||
if (1 > 2) {
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
class A() {
|
||||
operator infix fun plus(i : Int) {}
|
||||
operator fun unaryMinus() {}
|
||||
operator infix fun contains(a : Any?) : Boolean = true
|
||||
}
|
||||
|
||||
operator infix fun A.div(i : Int) {}
|
||||
operator infix fun A?.times(i : Int) {}
|
||||
|
||||
fun test(x : Int?, a : A?) {
|
||||
x.<!NONE_APPLICABLE!>plus<!>(1)
|
||||
x?.plus(1)
|
||||
x <!NONE_APPLICABLE!>+<!> 1
|
||||
<!UNSAFE_CALL!>-<!>x
|
||||
x<!UNSAFE_CALL!>.<!>unaryMinus()
|
||||
x?.unaryMinus()
|
||||
|
||||
a<!UNSAFE_CALL!>.<!>plus(1)
|
||||
a?.plus(1)
|
||||
a <!UNSAFE_INFIX_CALL!>plus<!> 1
|
||||
a <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
<!UNSAFE_CALL!>-<!>a
|
||||
a<!UNSAFE_CALL!>.<!>unaryMinus()
|
||||
a?.unaryMinus()
|
||||
|
||||
a<!UNSAFE_CALL!>.<!>div(1)
|
||||
a <!UNSAFE_OPERATOR_CALL!>/<!> 1
|
||||
a <!UNSAFE_INFIX_CALL!>div<!> 1
|
||||
a?.div(1)
|
||||
|
||||
a.times(1)
|
||||
a * 1
|
||||
a times 1
|
||||
a?.times(1)
|
||||
|
||||
1 <!UNSAFE_OPERATOR_CALL!>in<!> a
|
||||
a <!UNSAFE_INFIX_CALL!>contains<!> 1
|
||||
a<!UNSAFE_CALL!>.<!>contains(1)
|
||||
a?.contains(1)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !WITH_NEW_INFERENCE
|
||||
class A() {
|
||||
operator infix fun plus(i : Int) {}
|
||||
|
||||
Vendored
+2
-2
@@ -2,7 +2,7 @@ fun test() {
|
||||
val out : Int? = null
|
||||
val x : Nothing? = null
|
||||
if (out != x)
|
||||
out.<!NONE_APPLICABLE!>plus<!>(1)
|
||||
out<!UNSAFE_CALL!>.<!>plus(1)
|
||||
if (out == x) return
|
||||
out.<!NONE_APPLICABLE!>plus<!>(1)
|
||||
out<!UNSAFE_CALL!>.<!>plus(1)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ fun foo() {
|
||||
val y: Int? = 0
|
||||
val z: Int? = 0
|
||||
bar(<!ARGUMENT_TYPE_MISMATCH!>if (y != null) y else z<!>, <!ARGUMENT_TYPE_MISMATCH!>y<!>)
|
||||
y <!NONE_APPLICABLE!>+<!> 2
|
||||
y <!UNSAFE_OPERATOR_CALL!>+<!> 2
|
||||
baz(<!ARGUMENT_TYPE_MISMATCH!>y<!>, <!ARGUMENT_TYPE_MISMATCH!>y<!>, if (y == null) return else y, y)
|
||||
baz(y, z!!, z, y)
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ package example
|
||||
fun test() {
|
||||
val p = test.Public()
|
||||
if (p.public is Int) p.public + 1
|
||||
if (p.<!HIDDEN!>protected<!> is Int) p.<!HIDDEN!>protected<!> <!NONE_APPLICABLE!>+<!> 1
|
||||
if (p.<!HIDDEN!>protected<!> is Int) p.<!HIDDEN!>protected<!> <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
if (p.internal is Int) p.internal + 1
|
||||
val i = test.Internal()
|
||||
if (i.public is Int) i.public + 1
|
||||
if (i.<!HIDDEN!>protected<!> is Int) i.<!HIDDEN!>protected<!> <!NONE_APPLICABLE!>+<!> 1
|
||||
if (i.<!HIDDEN!>protected<!> is Int) i.<!HIDDEN!>protected<!> <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
if (i.internal is Int) i.internal + 1
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -13,15 +13,15 @@ class B {
|
||||
|
||||
fun f() {
|
||||
a = A()
|
||||
a.<!NONE_APPLICABLE!>f<!>(true)
|
||||
takeInt(a.<!NONE_APPLICABLE!>f<!>(""))
|
||||
a<!UNSAFE_CALL!>.<!>f(true)
|
||||
takeInt(a<!UNSAFE_CALL!>.<!>f(""))
|
||||
a.<!NONE_APPLICABLE!>f<!>()
|
||||
}
|
||||
|
||||
fun g() {
|
||||
takeInt(if (3 > 2) {
|
||||
a = A()
|
||||
a.<!NONE_APPLICABLE!>f<!>(true)
|
||||
a<!UNSAFE_CALL!>.<!>f(true)
|
||||
} else {
|
||||
6
|
||||
})
|
||||
|
||||
+1
-1
@@ -9,6 +9,6 @@ var a: A? = null
|
||||
|
||||
fun smartCastInterference(b: B) {
|
||||
if (a != null) {
|
||||
a.<!NONE_APPLICABLE!>foo<!>(b)
|
||||
a<!UNSAFE_CALL!>.<!>foo(b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// KT-282 Nullability in extension functions and in binary calls
|
||||
|
||||
class Set {
|
||||
operator fun contains(x : Int) : Boolean = true
|
||||
}
|
||||
|
||||
operator fun Set?.plus(x : Int) : Int = 1
|
||||
|
||||
operator fun Int?.contains(x : Int) : Boolean = false
|
||||
|
||||
fun f(): Unit {
|
||||
var set : Set? = null
|
||||
val i : Int? = null
|
||||
i <!NONE_APPLICABLE!>+<!> 1
|
||||
set + 1
|
||||
1 <!UNSAFE_OPERATOR_CALL!>in<!> set
|
||||
1 in 2
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !WITH_NEW_INFERENCE
|
||||
// KT-282 Nullability in extension functions and in binary calls
|
||||
|
||||
|
||||
+2
-2
@@ -23,13 +23,13 @@ fun testDataFlowInfo1(a: Int?, b: Int?) {
|
||||
val c: Int = a ?: b!!
|
||||
doInt(c)
|
||||
// b is nullable if a != null
|
||||
b <!NONE_APPLICABLE!>+<!> 1
|
||||
b <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
}
|
||||
|
||||
fun testDataFlowInfo2(a: Int?, b: Int?) {
|
||||
doInt(a ?: b!!)
|
||||
// b is nullable if a != null
|
||||
b <!NONE_APPLICABLE!>+<!> 1
|
||||
b <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
}
|
||||
|
||||
fun testTypeMismatch(a: String?, b: Any) {
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ fun foo(): Int {
|
||||
k.run()
|
||||
val d: Int = c
|
||||
// a is not null because of k constructor, but we do not know it
|
||||
return a <!NONE_APPLICABLE!>+<!> d
|
||||
return a <!UNSAFE_OPERATOR_CALL!>+<!> d
|
||||
}
|
||||
else return -1
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ fun foo(): Int {
|
||||
}
|
||||
k.run()
|
||||
val d: Int = c
|
||||
return a <!NONE_APPLICABLE!>+<!> d
|
||||
return a <!UNSAFE_OPERATOR_CALL!>+<!> d
|
||||
}
|
||||
else return -1
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ fun foo(): Int {
|
||||
}
|
||||
k.run()
|
||||
val d: Int = c
|
||||
return a <!NONE_APPLICABLE!>+<!> d
|
||||
return a <!UNSAFE_OPERATOR_CALL!>+<!> d
|
||||
}
|
||||
else return -1
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ fun bar(arg: Long?): Long {
|
||||
return i<!UNSAFE_CALL!>--<!> + i
|
||||
}
|
||||
if (i++ == 7L) {
|
||||
return i++ <!NONE_APPLICABLE!>+<!> i
|
||||
return i++ <!UNSAFE_OPERATOR_CALL!>+<!> i
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
fun foo(): Int {
|
||||
var i: Int? = 42
|
||||
i = null
|
||||
return i <!NONE_APPLICABLE!>+<!> 1
|
||||
return i <!UNSAFE_OPERATOR_CALL!>+<!> 1
|
||||
}
|
||||
|
||||
Vendored
+12
-12
@@ -346,22 +346,22 @@ class case_14_class {
|
||||
if (!funWithReturnsTrueAndInvertCondition(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null)) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (funWithReturnsFalse(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null)) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (funWithReturnsNotNull(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null) == null) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (funWithReturnsNull(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null) != null) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -415,26 +415,26 @@ class case_17_class {
|
||||
if (contracts.case_17_1(value_1, value_2, o.prop_1, this.prop_1)) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(this.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(this.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (contracts.case_17_2(value_1, value_2, o.prop_1, this.prop_1)) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(this.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(this.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (contracts.case_17_3(value_1, value_2, o.prop_1, this.prop_1) == null) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(this.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(this.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (contracts.case_17_4(value_1, value_2, o.prop_1, this.prop_1) != null) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(this.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(this.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+5
-5
@@ -38,7 +38,7 @@ class case_5_class {
|
||||
funWithReturns(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null)
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,22 +131,22 @@ class case_10_class {
|
||||
if (funWithReturnsTrue(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null)) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (!funWithReturnsFalse(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null)) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (funWithReturnsNotNull(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null) != null) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (funWithReturnsNull(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null) == null) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+5
-5
@@ -105,7 +105,7 @@ class case_3_class {
|
||||
contracts.case_3(value_1, value_2, o.prop_1, this.prop_1)
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,22 +158,22 @@ class case_6_class {
|
||||
if (contracts.case_6_1(value_1, value_2, o.prop_1, this.prop_1)) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (!contracts.case_6_2(value_1, value_2, o.prop_1, this.prop_1)) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (contracts.case_6_3(value_1, value_2, o.prop_1, this.prop_1) == null) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
if (contracts.case_6_4(value_1, value_2, o.prop_1, this.prop_1) != null) {
|
||||
println(value_1.<!INAPPLICABLE_CANDIDATE!>dec<!>())
|
||||
println(value_2?.toByte())
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1.<!NONE_APPLICABLE!>plus<!>(3))
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(o.prop_1<!UNSAFE_CALL!>.<!>plus(3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ fun case_1(x: Double?, y: Double?) : Double {
|
||||
} else if (x == null && y != null) {
|
||||
y
|
||||
} else {
|
||||
x <!NONE_APPLICABLE!>+<!> y
|
||||
x <!UNSAFE_OPERATOR_CALL!>+<!> y
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ internal fun FirErrorNamedReference.getCandidateSymbols(): Collection<FirBasedSy
|
||||
when (val diagnostic = diagnostic) {
|
||||
is ConeInapplicableCandidateError -> listOf(diagnostic.candidate.symbol)
|
||||
is ConeHiddenCandidateError -> listOf(diagnostic.candidateSymbol)
|
||||
is ConeAmbiguityError -> diagnostic.candidates
|
||||
is ConeAmbiguityError -> diagnostic.candidates.map { it.symbol }
|
||||
is ConeOperatorAmbiguityError -> diagnostic.candidates
|
||||
is ConeUnsupportedCallableReferenceTarget -> listOf(diagnostic.fir.symbol)
|
||||
else -> emptyList()
|
||||
|
||||
+1
-1
@@ -383,7 +383,7 @@ private class ElementsToShortenCollector(private val shorteningContext: FirShort
|
||||
private fun getSingleUnambiguousCandidate(namedReference: FirErrorNamedReference): FirCallableSymbol<*>? {
|
||||
val coneAmbiguityError = namedReference.diagnostic as? ConeAmbiguityError ?: return null
|
||||
|
||||
val candidates = coneAmbiguityError.candidates.map { it as FirCallableSymbol<*> }
|
||||
val candidates = coneAmbiguityError.candidates.map { it.symbol as FirCallableSymbol<*> }
|
||||
require(candidates.isNotEmpty()) { "Cannot have zero candidates" }
|
||||
|
||||
val distinctCandidates = candidates.distinctBy { it.callableId }
|
||||
|
||||
+5
-2
@@ -15,7 +15,10 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOperatorAmbiguityError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnmatchedTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
@@ -284,7 +287,7 @@ internal object FirReferenceResolveHelper {
|
||||
fun getFirSymbolsByErrorNamedReference(
|
||||
errorNamedReference: FirErrorNamedReference,
|
||||
): Collection<FirBasedSymbol<*>> = when (val diagnostic = errorNamedReference.diagnostic) {
|
||||
is ConeAmbiguityError -> diagnostic.candidates
|
||||
is ConeAmbiguityError -> diagnostic.candidates.map { it.symbol }
|
||||
is ConeOperatorAmbiguityError -> diagnostic.candidates
|
||||
is ConeInapplicableCandidateError -> listOf(diagnostic.candidate.symbol)
|
||||
else -> emptyList()
|
||||
|
||||
Reference in New Issue
Block a user