FIR2IR: Fix substitution work for context receivers
This commit is contained in:
+12
@@ -16752,12 +16752,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutedContextReceivers.kt")
|
||||||
|
public void testSubstitutedContextReceivers() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/substitutedContextReceivers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("superClassAndSubClassWithContextReceiver.kt")
|
@TestMetadata("superClassAndSubClassWithContextReceiver.kt")
|
||||||
public void testSuperClassAndSubClassWithContextReceiver() throws Exception {
|
public void testSuperClassAndSubClassWithContextReceiver() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/superClassAndSubClassWithContextReceiver.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/superClassAndSubClassWithContextReceiver.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("superClassAndSubClassWithContextReceiverSubstituted.kt")
|
||||||
|
public void testSuperClassAndSubClassWithContextReceiverSubstituted() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/superClassAndSubClassWithContextReceiverSubstituted.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("suspendContextualWithExtension.kt")
|
@TestMetadata("suspendContextualWithExtension.kt")
|
||||||
public void testSuspendContextualWithExtension() throws Exception {
|
public void testSuspendContextualWithExtension() throws Exception {
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ class JvmMappedScope(
|
|||||||
newReturnType = substitutor.substituteOrSelf(oldConstructor.returnTypeRef.coneType),
|
newReturnType = substitutor.substituteOrSelf(oldConstructor.returnTypeRef.coneType),
|
||||||
newParameterTypes = oldConstructor.valueParameters.map { substitutor.substituteOrSelf(it.returnTypeRef.coneType) },
|
newParameterTypes = oldConstructor.valueParameters.map { substitutor.substituteOrSelf(it.returnTypeRef.coneType) },
|
||||||
newTypeParameters = null,
|
newTypeParameters = null,
|
||||||
|
newContextReceiverTypes = emptyList(),
|
||||||
isExpect = false,
|
isExpect = false,
|
||||||
fakeOverrideSubstitution = null
|
fakeOverrideSubstitution = null
|
||||||
).apply {
|
).apply {
|
||||||
|
|||||||
+29
-3
@@ -135,11 +135,16 @@ class FirClassSubstitutionScope(
|
|||||||
it.returnTypeRef.coneType.substitute(newSubstitutor)
|
it.returnTypeRef.coneType.substitute(newSubstitutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val newContextReceiverTypes = member.contextReceivers.map {
|
||||||
|
it.typeRef.coneType.substitute(newSubstitutor)
|
||||||
|
}
|
||||||
|
|
||||||
if (newReceiverType == null &&
|
if (newReceiverType == null &&
|
||||||
newReturnType == null &&
|
newReturnType == null &&
|
||||||
newParameterTypes.all { it == null } &&
|
newParameterTypes.all { it == null } &&
|
||||||
newTypeParameters === member.typeParameters &&
|
newTypeParameters === member.typeParameters &&
|
||||||
fakeOverrideSubstitution == null
|
fakeOverrideSubstitution == null &&
|
||||||
|
newContextReceiverTypes.all { it == null }
|
||||||
) {
|
) {
|
||||||
if (original.dispatchReceiverType?.substitute(substitutor) != null) {
|
if (original.dispatchReceiverType?.substitute(substitutor) != null) {
|
||||||
return FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
|
return FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
|
||||||
@@ -164,6 +169,7 @@ class FirClassSubstitutionScope(
|
|||||||
member,
|
member,
|
||||||
newDispatchReceiverType ?: dispatchReceiverTypeForSubstitutedMembers,
|
newDispatchReceiverType ?: dispatchReceiverTypeForSubstitutedMembers,
|
||||||
newReceiverType,
|
newReceiverType,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
newParameterTypes,
|
newParameterTypes,
|
||||||
newTypeParameters as List<FirTypeParameter>,
|
newTypeParameters as List<FirTypeParameter>,
|
||||||
@@ -188,7 +194,15 @@ class FirClassSubstitutionScope(
|
|||||||
it.returnTypeRef.coneType.substitute(newSubstitutor)
|
it.returnTypeRef.coneType.substitute(newSubstitutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newReturnType == null && newParameterTypes.all { it == null } && newTypeParameters === constructor.typeParameters) {
|
val newContextReceiverTypes = constructor.contextReceivers.map {
|
||||||
|
it.typeRef.coneType.substitute(newSubstitutor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newReturnType == null &&
|
||||||
|
newParameterTypes.all { it == null } &&
|
||||||
|
newTypeParameters === constructor.typeParameters &&
|
||||||
|
newContextReceiverTypes.all { it == null }
|
||||||
|
) {
|
||||||
return original
|
return original
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +214,7 @@ class FirClassSubstitutionScope(
|
|||||||
newDispatchReceiverType,
|
newDispatchReceiverType,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
newParameterTypes,
|
newParameterTypes,
|
||||||
|
newContextReceiverTypes,
|
||||||
newTypeParameters,
|
newTypeParameters,
|
||||||
makeExpect,
|
makeExpect,
|
||||||
fakeOverrideSubstitution
|
fakeOverrideSubstitution
|
||||||
@@ -217,10 +232,15 @@ class FirClassSubstitutionScope(
|
|||||||
member, symbolForOverride
|
member, symbolForOverride
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val newContextReceiverTypes = member.contextReceivers.map {
|
||||||
|
it.typeRef.coneType.substitute(substitutor)
|
||||||
|
}
|
||||||
|
|
||||||
if (newReceiverType == null &&
|
if (newReceiverType == null &&
|
||||||
newReturnType == null &&
|
newReturnType == null &&
|
||||||
newTypeParameters === member.typeParameters &&
|
newTypeParameters === member.typeParameters &&
|
||||||
fakeOverrideSubstitution == null
|
fakeOverrideSubstitution == null &&
|
||||||
|
newContextReceiverTypes.all { it == null }
|
||||||
) {
|
) {
|
||||||
if (original.dispatchReceiverType?.substitute(substitutor) != null) {
|
if (original.dispatchReceiverType?.substitute(substitutor) != null) {
|
||||||
return FirFakeOverrideGenerator.createSubstitutionOverrideProperty(
|
return FirFakeOverrideGenerator.createSubstitutionOverrideProperty(
|
||||||
@@ -241,6 +261,7 @@ class FirClassSubstitutionScope(
|
|||||||
member,
|
member,
|
||||||
newDispatchReceiverType ?: dispatchReceiverTypeForSubstitutedMembers,
|
newDispatchReceiverType ?: dispatchReceiverTypeForSubstitutedMembers,
|
||||||
newReceiverType,
|
newReceiverType,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
newTypeParameters as List<FirTypeParameter>,
|
newTypeParameters as List<FirTypeParameter>,
|
||||||
makeExpect,
|
makeExpect,
|
||||||
@@ -316,6 +337,10 @@ class FirClassSubstitutionScope(
|
|||||||
it.returnTypeRef.coneType.substitute()
|
it.returnTypeRef.coneType.substitute()
|
||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
|
|
||||||
|
val newContextReceiverTypes = member.contextReceivers.map {
|
||||||
|
it.typeRef.coneType.substitute()
|
||||||
|
}
|
||||||
|
|
||||||
if (original.dispatchReceiverType?.substitute(substitutor) == null &&
|
if (original.dispatchReceiverType?.substitute(substitutor) == null &&
|
||||||
newReturnType == null &&
|
newReturnType == null &&
|
||||||
newGetterParameterTypes.all { it == null } &&
|
newGetterParameterTypes.all { it == null } &&
|
||||||
@@ -329,6 +354,7 @@ class FirClassSubstitutionScope(
|
|||||||
member,
|
member,
|
||||||
original,
|
original,
|
||||||
substitutor.substituteOrSelf(dispatchReceiverTypeForSubstitutedMembers) as ConeSimpleKotlinType?,
|
substitutor.substituteOrSelf(dispatchReceiverTypeForSubstitutedMembers) as ConeSimpleKotlinType?,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
newGetterParameterTypes,
|
newGetterParameterTypes,
|
||||||
newSetterParameterTypes,
|
newSetterParameterTypes,
|
||||||
|
|||||||
+66
-15
@@ -36,6 +36,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseFunction: FirSimpleFunction,
|
baseFunction: FirSimpleFunction,
|
||||||
newDispatchReceiverType: ConeSimpleKotlinType?,
|
newDispatchReceiverType: ConeSimpleKotlinType?,
|
||||||
newReceiverType: ConeKotlinType? = null,
|
newReceiverType: ConeKotlinType? = null,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>? = null,
|
||||||
newReturnType: ConeKotlinType? = null,
|
newReturnType: ConeKotlinType? = null,
|
||||||
newParameterTypes: List<ConeKotlinType?>? = null,
|
newParameterTypes: List<ConeKotlinType?>? = null,
|
||||||
newTypeParameters: List<FirTypeParameter>? = null,
|
newTypeParameters: List<FirTypeParameter>? = null,
|
||||||
@@ -43,8 +44,8 @@ object FirFakeOverrideGenerator {
|
|||||||
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
|
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
|
||||||
): FirNamedFunctionSymbol {
|
): FirNamedFunctionSymbol {
|
||||||
createSubstitutionOverrideFunction(
|
createSubstitutionOverrideFunction(
|
||||||
symbolForSubstitutionOverride, session, baseFunction, newDispatchReceiverType, newReceiverType, newReturnType,
|
symbolForSubstitutionOverride, session, baseFunction, newDispatchReceiverType, newReceiverType, newContextReceiverTypes,
|
||||||
newParameterTypes, newTypeParameters, isExpect, fakeOverrideSubstitution
|
newReturnType, newParameterTypes, newTypeParameters, isExpect, fakeOverrideSubstitution
|
||||||
)
|
)
|
||||||
return symbolForSubstitutionOverride
|
return symbolForSubstitutionOverride
|
||||||
}
|
}
|
||||||
@@ -63,6 +64,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseFunction: FirSimpleFunction,
|
baseFunction: FirSimpleFunction,
|
||||||
newDispatchReceiverType: ConeSimpleKotlinType?,
|
newDispatchReceiverType: ConeSimpleKotlinType?,
|
||||||
newReceiverType: ConeKotlinType?,
|
newReceiverType: ConeKotlinType?,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||||
newReturnType: ConeKotlinType?,
|
newReturnType: ConeKotlinType?,
|
||||||
newParameterTypes: List<ConeKotlinType?>?,
|
newParameterTypes: List<ConeKotlinType?>?,
|
||||||
newTypeParameters: List<FirTypeParameter>?,
|
newTypeParameters: List<FirTypeParameter>?,
|
||||||
@@ -81,6 +83,7 @@ object FirFakeOverrideGenerator {
|
|||||||
newParameterTypes,
|
newParameterTypes,
|
||||||
newTypeParameters,
|
newTypeParameters,
|
||||||
newReceiverType,
|
newReceiverType,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
fakeOverrideSubstitution = fakeOverrideSubstitution
|
fakeOverrideSubstitution = fakeOverrideSubstitution
|
||||||
).apply {
|
).apply {
|
||||||
@@ -98,6 +101,7 @@ object FirFakeOverrideGenerator {
|
|||||||
newParameterTypes: List<ConeKotlinType?>? = null,
|
newParameterTypes: List<ConeKotlinType?>? = null,
|
||||||
newTypeParameters: List<FirTypeParameter>? = null,
|
newTypeParameters: List<FirTypeParameter>? = null,
|
||||||
newReceiverType: ConeKotlinType? = null,
|
newReceiverType: ConeKotlinType? = null,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>? = null,
|
||||||
newReturnType: ConeKotlinType? = null,
|
newReturnType: ConeKotlinType? = null,
|
||||||
newModality: Modality? = null,
|
newModality: Modality? = null,
|
||||||
newVisibility: Visibility? = null,
|
newVisibility: Visibility? = null,
|
||||||
@@ -116,7 +120,7 @@ object FirFakeOverrideGenerator {
|
|||||||
attributes = baseFunction.attributes.copy()
|
attributes = baseFunction.attributes.copy()
|
||||||
typeParameters += configureAnnotationsTypeParametersAndSignature(
|
typeParameters += configureAnnotationsTypeParametersAndSignature(
|
||||||
session, baseFunction, newParameterTypes, newTypeParameters,
|
session, baseFunction, newParameterTypes, newTypeParameters,
|
||||||
newReceiverType, newReturnType, fakeOverrideSubstitution, newSymbol
|
newReceiverType, newContextReceiverTypes, newReturnType, fakeOverrideSubstitution, newSymbol
|
||||||
).filterIsInstance<FirTypeParameter>()
|
).filterIsInstance<FirTypeParameter>()
|
||||||
deprecation = baseFunction.deprecation
|
deprecation = baseFunction.deprecation
|
||||||
}
|
}
|
||||||
@@ -130,6 +134,7 @@ object FirFakeOverrideGenerator {
|
|||||||
newDispatchReceiverType: ConeSimpleKotlinType?,
|
newDispatchReceiverType: ConeSimpleKotlinType?,
|
||||||
newReturnType: ConeKotlinType?,
|
newReturnType: ConeKotlinType?,
|
||||||
newParameterTypes: List<ConeKotlinType?>?,
|
newParameterTypes: List<ConeKotlinType?>?,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||||
newTypeParameters: List<FirTypeParameterRef>?,
|
newTypeParameters: List<FirTypeParameterRef>?,
|
||||||
isExpect: Boolean,
|
isExpect: Boolean,
|
||||||
fakeOverrideSubstitution: FakeOverrideSubstitution?
|
fakeOverrideSubstitution: FakeOverrideSubstitution?
|
||||||
@@ -149,6 +154,7 @@ object FirFakeOverrideGenerator {
|
|||||||
newParameterTypes,
|
newParameterTypes,
|
||||||
newTypeParameters,
|
newTypeParameters,
|
||||||
newReceiverType = null,
|
newReceiverType = null,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
fakeOverrideSubstitution,
|
fakeOverrideSubstitution,
|
||||||
fakeOverrideSymbol
|
fakeOverrideSymbol
|
||||||
@@ -171,6 +177,7 @@ object FirFakeOverrideGenerator {
|
|||||||
newParameterTypes: List<ConeKotlinType?>?,
|
newParameterTypes: List<ConeKotlinType?>?,
|
||||||
newTypeParameters: List<FirTypeParameterRef>?,
|
newTypeParameters: List<FirTypeParameterRef>?,
|
||||||
newReceiverType: ConeKotlinType?,
|
newReceiverType: ConeKotlinType?,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||||
newReturnType: ConeKotlinType?,
|
newReturnType: ConeKotlinType?,
|
||||||
fakeOverrideSubstitution: FakeOverrideSubstitution?,
|
fakeOverrideSubstitution: FakeOverrideSubstitution?,
|
||||||
symbolForOverride: FirBasedSymbol<*>,
|
symbolForOverride: FirBasedSymbol<*>,
|
||||||
@@ -181,6 +188,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseFunction,
|
baseFunction,
|
||||||
newParameterTypes,
|
newParameterTypes,
|
||||||
newReceiverType,
|
newReceiverType,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
fakeOverrideSubstitution
|
fakeOverrideSubstitution
|
||||||
)
|
)
|
||||||
@@ -194,8 +202,8 @@ object FirFakeOverrideGenerator {
|
|||||||
substitutor.substituteOrNull(it.returnTypeRef.coneType)
|
substitutor.substituteOrNull(it.returnTypeRef.coneType)
|
||||||
}
|
}
|
||||||
val symbol = baseFunction.symbol
|
val symbol = baseFunction.symbol
|
||||||
val (copiedReceiverType, possibleReturnType) = substituteReceiverAndReturnType(
|
val (copiedReceiverType, copiedContextReceiverTypes, possibleReturnType) = substituteReceiverAndReturnType(
|
||||||
baseFunction as FirCallableDeclaration, newReceiverType, newReturnType, substitutor
|
baseFunction as FirCallableDeclaration, newReceiverType, newContextReceiverTypes, newReturnType, substitutor
|
||||||
)
|
)
|
||||||
val (copiedReturnType, newFakeOverrideSubstitution) = when (possibleReturnType) {
|
val (copiedReturnType, newFakeOverrideSubstitution) = when (possibleReturnType) {
|
||||||
is Maybe.Value -> possibleReturnType.value to null
|
is Maybe.Value -> possibleReturnType.value to null
|
||||||
@@ -205,6 +213,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseFunction,
|
baseFunction,
|
||||||
copiedParameterTypes,
|
copiedParameterTypes,
|
||||||
copiedReceiverType,
|
copiedReceiverType,
|
||||||
|
copiedContextReceiverTypes,
|
||||||
copiedReturnType,
|
copiedReturnType,
|
||||||
newFakeOverrideSubstitution
|
newFakeOverrideSubstitution
|
||||||
)
|
)
|
||||||
@@ -215,6 +224,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseFunction,
|
baseFunction,
|
||||||
newParameterTypes,
|
newParameterTypes,
|
||||||
newReceiverType,
|
newReceiverType,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
fakeOverrideSubstitution
|
fakeOverrideSubstitution
|
||||||
)
|
)
|
||||||
@@ -227,8 +237,9 @@ object FirFakeOverrideGenerator {
|
|||||||
baseFunction: FirFunction,
|
baseFunction: FirFunction,
|
||||||
newParameterTypes: List<ConeKotlinType?>?,
|
newParameterTypes: List<ConeKotlinType?>?,
|
||||||
newReceiverType: ConeKotlinType?,
|
newReceiverType: ConeKotlinType?,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||||
newReturnType: ConeKotlinType?,
|
newReturnType: ConeKotlinType?,
|
||||||
fakeOverrideSubstitution: FakeOverrideSubstitution?
|
fakeOverrideSubstitution: FakeOverrideSubstitution?,
|
||||||
) {
|
) {
|
||||||
annotations += baseFunction.annotations
|
annotations += baseFunction.annotations
|
||||||
|
|
||||||
@@ -256,6 +267,14 @@ object FirFakeOverrideGenerator {
|
|||||||
symbol = FirValueParameterSymbol(valueParameter.name)
|
symbol = FirValueParameterSymbol(valueParameter.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contextReceivers += baseFunction.contextReceivers.zip(
|
||||||
|
newContextReceiverTypes ?: List(baseFunction.contextReceivers.size) { null }
|
||||||
|
) { contextReceiver, newType ->
|
||||||
|
buildContextReceiverCopy(contextReceiver) {
|
||||||
|
typeRef = contextReceiver.typeRef.withReplacedConeType(newType)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createSubstitutionOverrideProperty(
|
fun createSubstitutionOverrideProperty(
|
||||||
@@ -264,6 +283,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseProperty: FirProperty,
|
baseProperty: FirProperty,
|
||||||
newDispatchReceiverType: ConeSimpleKotlinType?,
|
newDispatchReceiverType: ConeSimpleKotlinType?,
|
||||||
newReceiverType: ConeKotlinType? = null,
|
newReceiverType: ConeKotlinType? = null,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>? = null,
|
||||||
newReturnType: ConeKotlinType? = null,
|
newReturnType: ConeKotlinType? = null,
|
||||||
newTypeParameters: List<FirTypeParameter>? = null,
|
newTypeParameters: List<FirTypeParameter>? = null,
|
||||||
isExpect: Boolean = baseProperty.isExpect,
|
isExpect: Boolean = baseProperty.isExpect,
|
||||||
@@ -271,7 +291,7 @@ object FirFakeOverrideGenerator {
|
|||||||
): FirPropertySymbol {
|
): FirPropertySymbol {
|
||||||
createCopyForFirProperty(
|
createCopyForFirProperty(
|
||||||
symbolForSubstitutionOverride, baseProperty, session, FirDeclarationOrigin.SubstitutionOverride, isExpect,
|
symbolForSubstitutionOverride, baseProperty, session, FirDeclarationOrigin.SubstitutionOverride, isExpect,
|
||||||
newDispatchReceiverType, newTypeParameters, newReceiverType, newReturnType,
|
newDispatchReceiverType, newTypeParameters, newReceiverType, newContextReceiverTypes, newReturnType,
|
||||||
fakeOverrideSubstitution = fakeOverrideSubstitution
|
fakeOverrideSubstitution = fakeOverrideSubstitution
|
||||||
).apply {
|
).apply {
|
||||||
originalForSubstitutionOverrideAttr = baseProperty
|
originalForSubstitutionOverrideAttr = baseProperty
|
||||||
@@ -296,6 +316,7 @@ object FirFakeOverrideGenerator {
|
|||||||
newDispatchReceiverType: ConeSimpleKotlinType?,
|
newDispatchReceiverType: ConeSimpleKotlinType?,
|
||||||
newTypeParameters: List<FirTypeParameter>? = null,
|
newTypeParameters: List<FirTypeParameter>? = null,
|
||||||
newReceiverType: ConeKotlinType? = null,
|
newReceiverType: ConeKotlinType? = null,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>? = null,
|
||||||
newReturnType: ConeKotlinType? = null,
|
newReturnType: ConeKotlinType? = null,
|
||||||
newModality: Modality? = null,
|
newModality: Modality? = null,
|
||||||
newVisibility: Visibility? = null,
|
newVisibility: Visibility? = null,
|
||||||
@@ -319,6 +340,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseProperty,
|
baseProperty,
|
||||||
newTypeParameters,
|
newTypeParameters,
|
||||||
newReceiverType,
|
newReceiverType,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
fakeOverrideSubstitution
|
fakeOverrideSubstitution
|
||||||
)
|
)
|
||||||
@@ -331,30 +353,37 @@ object FirFakeOverrideGenerator {
|
|||||||
baseProperty: FirProperty,
|
baseProperty: FirProperty,
|
||||||
newTypeParameters: List<FirTypeParameter>?,
|
newTypeParameters: List<FirTypeParameter>?,
|
||||||
newReceiverType: ConeKotlinType?,
|
newReceiverType: ConeKotlinType?,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||||
newReturnType: ConeKotlinType?,
|
newReturnType: ConeKotlinType?,
|
||||||
fakeOverrideSubstitution: FakeOverrideSubstitution?
|
fakeOverrideSubstitution: FakeOverrideSubstitution?
|
||||||
): List<FirTypeParameter> {
|
): List<FirTypeParameter> {
|
||||||
return when {
|
return when {
|
||||||
baseProperty.typeParameters.isEmpty() -> {
|
baseProperty.typeParameters.isEmpty() -> {
|
||||||
configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType, fakeOverrideSubstitution)
|
configureAnnotationsAndSignature(
|
||||||
|
baseProperty, newReceiverType, newContextReceiverTypes, newReturnType, fakeOverrideSubstitution
|
||||||
|
)
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
newTypeParameters == null -> {
|
newTypeParameters == null -> {
|
||||||
val (copiedTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor(
|
val (copiedTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor(
|
||||||
useSiteSession, baseProperty, symbol, ConeSubstitutor.Empty
|
useSiteSession, baseProperty, symbol, ConeSubstitutor.Empty
|
||||||
)
|
)
|
||||||
val (copiedReceiverType, possibleReturnType) = substituteReceiverAndReturnType(
|
val (copiedReceiverType, copiedContextReceiverTypes, possibleReturnType) = substituteReceiverAndReturnType(
|
||||||
baseProperty, newReceiverType, newReturnType, substitutor
|
baseProperty, newReceiverType, newContextReceiverTypes, newReturnType, substitutor
|
||||||
)
|
)
|
||||||
val (copiedReturnType, newFakeOverrideSubstitution) = when (possibleReturnType) {
|
val (copiedReturnType, newFakeOverrideSubstitution) = when (possibleReturnType) {
|
||||||
is Maybe.Value -> possibleReturnType.value to null
|
is Maybe.Value -> possibleReturnType.value to null
|
||||||
else -> null to FakeOverrideSubstitution(substitutor, baseProperty.symbol)
|
else -> null to FakeOverrideSubstitution(substitutor, baseProperty.symbol)
|
||||||
}
|
}
|
||||||
configureAnnotationsAndSignature(baseProperty, copiedReceiverType, copiedReturnType, newFakeOverrideSubstitution)
|
configureAnnotationsAndSignature(
|
||||||
|
baseProperty, copiedReceiverType, copiedContextReceiverTypes, copiedReturnType, newFakeOverrideSubstitution
|
||||||
|
)
|
||||||
copiedTypeParameters.filterIsInstance<FirTypeParameter>()
|
copiedTypeParameters.filterIsInstance<FirTypeParameter>()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType, fakeOverrideSubstitution)
|
configureAnnotationsAndSignature(
|
||||||
|
baseProperty, newReceiverType, newContextReceiverTypes, newReturnType, fakeOverrideSubstitution
|
||||||
|
)
|
||||||
newTypeParameters
|
newTypeParameters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,27 +392,39 @@ object FirFakeOverrideGenerator {
|
|||||||
private fun substituteReceiverAndReturnType(
|
private fun substituteReceiverAndReturnType(
|
||||||
baseCallable: FirCallableDeclaration,
|
baseCallable: FirCallableDeclaration,
|
||||||
newReceiverType: ConeKotlinType?,
|
newReceiverType: ConeKotlinType?,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||||
newReturnType: ConeKotlinType?,
|
newReturnType: ConeKotlinType?,
|
||||||
substitutor: ConeSubstitutor
|
substitutor: ConeSubstitutor
|
||||||
): Pair<ConeKotlinType?, Maybe<ConeKotlinType?>> {
|
): Triple<ConeKotlinType?, List<ConeKotlinType?>, Maybe<ConeKotlinType?>> {
|
||||||
val copiedReceiverType = newReceiverType?.let {
|
val copiedReceiverType = newReceiverType?.let {
|
||||||
substitutor.substituteOrNull(it)
|
substitutor.substituteOrNull(it)
|
||||||
} ?: baseCallable.receiverTypeRef?.let {
|
} ?: baseCallable.receiverTypeRef?.let {
|
||||||
substitutor.substituteOrNull(it.coneType)
|
substitutor.substituteOrNull(it.coneType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val copiedContextReceiverTypes = newContextReceiverTypes?.map {
|
||||||
|
it?.type?.let(substitutor::substituteOrNull)
|
||||||
|
} ?: baseCallable.contextReceivers.map {
|
||||||
|
substitutor.substituteOrNull(it.typeRef.coneType)
|
||||||
|
}
|
||||||
|
|
||||||
val copiedReturnType = newReturnType?.let {
|
val copiedReturnType = newReturnType?.let {
|
||||||
substitutor.substituteOrNull(it)
|
substitutor.substituteOrNull(it)
|
||||||
} ?: baseCallable.returnTypeRef.let {
|
} ?: baseCallable.returnTypeRef.let {
|
||||||
val coneType = baseCallable.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: return copiedReceiverType to Maybe.Nothing
|
val coneType = baseCallable.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: return Triple(
|
||||||
|
copiedReceiverType,
|
||||||
|
copiedContextReceiverTypes,
|
||||||
|
Maybe.Nothing,
|
||||||
|
)
|
||||||
substitutor.substituteOrNull(coneType)
|
substitutor.substituteOrNull(coneType)
|
||||||
}
|
}
|
||||||
return copiedReceiverType to Maybe.Value(copiedReturnType)
|
return Triple(copiedReceiverType, copiedContextReceiverTypes, Maybe.Value(copiedReturnType))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirPropertyBuilder.configureAnnotationsAndSignature(
|
private fun FirPropertyBuilder.configureAnnotationsAndSignature(
|
||||||
baseProperty: FirProperty,
|
baseProperty: FirProperty,
|
||||||
newReceiverType: ConeKotlinType?,
|
newReceiverType: ConeKotlinType?,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||||
newReturnType: ConeKotlinType?,
|
newReturnType: ConeKotlinType?,
|
||||||
fakeOverrideSubstitution: FakeOverrideSubstitution?
|
fakeOverrideSubstitution: FakeOverrideSubstitution?
|
||||||
) {
|
) {
|
||||||
@@ -400,6 +441,13 @@ object FirFakeOverrideGenerator {
|
|||||||
returnTypeRef = baseProperty.returnTypeRef.withReplacedReturnType(newReturnType)
|
returnTypeRef = baseProperty.returnTypeRef.withReplacedReturnType(newReturnType)
|
||||||
}
|
}
|
||||||
receiverTypeRef = baseProperty.receiverTypeRef?.withReplacedConeType(newReceiverType)
|
receiverTypeRef = baseProperty.receiverTypeRef?.withReplacedConeType(newReceiverType)
|
||||||
|
contextReceivers += baseProperty.contextReceivers.zip(
|
||||||
|
newContextReceiverTypes ?: List(baseProperty.contextReceivers.size) { null }
|
||||||
|
) { contextReceiver, newType ->
|
||||||
|
buildContextReceiverCopy(contextReceiver) {
|
||||||
|
typeRef = contextReceiver.typeRef.withReplacedConeType(newType)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createSubstitutionOverrideField(
|
fun createSubstitutionOverrideField(
|
||||||
@@ -438,6 +486,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseProperty: FirSyntheticProperty,
|
baseProperty: FirSyntheticProperty,
|
||||||
baseSymbol: FirSyntheticPropertySymbol,
|
baseSymbol: FirSyntheticPropertySymbol,
|
||||||
newDispatchReceiverType: ConeSimpleKotlinType?,
|
newDispatchReceiverType: ConeSimpleKotlinType?,
|
||||||
|
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||||
newReturnType: ConeKotlinType?,
|
newReturnType: ConeKotlinType?,
|
||||||
newGetterParameterTypes: List<ConeKotlinType?>?,
|
newGetterParameterTypes: List<ConeKotlinType?>?,
|
||||||
newSetterParameterTypes: List<ConeKotlinType?>?,
|
newSetterParameterTypes: List<ConeKotlinType?>?,
|
||||||
@@ -450,6 +499,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseProperty.getter.delegate,
|
baseProperty.getter.delegate,
|
||||||
newDispatchReceiverType,
|
newDispatchReceiverType,
|
||||||
newReceiverType = null,
|
newReceiverType = null,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType,
|
newReturnType,
|
||||||
newGetterParameterTypes,
|
newGetterParameterTypes,
|
||||||
newTypeParameters = null,
|
newTypeParameters = null,
|
||||||
@@ -463,6 +513,7 @@ object FirFakeOverrideGenerator {
|
|||||||
baseSetter.delegate,
|
baseSetter.delegate,
|
||||||
newDispatchReceiverType,
|
newDispatchReceiverType,
|
||||||
newReceiverType = null,
|
newReceiverType = null,
|
||||||
|
newContextReceiverTypes,
|
||||||
StandardClassIds.Unit.constructClassLikeType(emptyArray(), isNullable = false),
|
StandardClassIds.Unit.constructClassLikeType(emptyArray(), isNullable = false),
|
||||||
newSetterParameterTypes,
|
newSetterParameterTypes,
|
||||||
newTypeParameters = null,
|
newTypeParameters = null,
|
||||||
|
|||||||
+6
-1
@@ -15,12 +15,12 @@ import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
|||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
||||||
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
|
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
|
||||||
import org.jetbrains.kotlin.fir.scopes.scopeForClass
|
import org.jetbrains.kotlin.fir.scopes.scopeForClass
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||||
@@ -197,6 +197,10 @@ private fun FirTypeAliasSymbol.findSAMConstructorForTypeAlias(
|
|||||||
valueParameter.returnTypeRef.coneType.let(substitutor::substituteOrNull)
|
valueParameter.returnTypeRef.coneType.let(substitutor::substituteOrNull)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val newContextReceiverTypes = samConstructorForClass.contextReceivers.map { contextReceiver ->
|
||||||
|
contextReceiver.typeRef.coneType.let(substitutor::substituteOrNull)
|
||||||
|
}
|
||||||
|
|
||||||
if (newReturnType == null && newParameterTypes.all { it == null }) return samConstructorForClass
|
if (newReturnType == null && newParameterTypes.all { it == null }) return samConstructorForClass
|
||||||
|
|
||||||
val symbolForOverride = FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(namedSymbol, expansionRegularClass.classId)
|
val symbolForOverride = FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(namedSymbol, expansionRegularClass.classId)
|
||||||
@@ -205,6 +209,7 @@ private fun FirTypeAliasSymbol.findSAMConstructorForTypeAlias(
|
|||||||
session, symbolForOverride, samConstructorForClass,
|
session, symbolForOverride, samConstructorForClass,
|
||||||
newDispatchReceiverType = null,
|
newDispatchReceiverType = null,
|
||||||
newReceiverType = null,
|
newReceiverType = null,
|
||||||
|
newContextReceiverTypes,
|
||||||
newReturnType, newParameterTypes, typeParameters,
|
newReturnType, newParameterTypes, typeParameters,
|
||||||
).fir
|
).fir
|
||||||
}
|
}
|
||||||
|
|||||||
+13
@@ -44,3 +44,16 @@ inline fun buildContextReceiver(init: FirContextReceiverBuilder.() -> Unit): Fir
|
|||||||
}
|
}
|
||||||
return FirContextReceiverBuilder().apply(init).build()
|
return FirContextReceiverBuilder().apply(init).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
inline fun buildContextReceiverCopy(original: FirContextReceiver, init: FirContextReceiverBuilder.() -> Unit): FirContextReceiver {
|
||||||
|
contract {
|
||||||
|
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
val copyBuilder = FirContextReceiverBuilder()
|
||||||
|
copyBuilder.source = original.source
|
||||||
|
copyBuilder.typeRef = original.typeRef
|
||||||
|
copyBuilder.customLabelName = original.customLabelName
|
||||||
|
copyBuilder.labelNameFromTypeRef = original.labelNameFromTypeRef
|
||||||
|
return copyBuilder.apply(init).build()
|
||||||
|
}
|
||||||
|
|||||||
+4
@@ -280,6 +280,10 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
|
|||||||
parents += loopJumpBuilder
|
parents += loopJumpBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder(contextReceiver) {
|
||||||
|
withCopy()
|
||||||
|
}
|
||||||
|
|
||||||
builder(valueParameter, type = "FirValueParameterImpl") {
|
builder(valueParameter, type = "FirValueParameterImpl") {
|
||||||
openBuilder()
|
openBuilder()
|
||||||
withCopy()
|
withCopy()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +ContextReceivers
|
// !LANGUAGE: +ContextReceivers
|
||||||
// TARGET_BACKEND: JVM_IR
|
// TARGET_BACKEND: JVM_IR
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// FIR status: context receivers aren't yet supported
|
// FIR status: context receivers aren't yet supported
|
||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
|
|
||||||
@@ -12,4 +11,4 @@ fun box(): String {
|
|||||||
with (listOf(1, 2, 3)) {
|
with (listOf(1, 2, 3)) {
|
||||||
return A().result
|
return A().result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +ContextReceivers
|
// !LANGUAGE: +ContextReceivers
|
||||||
// TARGET_BACKEND: JVM_IR
|
// TARGET_BACKEND: JVM_IR
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// FIR status: context receivers aren't yet supported
|
// FIR status: context receivers aren't yet supported
|
||||||
|
|
||||||
context(T) class B<T : CharSequence> {
|
context(T) class B<T : CharSequence> {
|
||||||
@@ -9,4 +8,4 @@ context(T) class B<T : CharSequence> {
|
|||||||
|
|
||||||
fun box() = with("OK") {
|
fun box() = with("OK") {
|
||||||
B().result
|
B().result
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// !LANGUAGE: +ContextReceivers
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
|
||||||
|
class Box<E>(val x: E)
|
||||||
|
|
||||||
|
class A<X, Y> {
|
||||||
|
context(Box<X>, Y)
|
||||||
|
fun foo(): String = x.toString() + this@Y.toString()
|
||||||
|
|
||||||
|
context(Box<X>, Y)
|
||||||
|
val p1: String get() = x.toString() + this@Y.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
context(Box<X>, Y)
|
||||||
|
fun <X, Y> bar(): String = x.toString() + this@Y.toString()
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return with(Box("OK")) {
|
||||||
|
with(56) {
|
||||||
|
val a = A<String, Int>()
|
||||||
|
if (a.foo() != "OK56") return "fail 1"
|
||||||
|
if (a.p1 != "OK56") return "fail 2"
|
||||||
|
|
||||||
|
val b = bar<String, Int>()
|
||||||
|
if (b != "OK56") return "fail 3"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
// !LANGUAGE: +ContextReceivers
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
|
||||||
|
class Components(val x: String)
|
||||||
|
|
||||||
|
context(Components)
|
||||||
|
abstract class A<F : CharSequence>(val y: F) {
|
||||||
|
fun foo(): String = x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
context(Components)
|
||||||
|
class B(y: String) : A<String>(y)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return with(Components("O")) {
|
||||||
|
B("K").foo()
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
@@ -16752,12 +16752,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutedContextReceivers.kt")
|
||||||
|
public void testSubstitutedContextReceivers() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/substitutedContextReceivers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("superClassAndSubClassWithContextReceiver.kt")
|
@TestMetadata("superClassAndSubClassWithContextReceiver.kt")
|
||||||
public void testSuperClassAndSubClassWithContextReceiver() throws Exception {
|
public void testSuperClassAndSubClassWithContextReceiver() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/superClassAndSubClassWithContextReceiver.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/superClassAndSubClassWithContextReceiver.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("superClassAndSubClassWithContextReceiverSubstituted.kt")
|
||||||
|
public void testSuperClassAndSubClassWithContextReceiverSubstituted() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/superClassAndSubClassWithContextReceiverSubstituted.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("suspendContextualWithExtension.kt")
|
@TestMetadata("suspendContextualWithExtension.kt")
|
||||||
public void testSuspendContextualWithExtension() throws Exception {
|
public void testSuspendContextualWithExtension() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user