[FIR] Support @LowPriorityInOverloadResolution annotation

This commit is contained in:
Dmitriy Novozhilov
2020-02-26 12:45:26 +03:00
parent 4454a0681b
commit 296ee2da4a
9 changed files with 58 additions and 7 deletions
@@ -12,7 +12,8 @@ enum class CallKind(vararg resolutionSequence: ResolutionStage) {
CheckExplicitReceiverConsistency,
CreateFreshTypeVariableSubstitutorStage,
CheckReceivers.Dispatch,
CheckReceivers.Extension
CheckReceivers.Extension,
CheckLowPriorityInOverloadResolution
),
SyntheticSelect(
MapArguments,
@@ -29,7 +30,8 @@ enum class CallKind(vararg resolutionSequence: ResolutionStage) {
CheckReceivers.Dispatch,
CheckReceivers.Extension,
CheckArguments,
EagerResolveOfCallableReferences
EagerResolveOfCallableReferences,
CheckLowPriorityInOverloadResolution
),
CallableReference(
CheckVisibility,
@@ -71,6 +71,7 @@ enum class CandidateApplicability {
PARAMETER_MAPPING_ERROR,
INAPPLICABLE,
SYNTHETIC_RESOLVED,
RESOLVED_LOW_PRIORITY,
RESOLVED
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -472,3 +474,24 @@ internal object CheckVisibility : CheckerStage() {
}
}
}
internal object CheckLowPriorityInOverloadResolution : CheckerStage() {
private val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_CLASS_ID: ClassId =
ClassId(FqName("kotlin.internal"), Name.identifier("LowPriorityInOverloadResolution"))
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val annotations = when (val fir = candidate.symbol.fir) {
is FirSimpleFunction -> fir.annotations
is FirProperty -> fir.annotations
else -> return
}
val hasLowPriorityAnnotation = annotations.any {
val lookupTag = ((it.annotationTypeRef as? FirResolvedTypeRef)?.type as? ConeClassLikeType)?.lookupTag ?: return@any false
lookupTag.classId == LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_CLASS_ID
}
if (hasLowPriorityAnnotation) {
sink.reportApplicability(CandidateApplicability.RESOLVED_LOW_PRIORITY)
}
}
}
@@ -0,0 +1,10 @@
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
fun foo(): Int = 1
fun foo(): String = ""
fun test() {
val s = foo()
s.length
}
@@ -0,0 +1,11 @@
FILE: lowPriorityInResolution.kt
@R|kotlin/Suppress|(String(INVISIBLE_MEMBER), String(INVISIBLE_REFERENCE)) @R|kotlin/internal/LowPriorityInOverloadResolution|() public final fun foo(): R|kotlin/Int| {
^foo Int(1)
}
public final fun foo(): R|kotlin/String| {
^foo String()
}
public final fun test(): R|kotlin/Unit| {
lval s: R|kotlin/String| = R|/foo|()
R|<local>/s|.R|kotlin/String.length|
}
@@ -163,6 +163,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
runTest("compiler/fir/resolve/testData/resolveWithStdlib/listPlusAssign.kt");
}
@TestMetadata("lowPriorityInResolution.kt")
public void testLowPriorityInResolution() throws Exception {
runTest("compiler/fir/resolve/testData/resolveWithStdlib/lowPriorityInResolution.kt");
}
@TestMetadata("mapList.kt")
public void testMapList() throws Exception {
runTest("compiler/fir/resolve/testData/resolveWithStdlib/mapList.kt");
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@@ -11,6 +11,6 @@ public fun <T> Iterable<T>.contains1(element: @kotlin.internal.NoInfer T): Boole
fun test() {
val a: Boolean = listOf(1).<!AMBIGUITY!>contains1<!>("")
val b: Boolean = listOf(1).<!AMBIGUITY!>contains1<!>(1)
val a: Boolean = listOf(1).contains1("")
val b: Boolean = listOf(1).contains1(1)
}
@@ -19,8 +19,8 @@ public fun <K, V> Map<K, V>.get1(key: Any?): Int = null!!
public fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.get1(key: K): V? = null!!
fun test(map: Map<Int, String>) {
val a: Int = listOf(1).<!AMBIGUITY!>contains1<!>("")
val b: Boolean = listOf(1).<!AMBIGUITY!>contains1<!>(1)
val a: Int = listOf(1).contains1("")
val b: Boolean = listOf(1).contains1(1)
val c: String? = map.get1("")
val d: String? = map.get1(1)