diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt index 77d6a64e6cb..a30373c1aa1 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.utils.addToStdlib.getOrPut import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runUnless @@ -135,40 +136,34 @@ class Fir2IrClassifierStorage( preCacheTypeParameters(klass, symbol) setTypeParameters(klass) if (klass is FirRegularClass) { - val fieldsForContextReceiversOfCurrentClass = createContextReceiverFields(klass) - if (fieldsForContextReceiversOfCurrentClass.isNotEmpty()) { - declarations.addAll(fieldsForContextReceiversOfCurrentClass) - fieldsForContextReceivers[this] = fieldsForContextReceiversOfCurrentClass + val fieldsForContextReceiversOfCurrentClass = getFieldsWithContextReceiversForClass(this, klass) + declarations.addAll(fieldsForContextReceiversOfCurrentClass) + } + } + + fun getFieldsWithContextReceiversForClass(irClass: IrClass, klass: FirClass): List { + if (klass !is FirRegularClass || klass.contextReceivers.isEmpty()) return emptyList() + + return fieldsForContextReceivers.getOrPut(irClass) { + klass.contextReceivers.withIndex().map { (index, contextReceiver) -> + components.irFactory.createField( + startOffset = UNDEFINED_OFFSET, + endOffset = UNDEFINED_OFFSET, + origin = IrDeclarationOrigin.FIELD_FOR_CLASS_CONTEXT_RECEIVER, + name = Name.identifier("contextReceiverField$index"), + visibility = DescriptorVisibilities.PRIVATE, + symbol = IrFieldSymbolImpl(), + type = contextReceiver.typeRef.toIrType(), + isFinal = true, + isStatic = false, + isExternal = false, + ).also { + it.parent = irClass + } } } } - fun IrClass.createContextReceiverFields(klass: FirRegularClass): List { - if (klass.contextReceivers.isEmpty()) return emptyList() - - val contextReceiverFields = mutableListOf() - for ((index, contextReceiver) in klass.contextReceivers.withIndex()) { - val irField = components.irFactory.createField( - startOffset = UNDEFINED_OFFSET, - endOffset = UNDEFINED_OFFSET, - origin = IrDeclarationOrigin.FIELD_FOR_CLASS_CONTEXT_RECEIVER, - name = Name.identifier("contextReceiverField$index"), - visibility = DescriptorVisibilities.PRIVATE, - symbol = IrFieldSymbolImpl(), - type = contextReceiver.typeRef.toIrType(), - isFinal = true, - isStatic = false, - isExternal = false, - ) - irField.parent = this@createContextReceiverFields - contextReceiverFields.add(irField) - } - - return contextReceiverFields - } - - fun getFieldsWithContextReceiversForClass(irClass: IrClass): List? = fieldsForContextReceivers[irClass] - private fun IrClass.declareSupertypes(klass: FirClass) { superTypes = klass.superTypeRefs.map { superTypeRef -> superTypeRef.toIrType() } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index b24965ef0c9..31ae7a462d2 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -691,8 +691,11 @@ class Fir2IrVisitor( IrGetValueImpl(startOffset, endOffset, constructorParameter.type, constructorParameter.symbol) } else { val contextReceivers = - components.classifierStorage.getFieldsWithContextReceiversForClass(irClass) - ?: error("Not defined context receivers for $irClass") + components.classifierStorage.getFieldsWithContextReceiversForClass(irClass, firClass) + require(contextReceivers.size > calleeReference.contextReceiverNumber) { + "Not defined context receiver #${calleeReference.contextReceiverNumber} for $irClass. " + + "Context receivers found: $contextReceivers" + } IrGetFieldImpl( startOffset, endOffset, contextReceivers[calleeReference.contextReceiverNumber].symbol, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index dfe98ec12b7..6117f340314 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -130,13 +130,16 @@ internal class ClassMemberGenerator( if (containingClass is FirRegularClass && containingClass.contextReceivers.isNotEmpty()) { val contextReceiverFields = - components.classifierStorage.getFieldsWithContextReceiversForClass(irClass) - ?: error("Not found context receiver fields") + components.classifierStorage.getFieldsWithContextReceiversForClass(irClass, containingClass) val thisParameter = conversionScope.dispatchReceiverParameter(irClass) ?: error("No found this parameter for $irClass") for (index in containingClass.contextReceivers.indices) { + require(contextReceiverFields.size > index) { + "Not defined context receiver #${index} for $irClass. " + + "Context receivers found: $contextReceiverFields" + } val irValueParameter = valueParameters[index] body.statements.add( IrSetFieldImpl( diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt index 8de3e7ccdbd..068e6947e8c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -209,7 +209,7 @@ class Fir2IrLazyClass( addDeclarationsFromScope(fir.staticScope(session, scopeSession)) with(classifierStorage) { - result.addAll(this@Fir2IrLazyClass.createContextReceiverFields(fir)) + result.addAll(getFieldsWithContextReceiversForClass(this@Fir2IrLazyClass, fir)) } for (name in scope.getCallableNames()) {