[FE] KT-51234 Check subtyping between context receivers
This commit is contained in:
committed by
teamcity
parent
a3fa2dc9bf
commit
292c0c4383
+6
@@ -10919,6 +10919,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/plusMatrix.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subtypingBetweenContextReceivers.kt")
|
||||
public void testSubtypingBetweenContextReceivers() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/subtypingBetweenContextReceivers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("superWithContext.kt")
|
||||
public void testSuperWithContext() throws Exception {
|
||||
|
||||
+6
@@ -10919,6 +10919,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/plusMatrix.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subtypingBetweenContextReceivers.kt")
|
||||
public void testSubtypingBetweenContextReceivers() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/subtypingBetweenContextReceivers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("superWithContext.kt")
|
||||
public void testSuperWithContext() throws Exception {
|
||||
|
||||
+6
@@ -10919,6 +10919,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/plusMatrix.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subtypingBetweenContextReceivers.kt")
|
||||
public void testSubtypingBetweenContextReceivers() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/subtypingBetweenContextReceivers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("superWithContext.kt")
|
||||
public void testSuperWithContext() throws Exception {
|
||||
|
||||
@@ -1308,6 +1308,7 @@ public interface Errors {
|
||||
DiagnosticFactory1<KtElement, String> MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> SUBTYPING_BETWEEN_CONTEXT_RECEIVERS = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Error sets
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> UNRESOLVED_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
|
||||
|
||||
+1
@@ -1120,6 +1120,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER, "Multiple arguments applicable for context receiver: {0}", TO_STRING);
|
||||
MAP.put(AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER, "With implicit context receiver, call is ambiguous. Specify the receiver explicitly");
|
||||
MAP.put(UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL, "To use contextual declarations, specify the `-Xcontext-receivers` compiler option");
|
||||
MAP.put(SUBTYPING_BETWEEN_CONTEXT_RECEIVERS, "Subtyping relation between context receivers is prohibited");
|
||||
|
||||
MAP.setImmutable();
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtContextReceiverList
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.containsTypeParameter
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
|
||||
fun checkContextReceiversAreEnabled(
|
||||
trace: BindingTrace,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
contextReceiverList: KtContextReceiverList
|
||||
) {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) {
|
||||
trace.report(
|
||||
Errors.UNSUPPORTED_FEATURE.on(
|
||||
contextReceiverList,
|
||||
LanguageFeature.ContextReceivers to languageVersionSettings
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkSubtypingBetweenContextReceivers(
|
||||
trace: BindingTrace,
|
||||
contextReceiverList: KtContextReceiverList,
|
||||
contextReceiverTypes: List<KotlinType>
|
||||
) {
|
||||
fun KotlinType.prepared(): KotlinType = when {
|
||||
isTypeParameter() -> supertypes().first()
|
||||
containsTypeParameter() -> replaceArgumentsWithStarProjections()
|
||||
else -> this
|
||||
}
|
||||
for (i in 0 until contextReceiverTypes.lastIndex) {
|
||||
val contextReceiverType = contextReceiverTypes[i].prepared()
|
||||
for (j in (i + 1) until contextReceiverTypes.size) {
|
||||
val anotherContextReceiverType = contextReceiverTypes[j].prepared()
|
||||
if (NewKotlinTypeChecker.Default.isSubtypeOf(contextReceiverType, anotherContextReceiverType) ||
|
||||
NewKotlinTypeChecker.Default.isSubtypeOf(anotherContextReceiverType, contextReceiverType)
|
||||
) {
|
||||
trace.report(Errors.SUBTYPING_BETWEEN_CONTEXT_RECEIVERS.on(contextReceiverList))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
||||
SuspendFunctionAsSupertypeChecker,
|
||||
EnumCompanionInEnumConstructorCallChecker,
|
||||
ContextualDeclarationChecker,
|
||||
SubtypingBetweenContextReceiversChecker,
|
||||
ValueParameterUsageInDefaultArgumentChecker,
|
||||
CyclicAnnotationsChecker,
|
||||
)
|
||||
|
||||
@@ -368,10 +368,12 @@ class TypeResolver(
|
||||
|
||||
val contextReceiverList = type.contextReceiverList
|
||||
val contextReceiversTypes = if (contextReceiverList != null) {
|
||||
checkContextReceiversAreEnabled(contextReceiverList)
|
||||
contextReceiverList.typeReferences().map { typeRef ->
|
||||
checkContextReceiversAreEnabled(c.trace, languageVersionSettings, contextReceiverList)
|
||||
val types = contextReceiverList.typeReferences().map { typeRef ->
|
||||
resolveType(c.noBareTypes(), typeRef)
|
||||
}
|
||||
checkSubtypingBetweenContextReceivers(c.trace, contextReceiverList, types)
|
||||
types
|
||||
} else emptyList()
|
||||
|
||||
val parameterDescriptors = resolveParametersOfFunctionType(type.parameters)
|
||||
@@ -454,7 +456,7 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
override fun visitContextReceiverList(contextReceiverList: KtContextReceiverList) {
|
||||
checkContextReceiversAreEnabled(contextReceiverList)
|
||||
checkContextReceiversAreEnabled(c.trace, languageVersionSettings, contextReceiverList)
|
||||
}
|
||||
|
||||
override fun visitDynamicType(type: KtDynamicType) {
|
||||
@@ -496,17 +498,6 @@ class TypeResolver(
|
||||
c.trace.report(Errors.UNSUPPORTED.on(it, "val or var on parameter in function type"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkContextReceiversAreEnabled(contextReceiverList: KtContextReceiverList) {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) {
|
||||
c.trace.report(
|
||||
UNSUPPORTED_FEATURE.on(
|
||||
contextReceiverList,
|
||||
LanguageFeature.ContextReceivers to languageVersionSettings
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return result ?: type(ErrorUtils.createErrorType(ErrorTypeKind.NO_TYPE_SPECIFIED, typeElement?.getDebugText() ?: "unknown element"))
|
||||
|
||||
+20
-6
@@ -6,11 +6,14 @@
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isContextualDeclaration
|
||||
import org.jetbrains.kotlin.resolve.checkContextReceiversAreEnabled
|
||||
import org.jetbrains.kotlin.resolve.checkSubtypingBetweenContextReceivers
|
||||
|
||||
object ContextualDeclarationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
@@ -19,12 +22,23 @@ object ContextualDeclarationChecker : DeclarationChecker {
|
||||
}
|
||||
if (declaration.isContextualDeclaration()) {
|
||||
val contextReceiverList = declaration.findDescendantOfType<KtContextReceiverList>() ?: return
|
||||
context.trace.report(
|
||||
Errors.UNSUPPORTED_FEATURE.on(
|
||||
contextReceiverList, LanguageFeature.ContextReceivers to context.languageVersionSettings
|
||||
)
|
||||
)
|
||||
checkContextReceiversAreEnabled(context.trace, context.languageVersionSettings, contextReceiverList)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object SubtypingBetweenContextReceiversChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers) || !declaration.isContextualDeclaration()) {
|
||||
return
|
||||
}
|
||||
val contextReceivers = when (descriptor) {
|
||||
is CallableDescriptor -> descriptor.contextReceiverParameters
|
||||
is ClassDescriptor -> descriptor.contextReceivers
|
||||
else -> return
|
||||
}
|
||||
val contextReceiverList = declaration.findDescendantOfType<KtContextReceiverList>() ?: return
|
||||
checkSubtypingBetweenContextReceivers(context.trace, contextReceiverList, contextReceivers.map { it.type })
|
||||
}
|
||||
}
|
||||
Vendored
+2
-2
@@ -3,7 +3,7 @@
|
||||
|
||||
class Box<E>(val x: E)
|
||||
|
||||
class A<X, Y> {
|
||||
class A<X, Y : Number> {
|
||||
context(Box<X>, Y)
|
||||
fun foo(): String = x.toString() + this@Y.toString()
|
||||
|
||||
@@ -12,7 +12,7 @@ class A<X, Y> {
|
||||
}
|
||||
|
||||
context(Box<X>, Y)
|
||||
fun <X, Y> bar(): String = x.toString() + this@Y.toString()
|
||||
fun <X, Y : Number> bar(): String = x.toString() + this@Y.toString()
|
||||
|
||||
fun box(): String {
|
||||
return with(Box("OK")) {
|
||||
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
// !DIAGNOSTICS: -UNCHECKED_CAST
|
||||
// !LANGUAGE: +ContextReceivers
|
||||
|
||||
interface A
|
||||
interface B : A
|
||||
typealias C = B
|
||||
|
||||
interface Inv<T>
|
||||
interface Cov<out T>
|
||||
|
||||
// Functions
|
||||
|
||||
context(A, A)
|
||||
fun f1() {}
|
||||
|
||||
context(A, B)
|
||||
fun f2() {}
|
||||
|
||||
context(A, C)
|
||||
fun f3() {}
|
||||
|
||||
context(B, C)
|
||||
fun f4() {}
|
||||
|
||||
context(C, C)
|
||||
fun f5() {}
|
||||
|
||||
context(A, A, A)
|
||||
fun f6() {}
|
||||
|
||||
context(Inv<A>, Inv<B>)
|
||||
fun f7() {}
|
||||
|
||||
context(Inv<A>, Inv<A>)
|
||||
fun f8() {}
|
||||
|
||||
context(Inv<T>, Inv<A>)
|
||||
fun <T> f9() {}
|
||||
|
||||
context(Cov<A>, Cov<B>)
|
||||
fun f10() {}
|
||||
|
||||
context(Cov<T>, Cov<A>)
|
||||
fun <T> f11() {}
|
||||
|
||||
context(T, A)
|
||||
fun <T> f12() {}
|
||||
|
||||
// Classes
|
||||
|
||||
context(A, A)
|
||||
class C1 {
|
||||
context(A, A)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(A, A)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(A, B)
|
||||
class C2 {
|
||||
context(A, B)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(A, B)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(A, C)
|
||||
class C3 {
|
||||
context(A, C)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(A, C)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(B, C)
|
||||
class C4 {
|
||||
context(B, C)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(B, C)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(C, C)
|
||||
class C5 {
|
||||
context(C, C)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(C, C)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(A, A, A)
|
||||
class C6 {
|
||||
context(A, A, A)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(A, A, A)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(Inv<A>, Inv<B>)
|
||||
class C7 {
|
||||
context(Inv<A>, Inv<B>)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(Inv<A>, Inv<B>)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(Inv<A>, Inv<A>)
|
||||
class C8 {
|
||||
context(Inv<A>, Inv<A>)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(Inv<A>, Inv<A>)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(Inv<T>, Inv<A>)
|
||||
class C9<T> {
|
||||
context(Inv<T>, Inv<A>)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(Inv<T>, Inv<A>)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(Cov<A>, Cov<B>)
|
||||
class C10 {
|
||||
context(Cov<A>, Cov<B>)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(Cov<A>, Cov<B>)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(Cov<T>, Cov<A>)
|
||||
class C11<T> {
|
||||
context(Cov<T>, Cov<A>)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(Cov<T>, Cov<A>)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(T, A)
|
||||
class C12<T> {
|
||||
context(T, A)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(T, A)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
||||
context(A, A)
|
||||
val p1: Any?
|
||||
get() { return null }
|
||||
|
||||
context(A, B)
|
||||
val p2: Any?
|
||||
get() { return null }
|
||||
|
||||
context(A, C)
|
||||
val p3: Any?
|
||||
get() { return null }
|
||||
|
||||
context(B, C)
|
||||
val p4: Any?
|
||||
get() { return null }
|
||||
|
||||
context(C, C)
|
||||
val p5: Any?
|
||||
get() { return null }
|
||||
|
||||
context(A, A, A)
|
||||
val p6: Any?
|
||||
get() { return null }
|
||||
|
||||
context(Inv<A>, Inv<B>)
|
||||
val p7: Any?
|
||||
get() { return null }
|
||||
|
||||
context(Inv<A>, Inv<A>)
|
||||
val p8: Any?
|
||||
get() { return null }
|
||||
|
||||
context(Inv<T>, Inv<A>)
|
||||
val <T> p9: Any?
|
||||
get() { return null }
|
||||
|
||||
context(Cov<A>, Cov<B>)
|
||||
val p10: Any?
|
||||
get() { return null }
|
||||
|
||||
context(Cov<T>, Cov<A>)
|
||||
val <T> p11: Any?
|
||||
get() { return null }
|
||||
|
||||
context(T, A)
|
||||
val <T> p12: Any?
|
||||
get() { return null }
|
||||
|
||||
// Function types
|
||||
|
||||
// Function types are processed with the same function that is used for checking contextual declarations
|
||||
// So we check here only one simple case: `context(A, B)`
|
||||
|
||||
context(A, B)
|
||||
fun f(g: context(A, B) () -> Unit, value: Any): context(A, B) () -> Unit {
|
||||
return value as (context(A, B) () -> Unit)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val lf: context(A, B) () -> Unit = { }
|
||||
}
|
||||
Vendored
+221
@@ -0,0 +1,221 @@
|
||||
// !DIAGNOSTICS: -UNCHECKED_CAST
|
||||
// !LANGUAGE: +ContextReceivers
|
||||
|
||||
interface A
|
||||
interface B : A
|
||||
typealias C = B
|
||||
|
||||
interface Inv<T>
|
||||
interface Cov<out T>
|
||||
|
||||
// Functions
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A)<!>
|
||||
fun f1() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!>
|
||||
fun f2() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, C)<!>
|
||||
fun f3() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(B, C)<!>
|
||||
fun f4() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(C, C)<!>
|
||||
fun f5() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A, A)<!>
|
||||
fun f6() {}
|
||||
|
||||
context(Inv<A>, Inv<B>)
|
||||
fun f7() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<A>, Inv<A>)<!>
|
||||
fun f8() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<T>, Inv<A>)<!>
|
||||
fun <T> f9() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<A>, Cov<B>)<!>
|
||||
fun f10() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<T>, Cov<A>)<!>
|
||||
fun <T> f11() {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(T, A)<!>
|
||||
fun <T> f12() {}
|
||||
|
||||
// Classes
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A)<!>
|
||||
class C1 {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!>
|
||||
class C2 {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, C)<!>
|
||||
class C3 {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, C)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, C)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(B, C)<!>
|
||||
class C4 {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(B, C)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(B, C)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(C, C)<!>
|
||||
class C5 {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(C, C)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(C, C)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A, A)<!>
|
||||
class C6 {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A, A)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A, A)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
context(Inv<A>, Inv<B>)
|
||||
class C7 {
|
||||
context(Inv<A>, Inv<B>)
|
||||
val p: Any get() = 42
|
||||
|
||||
context(Inv<A>, Inv<B>)
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<A>, Inv<A>)<!>
|
||||
class C8 {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<A>, Inv<A>)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<A>, Inv<A>)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<T>, Inv<A>)<!>
|
||||
class C9<T> {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<T>, Inv<A>)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<T>, Inv<A>)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<A>, Cov<B>)<!>
|
||||
class C10 {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<A>, Cov<B>)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<A>, Cov<B>)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<T>, Cov<A>)<!>
|
||||
class C11<T> {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<T>, Cov<A>)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<T>, Cov<A>)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(T, A)<!>
|
||||
class C12<T> {
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(T, A)<!>
|
||||
val p: Any get() = 42
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(T, A)<!>
|
||||
fun m() {}
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A)<!>
|
||||
val p1: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!>
|
||||
val p2: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, C)<!>
|
||||
val p3: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(B, C)<!>
|
||||
val p4: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(C, C)<!>
|
||||
val p5: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, A, A)<!>
|
||||
val p6: Any?
|
||||
get() { return null }
|
||||
|
||||
context(Inv<A>, Inv<B>)
|
||||
val p7: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<A>, Inv<A>)<!>
|
||||
val p8: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Inv<T>, Inv<A>)<!>
|
||||
val <T> p9: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<A>, Cov<B>)<!>
|
||||
val p10: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<T>, Cov<A>)<!>
|
||||
val <T> p11: Any?
|
||||
get() { return null }
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(T, A)<!>
|
||||
val <T> p12: Any?
|
||||
get() { return null }
|
||||
|
||||
// Function types
|
||||
|
||||
// Function types are processed with the same function that is used for checking contextual declarations
|
||||
// So we check here only one simple case: `context(A, B)`
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!>
|
||||
fun f(g: <!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!> () -> Unit, value: Any): <!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!> () -> Unit {
|
||||
return value as (<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!> () -> Unit)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val lf: <!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(A, B)<!> () -> Unit = { }
|
||||
}
|
||||
compiler/testData/diagnostics/tests/extensions/contextReceivers/subtypingBetweenContextReceivers.txt
Vendored
+161
@@ -0,0 +1,161 @@
|
||||
package
|
||||
|
||||
context(A, A) public val p1: kotlin.Any?
|
||||
context(Cov<A>, Cov<B>) public val p10: kotlin.Any?
|
||||
context(Cov<T>, Cov<A>) public val </*0*/ T> p11: kotlin.Any?
|
||||
context(T, A) public val </*0*/ T> p12: kotlin.Any?
|
||||
context(A, B) public val p2: kotlin.Any?
|
||||
context(A, C /* = B */) public val p3: kotlin.Any?
|
||||
context(B, C /* = B */) public val p4: kotlin.Any?
|
||||
context(C /* = B */, C /* = B */) public val p5: kotlin.Any?
|
||||
context(A, A, A) public val p6: kotlin.Any?
|
||||
context(Inv<A>, Inv<B>) public val p7: kotlin.Any?
|
||||
context(Inv<A>, Inv<A>) public val p8: kotlin.Any?
|
||||
context(Inv<T>, Inv<A>) public val </*0*/ T> p9: kotlin.Any?
|
||||
context(A, B) public fun f(/*0*/ g: context(A, B) () -> kotlin.Unit, /*1*/ value: kotlin.Any): context(A, B) () -> kotlin.Unit
|
||||
context(A, A) public fun f1(): kotlin.Unit
|
||||
context(Cov<A>, Cov<B>) public fun f10(): kotlin.Unit
|
||||
context(Cov<T>, Cov<A>) public fun </*0*/ T> f11(): kotlin.Unit
|
||||
context(T, A) public fun </*0*/ T> f12(): kotlin.Unit
|
||||
context(A, B) public fun f2(): kotlin.Unit
|
||||
context(A, C /* = B */) public fun f3(): kotlin.Unit
|
||||
context(B, C /* = B */) public fun f4(): kotlin.Unit
|
||||
context(C /* = B */, C /* = B */) public fun f5(): kotlin.Unit
|
||||
context(A, A, A) public fun f6(): kotlin.Unit
|
||||
context(Inv<A>, Inv<B>) public fun f7(): kotlin.Unit
|
||||
context(Inv<A>, Inv<A>) public fun f8(): kotlin.Unit
|
||||
context(Inv<T>, Inv<A>) public fun </*0*/ T> f9(): kotlin.Unit
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public interface 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 interface B : 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
|
||||
}
|
||||
|
||||
context(A, A) public final class C1 {
|
||||
public constructor C1()
|
||||
context(A, A) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(A, A) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(Cov<A>, Cov<B>) public final class C10 {
|
||||
public constructor C10()
|
||||
context(Cov<A>, Cov<B>) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(Cov<A>, Cov<B>) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(Cov<T>, Cov<A>) public final class C11</*0*/ T> {
|
||||
public constructor C11</*0*/ T>()
|
||||
context(Cov<T>, Cov<A>) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(Cov<T>, Cov<A>) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(T, A) public final class C12</*0*/ T> {
|
||||
public constructor C12</*0*/ T>()
|
||||
context(T, A) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(T, A) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(A, B) public final class C2 {
|
||||
public constructor C2()
|
||||
context(A, B) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(A, B) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(A, C /* = B */) public final class C3 {
|
||||
public constructor C3()
|
||||
context(A, C /* = B */) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(A, C /* = B */) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(B, C /* = B */) public final class C4 {
|
||||
public constructor C4()
|
||||
context(B, C /* = B */) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(B, C /* = B */) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(C /* = B */, C /* = B */) public final class C5 {
|
||||
public constructor C5()
|
||||
context(C /* = B */, C /* = B */) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(C /* = B */, C /* = B */) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(A, A, A) public final class C6 {
|
||||
public constructor C6()
|
||||
context(A, A, A) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(A, A, A) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(Inv<A>, Inv<B>) public final class C7 {
|
||||
public constructor C7()
|
||||
context(Inv<A>, Inv<B>) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(Inv<A>, Inv<B>) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(Inv<A>, Inv<A>) public final class C8 {
|
||||
public constructor C8()
|
||||
context(Inv<A>, Inv<A>) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(Inv<A>, Inv<A>) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
context(Inv<T>, Inv<A>) public final class C9</*0*/ T> {
|
||||
public constructor C9</*0*/ T>()
|
||||
context(Inv<T>, Inv<A>) public final val p: kotlin.Any
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
context(Inv<T>, Inv<A>) public final fun m(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface Cov</*0*/ out 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
|
||||
}
|
||||
|
||||
public interface Inv</*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
|
||||
}
|
||||
public typealias C = B
|
||||
Generated
+6
@@ -10925,6 +10925,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/plusMatrix.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("subtypingBetweenContextReceivers.kt")
|
||||
public void testSubtypingBetweenContextReceivers() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/subtypingBetweenContextReceivers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("superWithContext.kt")
|
||||
public void testSuperWithContext() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user