[FIR] KT-59368 context receiver subtyping checker
This commit is contained in:
+6
@@ -2105,6 +2105,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.SUBTYPING_BETWEEN_CONTEXT_RECEIVERS) { firDiagnostic ->
|
||||
SubtypingBetweenContextReceiversImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.RECURSION_IN_IMPLICIT_TYPES) { firDiagnostic ->
|
||||
RecursionInImplicitTypesImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
|
||||
+4
@@ -1500,6 +1500,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = UnsupportedContextualDeclarationCall::class
|
||||
}
|
||||
|
||||
interface SubtypingBetweenContextReceivers : KtFirDiagnostic<KtElement> {
|
||||
override val diagnosticClass get() = SubtypingBetweenContextReceivers::class
|
||||
}
|
||||
|
||||
interface RecursionInImplicitTypes : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = RecursionInImplicitTypes::class
|
||||
}
|
||||
|
||||
+5
@@ -1800,6 +1800,11 @@ internal class UnsupportedContextualDeclarationCallImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.UnsupportedContextualDeclarationCall
|
||||
|
||||
internal class SubtypingBetweenContextReceiversImpl(
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.SubtypingBetweenContextReceivers
|
||||
|
||||
internal class RecursionInImplicitTypesImpl(
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
FILE: contextReceiversSubtyping.kt
|
||||
public abstract interface D : R|D1|, R|D2| {
|
||||
}
|
||||
public abstract interface D1 : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface D2 : R|kotlin/Any| {
|
||||
}
|
||||
context(R|T|, R|D2|)
|
||||
public final fun <T : R|D1|, R|D2|> foo(): R|kotlin/Unit| {
|
||||
}
|
||||
public abstract interface Cov<out T> : R|kotlin/Any| {
|
||||
}
|
||||
public final class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final class B : R|kotlin/Any| {
|
||||
public constructor(): R|B| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
context(R|Cov<T>|, R|Cov<B>|)
|
||||
public final fun <T : R|A|> foo(): R|kotlin/Unit| {
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: +ContextReceivers
|
||||
|
||||
interface D: D1, D2 {}
|
||||
interface D1 {}
|
||||
interface D2 {}
|
||||
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(T, D2)<!>
|
||||
fun <T> foo() where T: D1, T: D2 {}
|
||||
|
||||
interface Cov<out T> {}
|
||||
class A {}
|
||||
class B {}
|
||||
|
||||
// This sholdn't be an error since the type parameter is predetermined to be `A`,
|
||||
// which causes that there can't be subtyping between the context receivers.
|
||||
// However, the cheking is simplified because it is time-consuming process.
|
||||
<!SUBTYPING_BETWEEN_CONTEXT_RECEIVERS!>context(Cov<T>, Cov<B>)<!>
|
||||
fun <T: <!FINAL_UPPER_BOUND!>A<!>> foo() {}
|
||||
+6
@@ -1503,6 +1503,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/checkers/complexConflictingProjections.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("contextReceiversSubtyping.kt")
|
||||
public void testContextReceiversSubtyping() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/checkers/contextReceiversSubtyping.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("importAnnotationWithRequiresOptIn.kt")
|
||||
public void testImportAnnotationWithRequiresOptIn() throws Exception {
|
||||
|
||||
+6
@@ -1503,6 +1503,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/checkers/complexConflictingProjections.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("contextReceiversSubtyping.kt")
|
||||
public void testContextReceiversSubtyping() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/checkers/contextReceiversSubtyping.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("importAnnotationWithRequiresOptIn.kt")
|
||||
public void testImportAnnotationWithRequiresOptIn() throws Exception {
|
||||
|
||||
+1
@@ -676,6 +676,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
}
|
||||
val AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED)
|
||||
val UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL by error<KtElement>(PositioningStrategy.NAME_IDENTIFIER)
|
||||
val SUBTYPING_BETWEEN_CONTEXT_RECEIVERS by error<KtElement>(PositioningStrategy.DEFAULT)
|
||||
}
|
||||
|
||||
val TYPES_AND_TYPE_PARAMETERS by object : DiagnosticGroup("Types & type parameters") {
|
||||
|
||||
@@ -415,6 +415,7 @@ object FirErrors {
|
||||
val MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER by error0<KtElement>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL by error0<KtElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val SUBTYPING_BETWEEN_CONTEXT_RECEIVERS by error0<KtElement>()
|
||||
|
||||
// Types & type parameters
|
||||
val RECURSION_IN_IMPLICIT_TYPES by error0<PsiElement>()
|
||||
|
||||
+1
@@ -263,6 +263,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
||||
"MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER",
|
||||
"AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER",
|
||||
"UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL",
|
||||
"SUBTYPING_BETWEEN_CONTEXT_RECEIVERS",
|
||||
"RECURSION_IN_IMPLICIT_TYPES",
|
||||
"INFERENCE_ERROR",
|
||||
"PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT",
|
||||
|
||||
@@ -5,10 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import org.jetbrains.kotlin.KtLightSourceElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.findChildByType
|
||||
import org.jetbrains.kotlin.diagnostics.findDescendantByType
|
||||
import org.jetbrains.kotlin.diagnostics.traverseDescendants
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.toKtLightSourceElement
|
||||
import org.jetbrains.kotlin.util.getChildren
|
||||
|
||||
|
||||
/**
|
||||
@@ -23,3 +32,17 @@ fun KtModifierKeywordToken.toVisibilityOrNull(): Visibility? {
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates first [CONTEXT_RECEIVER_LIST] and returns position in source.
|
||||
*/
|
||||
fun KtSourceElement.findContextReceiverListSource(): KtLightSourceElement? {
|
||||
if (this.lighterASTNode.tokenType == KtNodeTypes.CONTEXT_RECEIVER_LIST)
|
||||
return this.lighterASTNode.toKtLightSourceElement(treeStructure)
|
||||
|
||||
return treeStructure.findDescendantByType(
|
||||
lighterASTNode,
|
||||
KtNodeTypes.CONTEXT_RECEIVER_LIST,
|
||||
false
|
||||
)?.toKtLightSourceElement(treeStructure)
|
||||
}
|
||||
|
||||
+52
-34
@@ -5,27 +5,34 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.KtLightSourceElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes.CONTEXT_RECEIVER_LIST
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.findContextReceiverListSource
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.toKtLightSourceElement
|
||||
import org.jetbrains.kotlin.util.getChildren
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
|
||||
object FirContextReceiversDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) return
|
||||
if (declaration.source?.kind is KtFakeSourceElementKind) return
|
||||
if (!declaration.hasContextReceiver()) return
|
||||
val contextReceivers = declaration.getContextReceiver()
|
||||
if (contextReceivers.isEmpty()) return
|
||||
val source = declaration.source?.findContextReceiverListSource() ?: return
|
||||
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) {
|
||||
if (checkSubTypes(contextReceivers.map { it.typeRef.coneType }, context)) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.SUBTYPING_BETWEEN_CONTEXT_RECEIVERS,
|
||||
context
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.UNSUPPORTED_FEATURE,
|
||||
@@ -34,36 +41,47 @@ object FirContextReceiversDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
)
|
||||
}
|
||||
|
||||
private fun FirDeclaration.hasContextReceiver(): Boolean {
|
||||
val contextReceivers = when (this) {
|
||||
private fun FirDeclaration.getContextReceiver(): List<FirContextReceiver> {
|
||||
return when (this) {
|
||||
is FirCallableDeclaration -> contextReceivers
|
||||
is FirRegularClass -> contextReceivers
|
||||
is FirScript -> contextReceivers
|
||||
else -> emptyList()
|
||||
}
|
||||
return contextReceivers.isNotEmpty()
|
||||
}
|
||||
|
||||
|
||||
private fun KtSourceElement.findContextReceiverListSource(): KtLightSourceElement? {
|
||||
var contextReceiverList: LighterASTNode? = null
|
||||
var contextReceiverListOffset = startOffset
|
||||
|
||||
val nodes = lighterASTNode.getChildren(treeStructure)
|
||||
for (node in nodes) {
|
||||
if (node.tokenType == CONTEXT_RECEIVER_LIST) {
|
||||
contextReceiverList = node
|
||||
break
|
||||
} else {
|
||||
contextReceiverListOffset += node.endOffset - node.startOffset
|
||||
}
|
||||
}
|
||||
if (contextReceiverList == null) return null
|
||||
|
||||
return contextReceiverList.toKtLightSourceElement(
|
||||
treeStructure,
|
||||
startOffset = contextReceiverListOffset,
|
||||
endOffset = contextReceiverListOffset + contextReceiverList.textLength,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified checking of subtype relation used in context receiver checkers.
|
||||
* It converts type parameters to star projections and top level type parameters to its supertypes. Then it checks the relation.
|
||||
*/
|
||||
fun checkSubTypes(types: List<ConeKotlinType>, context: CheckerContext): Boolean {
|
||||
fun replaceTypeParametersByStarProjections(type: ConeClassLikeType): ConeClassLikeType {
|
||||
return type.withArguments(type.typeArguments.map {
|
||||
when {
|
||||
it.isStarProjection -> it
|
||||
it.type!! is ConeTypeParameterType -> ConeStarProjection
|
||||
it.type!! is ConeClassLikeType -> replaceTypeParametersByStarProjections(it.type as ConeClassLikeType)
|
||||
else -> it
|
||||
}
|
||||
}.toTypedArray())
|
||||
}
|
||||
|
||||
val replacedTypeParameters = types.flatMap { r ->
|
||||
when (r) {
|
||||
is ConeTypeParameterType -> r.lookupTag.typeParameterSymbol.resolvedBounds.map { it.type }
|
||||
is ConeClassLikeType -> listOf(replaceTypeParametersByStarProjections(r))
|
||||
else -> listOf(r)
|
||||
}
|
||||
}
|
||||
|
||||
for (i in replacedTypeParameters.indices)
|
||||
for (j in i + 1..<replacedTypeParameters.size) {
|
||||
if (replacedTypeParameters[i].isSubtypeOf(replacedTypeParameters[j], context.session)
|
||||
|| replacedTypeParameters[j].isSubtypeOf(replacedTypeParameters[i], context.session)
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
+22
-11
@@ -5,29 +5,40 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.checkSubTypes
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.findContextReceiverListSource
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
|
||||
object FirContextReceiversTypeChecker : FirTypeRefChecker() {
|
||||
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) return
|
||||
if (typeRef !is FirResolvedTypeRef) return
|
||||
val source = typeRef.source ?: return
|
||||
if (source.kind is KtFakeSourceElementKind) return
|
||||
if (typeRef.source?.kind is KtFakeSourceElementKind) return
|
||||
if (!typeRef.coneType.hasContextReceivers) return
|
||||
val source = typeRef.source?.findContextReceiverListSource() ?: return
|
||||
|
||||
if (typeRef.coneType.hasContextReceivers) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.UNSUPPORTED_FEATURE,
|
||||
LanguageFeature.ContextReceivers to context.languageVersionSettings,
|
||||
context
|
||||
)
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) {
|
||||
if (checkSubTypes(typeRef.coneType.contextReceiversTypes(context.session), context)) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.SUBTYPING_BETWEEN_CONTEXT_RECEIVERS,
|
||||
context
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.UNSUPPORTED_FEATURE,
|
||||
LanguageFeature.ContextReceivers to context.languageVersionSettings,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -581,6 +581,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SINGLE_ANONYMOUS_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SMARTCAST_IMPOSSIBLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SPREAD_OF_NULLABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUBCLASS_OPT_IN_INAPPLICABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUBTYPING_BETWEEN_CONTEXT_RECEIVERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPES_FOR_ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_APPEARS_TWICE
|
||||
@@ -1276,6 +1277,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
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."
|
||||
)
|
||||
|
||||
// Ambiguity
|
||||
map.put(OVERLOAD_RESOLUTION_AMBIGUITY, "Overload resolution ambiguity between candidates: {0}", SYMBOLS)
|
||||
|
||||
-221
@@ -1,221 +0,0 @@
|
||||
// !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
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNCHECKED_CAST
|
||||
// !LANGUAGE: +ContextReceivers
|
||||
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
// !DIAGNOSTICS: -UNCHECKED_CAST
|
||||
|
||||
<!UNSUPPORTED_FEATURE!>context(Any)<!>
|
||||
fun f(g: <!UNSUPPORTED_FEATURE!>context(Any) () -> Unit<!>, value: Any): <!UNSUPPORTED_FEATURE!>context(A) () -> Unit<!> {
|
||||
return value as <!UNSUPPORTED_FEATURE!>(context(A) () -> Unit)<!>
|
||||
fun f(g: <!UNSUPPORTED_FEATURE!>context(Any)<!> () -> Unit, value: Any): <!UNSUPPORTED_FEATURE!>context(A)<!> () -> Unit {
|
||||
return value as (<!UNSUPPORTED_FEATURE!>context(A)<!> () -> Unit)
|
||||
}
|
||||
|
||||
fun f(g: () -> Unit, value: Any) : () -> Unit {
|
||||
|
||||
Reference in New Issue
Block a user