[FE] Implement temporary resolution algorithm
This commit is contained in:
committed by
TeamCityServer
parent
d923c95671
commit
c34fe8d547
+70
-6
@@ -10471,12 +10471,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/classObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("contextReceiver.kt")
|
||||
public void testContextReceiver() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ExtensionFunctions.kt")
|
||||
public void testExtensionFunctions() throws Exception {
|
||||
@@ -10572,6 +10566,76 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
public void testVariableInvoke() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/variableInvoke.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/extensions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ContextReceivers {
|
||||
@Test
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/extensions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dp.kt")
|
||||
public void testDp() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/dp.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("insideDeclaration.kt")
|
||||
public void testInsideDeclaration() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/insideDeclaration.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lazy.kt")
|
||||
public void testLazy() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/lazy.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("manyReceivers.kt")
|
||||
public void testManyReceivers() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/manyReceivers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("noExplicitReceiver.kt")
|
||||
public void testNoExplicitReceiver() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/noExplicitReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("plusMatrix.kt")
|
||||
public void testPlusMatrix() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/plusMatrix.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeParameterized.kt")
|
||||
public void testTypeParameterized() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/typeParameterized.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeParameterizedList.kt")
|
||||
public void testTypeParameterizedList() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/typeParameterizedList.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("withExplicitReceiver.kt")
|
||||
public void testWithExplicitReceiver() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/withExplicitReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("withExplicitReceiverError.kt")
|
||||
public void testWithExplicitReceiverError() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/withExplicitReceiverError.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
@@ -1194,6 +1194,9 @@ public interface Errors {
|
||||
DiagnosticFactory1<KtElement, String> ERROR_IN_CONTRACT_DESCRIPTION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtElement, String> CONTRACT_NOT_ALLOWED = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
// Context receivers
|
||||
DiagnosticFactory1<KtElement, String> NO_CONTEXT_RECEIVER = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
// Error sets
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> UNRESOLVED_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
|
||||
UNRESOLVED_REFERENCE, NAMED_PARAMETER_NOT_FOUND, UNRESOLVED_REFERENCE_WRONG_RECEIVER);
|
||||
|
||||
+2
@@ -1086,6 +1086,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ERROR_IN_CONTRACT_DESCRIPTION, "Error in contract description: {0}", TO_STRING);
|
||||
MAP.put(CONTRACT_NOT_ALLOWED, "{0}", TO_STRING);
|
||||
|
||||
MAP.put(NO_CONTEXT_RECEIVER, "No required context receiver found: {0}", TO_STRING);
|
||||
|
||||
MAP.setImmutable();
|
||||
|
||||
for (Field field : Errors.class.getFields()) {
|
||||
|
||||
+9
@@ -93,6 +93,15 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
)
|
||||
)
|
||||
}
|
||||
NoContextReceiver::class.java -> {
|
||||
val callElement = psiKotlinCall.psiCall.callElement
|
||||
trace.report(
|
||||
NO_CONTEXT_RECEIVER.on(
|
||||
callElement,
|
||||
(diagnostic as NoContextReceiver).receiverDescriptor.value.toString()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -74,6 +74,12 @@ public abstract class DelegatingResolvedCall<D extends CallableDescriptor> imple
|
||||
return resolvedCall.getDispatchReceiver();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ReceiverValue> getContextReceivers() {
|
||||
return resolvedCall.getContextReceivers();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ExplicitReceiverKind getExplicitReceiverKind() {
|
||||
|
||||
@@ -69,6 +69,10 @@ public interface ResolvedCall<D extends CallableDescriptor> {
|
||||
@Nullable
|
||||
ReceiverValue getDispatchReceiver();
|
||||
|
||||
/** If the target was a function or property with context receivers, this is the value for its context receiver parameters */
|
||||
@NotNull
|
||||
List<ReceiverValue> getContextReceivers();
|
||||
|
||||
/** Determines whether receiver argument or this object is substituted for explicit receiver */
|
||||
@NotNull
|
||||
ExplicitReceiverKind getExplicitReceiverKind();
|
||||
|
||||
@@ -288,6 +288,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
return dispatchReceiver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ReceiverValue> getContextReceivers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ExplicitReceiverKind getExplicitReceiverKind() {
|
||||
|
||||
+54
-12
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.components.CheckReceivers.candidateDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.components.CheckReceivers.checkReceiver
|
||||
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments
|
||||
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
|
||||
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
|
||||
@@ -24,13 +26,15 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.InfixCallNoInfixModifier
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorModifier
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.typeConstructor
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible
|
||||
@@ -680,22 +684,60 @@ internal object CheckReceivers : ResolutionPart() {
|
||||
}
|
||||
|
||||
override fun ResolutionCandidate.process(workIndex: Int) {
|
||||
if (workIndex == 0) {
|
||||
checkReceiver(
|
||||
when (workIndex) {
|
||||
0 -> checkReceiver(
|
||||
resolvedCall.dispatchReceiverArgument,
|
||||
candidateDescriptor.dispatchReceiverParameter,
|
||||
shouldCheckImplicitInvoke = true,
|
||||
)
|
||||
} else {
|
||||
checkReceiver(
|
||||
resolvedCall.extensionReceiverArgument,
|
||||
candidateDescriptor.extensionReceiverParameter,
|
||||
shouldCheckImplicitInvoke = false, // reproduce old inference behaviour
|
||||
)
|
||||
1 -> {
|
||||
checkReceiver(
|
||||
resolvedCall.extensionReceiverArgument,
|
||||
candidateDescriptor.extensionReceiverParameter,
|
||||
shouldCheckImplicitInvoke = false, // reproduce old inference behaviour
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
resolvedCall.contextReceiversArguments = searchForAdditionalReceivers() ?: return
|
||||
for (i in resolvedCall.contextReceiversArguments.indices) {
|
||||
checkReceiver(
|
||||
resolvedCall.contextReceiversArguments[i],
|
||||
candidateDescriptor.contextReceiverParameters[i],
|
||||
shouldCheckImplicitInvoke = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun ResolutionCandidate.workCount() = 2
|
||||
override fun ResolutionCandidate.workCount() = 3
|
||||
|
||||
private fun ResolutionCandidate.searchForAdditionalReceivers(): List<SimpleKotlinCallArgument>? {
|
||||
val result = mutableListOf<ReceiverValueWithSmartCastInfo>()
|
||||
val candidateReceivers = scopeTower.lexicalScope.parentsWithSelf
|
||||
.flatMap { if (it is LexicalScope) scopeTower.getImplicitReceivers(it) else emptyList() }
|
||||
|
||||
fun KotlinType.prepared(): KotlinType = if (containsTypeParameter()) replaceArgumentsWithStarProjections() else this
|
||||
|
||||
for (receiver in candidateDescriptor.contextReceiverParameters) {
|
||||
val expectedReceiverType = receiver.type
|
||||
val expectedReceiverTypeClosestBound =
|
||||
if (expectedReceiverType.isTypeParameter()) expectedReceiverType.supertypes().first()
|
||||
else expectedReceiverType
|
||||
val selectedCandidate = candidateReceivers.firstOrNull { candidateReceiver ->
|
||||
val candidateReceiverType = candidateReceiver.receiverValue.type
|
||||
org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker.Default.isSubtypeOf(
|
||||
candidateReceiverType.prepared(),
|
||||
expectedReceiverTypeClosestBound.prepared()
|
||||
)
|
||||
} ?: run {
|
||||
this.diagnosticsFromResolutionParts.add(NoContextReceiver(receiver))
|
||||
return null
|
||||
}
|
||||
result.add(selectedCandidate)
|
||||
}
|
||||
return result.map { ReceiverExpressionKotlinCallArgument(it) }
|
||||
}
|
||||
}
|
||||
|
||||
internal object CheckArgumentsInParenthesis : ResolutionPart() {
|
||||
|
||||
+7
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.model
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
|
||||
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
|
||||
@@ -272,6 +273,12 @@ class CompatibilityWarningOnArgument(
|
||||
}
|
||||
}
|
||||
|
||||
class NoContextReceiver(val receiverDescriptor: ReceiverParameterDescriptor) : KotlinCallDiagnostic(INAPPLICABLE) {
|
||||
override fun report(reporter: DiagnosticReporter) {
|
||||
reporter.onCall(this)
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinConstraintSystemDiagnostic(
|
||||
val error: ConstraintSystemError
|
||||
) : KotlinCallDiagnostic(error.applicability) {
|
||||
|
||||
@@ -76,6 +76,7 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
|
||||
abstract val explicitReceiverKind: ExplicitReceiverKind
|
||||
abstract val dispatchReceiverArgument: SimpleKotlinCallArgument?
|
||||
abstract val extensionReceiverArgument: SimpleKotlinCallArgument?
|
||||
abstract var contextReceiversArguments: List<SimpleKotlinCallArgument>
|
||||
abstract val typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
|
||||
abstract val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
abstract val freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor
|
||||
|
||||
@@ -85,6 +85,7 @@ open class MutableResolvedCallAtom(
|
||||
open val reflectionCandidateType: UnwrappedType? = null,
|
||||
open val candidate: CallableReferenceResolutionCandidate? = null
|
||||
) : ResolvedCallAtom() {
|
||||
override var contextReceiversArguments: List<SimpleKotlinCallArgument> = listOf()
|
||||
override lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
|
||||
override lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
override lateinit var freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
class View
|
||||
|
||||
context(View) val Int.dp get() = 42 * this
|
||||
|
||||
fun View.f() {
|
||||
123.dp
|
||||
with(123) {
|
||||
dp
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.g(v: View) {
|
||||
with(v) {
|
||||
dp
|
||||
}
|
||||
}
|
||||
|
||||
fun h() {
|
||||
123.dp
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
class View
|
||||
|
||||
context(View) val Int.dp get() = 42 * this
|
||||
|
||||
fun View.f() {
|
||||
123.dp
|
||||
with(123) {
|
||||
dp
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.g(v: View) {
|
||||
with(v) {
|
||||
dp
|
||||
}
|
||||
}
|
||||
|
||||
fun h() {
|
||||
123.<!NO_CONTEXT_RECEIVER!>dp<!>
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package
|
||||
|
||||
public val kotlin.Int.dp: kotlin.Int
|
||||
public fun h(): kotlin.Unit
|
||||
public fun View.f(): kotlin.Unit
|
||||
public fun kotlin.Int.g(/*0*/ v: View): kotlin.Unit
|
||||
|
||||
public final class View {
|
||||
public constructor View()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
interface Lazy<T>
|
||||
|
||||
context(Lazy<Int>, Lazy<CharSequence>)
|
||||
fun test1() {}
|
||||
|
||||
context(Lazy<T>)
|
||||
fun <T> Lazy<Int>.test2() {}
|
||||
|
||||
context(Lazy<Lazy<T>>)
|
||||
fun <T> Lazy<Int>.test3() {}
|
||||
|
||||
fun <T> f(lazy1: Lazy<Int>, lazy2: Lazy<CharSequence>, lazyT: Lazy<T>, lazyLazyT: Lazy<Lazy<T>>) {
|
||||
with(lazy1) {
|
||||
with(lazy2) {
|
||||
test1()
|
||||
test2()
|
||||
test3()
|
||||
}
|
||||
}
|
||||
with(lazy2) {
|
||||
with(lazy1) {
|
||||
test1()
|
||||
test2()
|
||||
test3()
|
||||
}
|
||||
}
|
||||
with(lazyT) {
|
||||
with(lazy1) {
|
||||
test1()
|
||||
test2()
|
||||
test3()
|
||||
}
|
||||
}
|
||||
with(lazyLazyT) {
|
||||
with(lazy1) {
|
||||
test1()
|
||||
test2()
|
||||
test3()
|
||||
}
|
||||
}
|
||||
with(lazy1) {
|
||||
with(lazyLazyT) {
|
||||
test1()
|
||||
test2()
|
||||
test3()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
interface Lazy<T>
|
||||
|
||||
context(Lazy<Int>, Lazy<CharSequence>)
|
||||
fun test1() {}
|
||||
|
||||
context(Lazy<T>)
|
||||
fun <T> Lazy<Int>.test2() {}
|
||||
|
||||
context(Lazy<Lazy<T>>)
|
||||
fun <T> Lazy<Int>.test3() {}
|
||||
|
||||
fun <T> f(lazy1: Lazy<Int>, lazy2: Lazy<CharSequence>, lazyT: Lazy<T>, lazyLazyT: Lazy<Lazy<T>>) {
|
||||
with(lazy1) {
|
||||
with(lazy2) {
|
||||
test1()
|
||||
test2()
|
||||
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>test3<!>()
|
||||
}
|
||||
}
|
||||
with(lazy2) {
|
||||
with(lazy1) {
|
||||
test1()
|
||||
test2()
|
||||
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>test3<!>()
|
||||
}
|
||||
}
|
||||
with(lazyT) {
|
||||
with(lazy1) {
|
||||
<!NO_CONTEXT_RECEIVER!>test1()<!>
|
||||
test2()
|
||||
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>test3<!>()
|
||||
}
|
||||
}
|
||||
with(lazyLazyT) {
|
||||
with(lazy1) {
|
||||
<!NO_CONTEXT_RECEIVER!>test1()<!>
|
||||
test2()
|
||||
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>test3<!>()
|
||||
}
|
||||
}
|
||||
with(lazy1) {
|
||||
with(lazyLazyT) {
|
||||
<!NO_CONTEXT_RECEIVER!>test1()<!>
|
||||
test2()
|
||||
test3()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T> f(/*0*/ lazy1: Lazy<kotlin.Int>, /*1*/ lazy2: Lazy<kotlin.CharSequence>, /*2*/ lazyT: Lazy<T>, /*3*/ lazyLazyT: Lazy<Lazy<T>>): kotlin.Unit
|
||||
public fun test1(): kotlin.Unit
|
||||
public fun </*0*/ T> Lazy<kotlin.Int>.test2(): kotlin.Unit
|
||||
public fun </*0*/ T> Lazy<kotlin.Int>.test3(): kotlin.Unit
|
||||
|
||||
public interface Lazy</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
class A {
|
||||
val a = 1
|
||||
}
|
||||
|
||||
class B {
|
||||
val b = 2
|
||||
}
|
||||
|
||||
class C {
|
||||
val c = 3
|
||||
}
|
||||
|
||||
context(A, B) fun C.f() {}
|
||||
|
||||
fun main(a: A, b: B, c: C) {
|
||||
with(a) {
|
||||
with(b) {
|
||||
with(c) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
with(b) {
|
||||
with(c) {
|
||||
with(a) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
with(a) {
|
||||
with(c) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
class A {
|
||||
val a = 1
|
||||
}
|
||||
|
||||
class B {
|
||||
val b = 2
|
||||
}
|
||||
|
||||
class C {
|
||||
val c = 3
|
||||
}
|
||||
|
||||
context(A, B) fun C.f() {}
|
||||
|
||||
fun main(a: A, b: B, c: C) {
|
||||
with(a) {
|
||||
with(b) {
|
||||
with(c) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
with(b) {
|
||||
with(c) {
|
||||
with(a) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
with(a) {
|
||||
with(c) {
|
||||
<!NO_CONTEXT_RECEIVER!>f()<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: A, /*1*/ b: B, /*2*/ c: C): kotlin.Unit
|
||||
public fun C.f(): kotlin.Unit
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public final val a: kotlin.Int = 1
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B {
|
||||
public constructor B()
|
||||
public final val b: kotlin.Int = 2
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class C {
|
||||
public constructor C()
|
||||
public final val c: kotlin.Int = 3
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
class A
|
||||
class B
|
||||
class C
|
||||
|
||||
context(A) fun B.f() {}
|
||||
context(A) fun B.g() {
|
||||
f()
|
||||
}
|
||||
context(A) fun C.h() {
|
||||
<!INAPPLICABLE_CANDIDATE!>f<!>()
|
||||
}
|
||||
|
||||
fun A.q(b: B) {
|
||||
with(b) {
|
||||
f()
|
||||
}
|
||||
<!INAPPLICABLE_CANDIDATE!>f<!>()
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
class A
|
||||
class B
|
||||
class C
|
||||
|
||||
context(A) fun B.f() {}
|
||||
context(A) fun B.g() {
|
||||
f()
|
||||
}
|
||||
context(A) fun C.h() {
|
||||
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>f<!>()
|
||||
}
|
||||
|
||||
fun A.q(b: B) {
|
||||
with(b) {
|
||||
f()
|
||||
}
|
||||
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>f<!>()
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package
|
||||
|
||||
public fun B.f(): kotlin.Unit
|
||||
public fun B.g(): kotlin.Unit
|
||||
public fun C.h(): kotlin.Unit
|
||||
public fun A.q(/*0*/ b: B): kotlin.Unit
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B {
|
||||
public constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class C {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
interface NumberOperations {
|
||||
fun Number.plus(other: Number): Number
|
||||
}
|
||||
|
||||
class Matrix
|
||||
|
||||
context(NumberOperations) fun Matrix.plus(other: Matrix): Matrix = TODO()
|
||||
|
||||
fun NumberOperations.plusMatrix(m1: Matrix, m2: Matrix) {
|
||||
m1.plus(m2)
|
||||
m2.plus(m1)
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package
|
||||
|
||||
public fun Matrix.plus(/*0*/ other: Matrix): Matrix
|
||||
public fun NumberOperations.plusMatrix(/*0*/ m1: Matrix, /*1*/ m2: Matrix): kotlin.Unit
|
||||
|
||||
public final class Matrix {
|
||||
public constructor Matrix()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface NumberOperations {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
public abstract fun kotlin.Number.plus(/*0*/ other: kotlin.Number): kotlin.Number
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class A
|
||||
class B<X>(val x: X)
|
||||
|
||||
context(T)
|
||||
fun <T> T.f(t: B<T>) {}
|
||||
|
||||
fun Int.main(a: A, b: B<String>) {
|
||||
a.<!INAPPLICABLE_CANDIDATE!>f<!>(b)
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class A
|
||||
class B<X>(val x: X)
|
||||
|
||||
context(T)
|
||||
fun <T> T.f(t: B<T>) {}
|
||||
|
||||
fun Int.main(a: A, b: B<String>) {
|
||||
a.f(<!TYPE_MISMATCH, TYPE_MISMATCH!>b<!>)
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T> T.f(/*0*/ t: B<T>): kotlin.Unit
|
||||
public fun kotlin.Int.main(/*0*/ a: A, /*1*/ b: B<kotlin.String>): kotlin.Unit
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B</*0*/ X> {
|
||||
public constructor B</*0*/ X>(/*0*/ x: X)
|
||||
public final val x: X
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun <T> listOf(vararg e: T): List<T> = null!!
|
||||
|
||||
class A<T>
|
||||
|
||||
context(List<T>)
|
||||
fun <T> A<T>.f() {}
|
||||
|
||||
fun main() {
|
||||
with(listOf(1, 2, 3)) {
|
||||
A<Int>().f()
|
||||
}
|
||||
with(listOf("1", "2", "3")) {
|
||||
A<Int>().f()
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun <T> listOf(vararg e: T): List<T> = null!!
|
||||
|
||||
class A<T>
|
||||
|
||||
context(List<T>)
|
||||
fun <T> A<T>.f() {}
|
||||
|
||||
fun main() {
|
||||
with(listOf(1, 2, 3)) {
|
||||
A<Int>().f()
|
||||
}
|
||||
with(listOf("1", "2", "3")) {
|
||||
A<Int>().<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>f<!>()
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T> listOf(/*0*/ vararg e: T /*kotlin.Array<out T>*/): kotlin.collections.List<T>
|
||||
public fun main(): kotlin.Unit
|
||||
public fun </*0*/ T> A<T>.f(): kotlin.Unit
|
||||
|
||||
public final class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
open class A
|
||||
class B
|
||||
class C: A()
|
||||
|
||||
context(A)
|
||||
fun B.f() {}
|
||||
|
||||
fun main() {
|
||||
val b = B()
|
||||
|
||||
b.f()
|
||||
with(A()) {
|
||||
b.f()
|
||||
}
|
||||
with(C()) {
|
||||
b.f()
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
open class A
|
||||
class B
|
||||
class C: A()
|
||||
|
||||
context(A)
|
||||
fun B.f() {}
|
||||
|
||||
fun main() {
|
||||
val b = B()
|
||||
|
||||
b.<!NO_CONTEXT_RECEIVER!>f()<!>
|
||||
with(A()) {
|
||||
b.f()
|
||||
}
|
||||
with(C()) {
|
||||
b.f()
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package
|
||||
|
||||
public fun main(): kotlin.Unit
|
||||
public fun B.f(): kotlin.Unit
|
||||
|
||||
public open class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B {
|
||||
public constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class C : A {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
class A
|
||||
class B
|
||||
class C
|
||||
|
||||
context(A)
|
||||
fun B.f() {}
|
||||
|
||||
fun main() {
|
||||
val b = B()
|
||||
|
||||
b.f()
|
||||
with(A()) {
|
||||
b.f()
|
||||
}
|
||||
with(C()) {
|
||||
b.f()
|
||||
}
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
class A
|
||||
class B
|
||||
class C
|
||||
|
||||
context(A)
|
||||
fun B.f() {}
|
||||
|
||||
fun main() {
|
||||
val b = B()
|
||||
|
||||
b.<!NO_CONTEXT_RECEIVER!>f()<!>
|
||||
with(A()) {
|
||||
b.f()
|
||||
}
|
||||
with(C()) {
|
||||
b.<!NO_CONTEXT_RECEIVER!>f()<!>
|
||||
}
|
||||
}
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
package
|
||||
|
||||
public fun main(): kotlin.Unit
|
||||
public fun B.f(): kotlin.Unit
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B {
|
||||
public constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class C {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Generated
+70
-6
@@ -10477,12 +10477,6 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/classObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("contextReceiver.kt")
|
||||
public void testContextReceiver() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ExtensionFunctions.kt")
|
||||
public void testExtensionFunctions() throws Exception {
|
||||
@@ -10578,6 +10572,76 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
public void testVariableInvoke() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/variableInvoke.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/extensions/contextReceivers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ContextReceivers {
|
||||
@Test
|
||||
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/extensions/contextReceivers"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dp.kt")
|
||||
public void testDp() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/dp.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("insideDeclaration.kt")
|
||||
public void testInsideDeclaration() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/insideDeclaration.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lazy.kt")
|
||||
public void testLazy() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/lazy.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("manyReceivers.kt")
|
||||
public void testManyReceivers() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/manyReceivers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("noExplicitReceiver.kt")
|
||||
public void testNoExplicitReceiver() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/noExplicitReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("plusMatrix.kt")
|
||||
public void testPlusMatrix() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/plusMatrix.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeParameterized.kt")
|
||||
public void testTypeParameterized() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/typeParameterized.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeParameterizedList.kt")
|
||||
public void testTypeParameterizedList() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/typeParameterizedList.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("withExplicitReceiver.kt")
|
||||
public void testWithExplicitReceiver() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/withExplicitReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("withExplicitReceiverError.kt")
|
||||
public void testWithExplicitReceiverError() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/withExplicitReceiverError.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
@@ -84,6 +84,8 @@ fun KotlinType.isPrimitiveNumberOrNullableType(): Boolean =
|
||||
|
||||
fun KotlinType.isTypeParameter(): Boolean = TypeUtils.isTypeParameter(this)
|
||||
|
||||
fun KotlinType.containsTypeParameter(): Boolean = TypeUtils.contains(this) { t -> TypeUtils.isTypeParameter(t) }
|
||||
|
||||
fun KotlinType.upperBoundedByPrimitiveNumberOrNullableType(): Boolean =
|
||||
TypeUtils.getTypeParameterDescriptorOrNull(this)?.upperBounds?.any {
|
||||
it.isPrimitiveNumberOrNullableType() || it.upperBoundedByPrimitiveNumberOrNullableType()
|
||||
|
||||
@@ -233,6 +233,7 @@ private fun resolveAccessorCall(
|
||||
override fun getResultingDescriptor() = suspendPropertyDescriptor
|
||||
override fun getExtensionReceiver() = null
|
||||
override fun getDispatchReceiver() = null
|
||||
override fun getContextReceivers(): List<ReceiverValue> = emptyList()
|
||||
override fun getExplicitReceiverKind() = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
override fun getValueArguments(): MutableMap<ValueParameterDescriptor, ResolvedValueArgument> = mutableMapOf()
|
||||
override fun getValueArgumentsByIndex(): MutableList<ResolvedValueArgument> = mutableListOf()
|
||||
|
||||
Reference in New Issue
Block a user