[IR] Add isAssignable property to IrValueParameter.
Use it to check that only the value parameters that are explicitly marked assignable are assigned. Currently, the only parameters marked assignable are those for default argument stubs.
This commit is contained in:
committed by
Alexander Udalov
parent
8d791ca98e
commit
1f2ca606a5
@@ -356,7 +356,7 @@ internal fun IrDeclarationParent.declareThisReceiverParameter(
|
||||
symbolTable.irFactory.createValueParameter(
|
||||
startOffset, endOffset, thisOrigin, symbol,
|
||||
Name.special("<this>"), -1, thisType,
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
).apply {
|
||||
this.parent = this@declareThisReceiverParameter
|
||||
receiverDescriptor.bind(this)
|
||||
|
||||
+2
-2
@@ -256,7 +256,7 @@ class Fir2IrDeclarationStorage(
|
||||
startOffset, endOffset, IrDeclarationOrigin.DEFINED, symbol,
|
||||
Name.special("<set-?>"), 0, type,
|
||||
varargElementType = null,
|
||||
isCrossinline = false, isNoinline = false
|
||||
isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
).apply {
|
||||
this.parent = parent
|
||||
descriptor.bind(this)
|
||||
@@ -843,7 +843,7 @@ class Fir2IrDeclarationStorage(
|
||||
valueParameter.name, index, type,
|
||||
if (!valueParameter.isVararg) null
|
||||
else valueParameter.returnTypeRef.coneType.arrayElementType()?.toIrType(typeContext),
|
||||
valueParameter.isCrossinline, valueParameter.isNoinline
|
||||
valueParameter.isCrossinline, valueParameter.isNoinline, false
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
if (valueParameter.defaultValue.let {
|
||||
|
||||
+2
-1
@@ -274,7 +274,8 @@ internal class AdapterGenerator(
|
||||
type,
|
||||
varargElementType = null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
isNoinline = false,
|
||||
isAssignable = false
|
||||
).also { irAdapterValueParameter ->
|
||||
descriptor.bind(irAdapterValueParameter)
|
||||
irAdapterValueParameter.parent = adapterFunction
|
||||
|
||||
+1
-1
@@ -281,7 +281,7 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
|
||||
) { symbol ->
|
||||
components.irFactory.createValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, symbol, name, index, type, null,
|
||||
isCrossinline = false, isNoinline = false
|
||||
isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
)
|
||||
}.apply {
|
||||
parent = irFunction
|
||||
|
||||
+4
-1
@@ -137,7 +137,10 @@ class CheckIrElementVisitor(
|
||||
|
||||
override fun visitSetValue(expression: IrSetValue) {
|
||||
super.visitSetValue(expression)
|
||||
|
||||
val declaration = expression.symbol.owner
|
||||
if (declaration is IrValueParameter && !declaration.isAssignable) {
|
||||
reportError(expression, "Assignment to value parameters not marked assignable")
|
||||
}
|
||||
expression.ensureTypeIs(irBuiltIns.unitType)
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,8 @@ fun IrValueParameter.copyTo(
|
||||
varargElementType: IrType? = this.varargElementType, // TODO: remapTypeParameters here as well
|
||||
defaultValue: IrExpressionBody? = this.defaultValue,
|
||||
isCrossinline: Boolean = this.isCrossinline,
|
||||
isNoinline: Boolean = this.isNoinline
|
||||
isNoinline: Boolean = this.isNoinline,
|
||||
isAssignable: Boolean = this.isAssignable
|
||||
): IrValueParameter {
|
||||
val descriptor = if (index < 0) {
|
||||
WrappedReceiverParameterDescriptor()
|
||||
@@ -143,7 +144,7 @@ fun IrValueParameter.copyTo(
|
||||
}
|
||||
return factory.createValueParameter(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
name, index, type, varargElementType, isCrossinline, isNoinline
|
||||
name, index, type, varargElementType, isCrossinline, isNoinline, isAssignable = isAssignable
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = irFunction
|
||||
@@ -171,7 +172,7 @@ fun IrFunction.copyReceiverParametersFrom(from: IrFunction) {
|
||||
startOffset, endOffset, origin,
|
||||
IrValueParameterSymbolImpl(newDescriptor),
|
||||
name,
|
||||
index, type, varargElementType, isCrossinline, isNoinline
|
||||
index, type, varargElementType, isCrossinline, isNoinline, false
|
||||
).also { parameter ->
|
||||
parameter.parent = this@copyReceiverParametersFrom
|
||||
newDescriptor.bind(this)
|
||||
@@ -422,6 +423,7 @@ fun IrFunction.createDispatchReceiverParameter(origin: IrDeclarationOrigin? = nu
|
||||
parentAsClass.defaultType,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
).apply {
|
||||
parent = this@createDispatchReceiverParameter
|
||||
|
||||
+2
-1
@@ -586,7 +586,8 @@ private fun IrFunction.generateDefaultsFunctionImpl(
|
||||
type = if (makeNullable) newType.makeNullable() else newType,
|
||||
defaultValue = if (it.defaultValue != null) {
|
||||
factory.createExpressionBody(IrErrorExpressionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, "Default Stub"))
|
||||
} else null
|
||||
} else null,
|
||||
isAssignable = it.defaultValue != null
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
@PublishedApi
|
||||
@@ -213,7 +212,7 @@ fun <D> buildReceiverParameter(
|
||||
parent.factory.createValueParameter(
|
||||
startOffset, endOffset, origin,
|
||||
IrValueParameterSymbolImpl(wrappedDescriptor),
|
||||
RECEIVER_PARAMETER_NAME, -1, type, null, isCrossinline = false, isNoinline = false
|
||||
RECEIVER_PARAMETER_NAME, -1, type, null, isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
).also {
|
||||
wrappedDescriptor.bind(it)
|
||||
it.parent = parent
|
||||
@@ -227,7 +226,7 @@ internal fun IrFactory.buildValueParameter(builder: IrValueParameterBuilder, par
|
||||
return createValueParameter(
|
||||
startOffset, endOffset, origin,
|
||||
IrValueParameterSymbolImpl(wrappedDescriptor),
|
||||
name, index, type, varargElementType, isCrossInline, isNoinline, isHidden
|
||||
name, index, type, varargElementType, isCrossInline, isNoinline, isHidden, false
|
||||
).also {
|
||||
wrappedDescriptor.bind(it)
|
||||
it.parent = parent
|
||||
|
||||
+1
-1
@@ -415,7 +415,7 @@ private fun StatementGenerator.createFunctionForSuspendConversion(
|
||||
Name.identifier("p$index"),
|
||||
index,
|
||||
irParameterType,
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
)
|
||||
}.also {
|
||||
adaptedParameterDescriptor.bind(it)
|
||||
|
||||
+1
-1
@@ -392,7 +392,7 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
|
||||
name,
|
||||
index,
|
||||
type.toIrType(),
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
).also { irAdapterValueParameter ->
|
||||
descriptor.bind(irAdapterValueParameter)
|
||||
}
|
||||
|
||||
+3
-2
@@ -235,10 +235,11 @@ object IrFactoryImpl : IrFactory {
|
||||
varargElementType: IrType?,
|
||||
isCrossinline: Boolean,
|
||||
isNoinline: Boolean,
|
||||
isHidden: Boolean
|
||||
isHidden: Boolean,
|
||||
isAssignable: Boolean,
|
||||
): IrValueParameter =
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, origin, symbol, name, index, type, varargElementType, isCrossinline, isNoinline, isHidden
|
||||
startOffset, endOffset, origin, symbol, name, index, type, varargElementType, isCrossinline, isNoinline, isHidden, isAssignable
|
||||
)
|
||||
|
||||
override fun createExpressionBody(
|
||||
|
||||
+2
-1
@@ -39,7 +39,8 @@ class IrValueParameterImpl(
|
||||
override var varargElementType: IrType?,
|
||||
override val isCrossinline: Boolean,
|
||||
override val isNoinline: Boolean,
|
||||
override val isHidden: Boolean = false
|
||||
override val isHidden: Boolean = false,
|
||||
override val isAssignable: Boolean = false
|
||||
) : IrValueParameter() {
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
override val descriptor: ParameterDescriptor
|
||||
|
||||
+3
-2
@@ -237,10 +237,11 @@ object PersistentIrFactory : IrFactory {
|
||||
varargElementType: IrType?,
|
||||
isCrossinline: Boolean,
|
||||
isNoinline: Boolean,
|
||||
isHidden: Boolean
|
||||
isHidden: Boolean,
|
||||
isAssignable: Boolean
|
||||
): IrValueParameter =
|
||||
PersistentIrValueParameter(
|
||||
startOffset, endOffset, origin, symbol, name, index, type, varargElementType, isCrossinline, isNoinline, isHidden
|
||||
startOffset, endOffset, origin, symbol, name, index, type, varargElementType, isCrossinline, isNoinline, isHidden, isAssignable
|
||||
)
|
||||
|
||||
override fun createExpressionBody(
|
||||
|
||||
+2
-1
@@ -41,7 +41,8 @@ internal class PersistentIrValueParameter(
|
||||
varargElementType: IrType?,
|
||||
override val isCrossinline: Boolean,
|
||||
override val isNoinline: Boolean,
|
||||
override val isHidden: Boolean = false
|
||||
override val isHidden: Boolean = false,
|
||||
override val isAssignable: Boolean
|
||||
) : IrValueParameter(),
|
||||
PersistentIrDeclarationBase<ValueParameterCarrier>,
|
||||
ValueParameterCarrier {
|
||||
|
||||
@@ -199,7 +199,8 @@ interface IrFactory {
|
||||
varargElementType: IrType?,
|
||||
isCrossinline: Boolean,
|
||||
isNoinline: Boolean,
|
||||
isHidden: Boolean = false
|
||||
isHidden: Boolean = false,
|
||||
isAssignable: Boolean = false
|
||||
): IrValueParameter
|
||||
|
||||
// Bodies
|
||||
|
||||
@@ -39,6 +39,11 @@ abstract class IrValueParameter : IrValueDeclaration(), IrSymbolDeclaration<IrVa
|
||||
// Once we are able to load any top-level declaration from klib this hack should be deprecated and removed.
|
||||
abstract val isHidden: Boolean
|
||||
|
||||
// Parameters are not assignable by default. However, in the IR, assignments to parameters are used
|
||||
// to implement default argument stubs. If the default value is to be used, the value is assigned
|
||||
// to the parameter.
|
||||
abstract val isAssignable: Boolean
|
||||
|
||||
abstract var defaultValue: IrExpressionBody?
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ interface IrLazyDeclarationBase : IrDeclaration {
|
||||
fun ReceiverParameterDescriptor.generateReceiverParameterStub(): IrValueParameter =
|
||||
factory.createValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, IrValueParameterSymbolImpl(this),
|
||||
name, -1, type.toIrType(), null, isCrossinline = false, isNoinline = false
|
||||
name, -1, type.toIrType(), null, isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
)
|
||||
|
||||
fun generateMemberStubs(memberScope: MemberScope, container: MutableList<IrDeclaration>) {
|
||||
|
||||
@@ -80,7 +80,7 @@ class IrBuiltIns(
|
||||
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
|
||||
irFactory.createValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg$i"), i,
|
||||
valueParameterType, null, isCrossinline = false, isNoinline = false
|
||||
valueParameterType, null, isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
).apply {
|
||||
parent = operator
|
||||
}
|
||||
@@ -165,7 +165,7 @@ class IrBuiltIns(
|
||||
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
|
||||
val valueParameter = irFactory.createValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg0"), 0,
|
||||
valueIrType, null, isCrossinline = false, isNoinline = false
|
||||
valueIrType, null, isCrossinline = false, isNoinline = false, isAssignable = false
|
||||
)
|
||||
|
||||
valueParameter.parent = operator
|
||||
|
||||
@@ -268,7 +268,8 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
|
||||
val vDeclaration = irFactory.createValueParameter(
|
||||
offset, offset, classOrigin, vSymbol, Name.special("<this>"), -1, type, null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
isNoinline = false,
|
||||
isAssignable = false
|
||||
)
|
||||
|
||||
if (vDescriptor is WrappedReceiverParameterDescriptor) vDescriptor.bind(vDeclaration)
|
||||
@@ -332,7 +333,8 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
|
||||
val vDeclaration = irFactory.createValueParameter(
|
||||
offset, offset, memberOrigin, vSymbol, Name.identifier("p$i"), i - 1, vType, null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
isNoinline = false,
|
||||
isAssignable = false
|
||||
)
|
||||
vDeclaration.parent = fDeclaration
|
||||
if (vDescriptor is WrappedValueParameterDescriptor) vDescriptor.bind(vDeclaration)
|
||||
|
||||
@@ -95,7 +95,8 @@ class FakeOverrideCopier(
|
||||
declaration.type.remapType(),
|
||||
declaration.varargElementType?.remapType(),
|
||||
declaration.isCrossinline,
|
||||
declaration.isNoinline
|
||||
declaration.isNoinline,
|
||||
false
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
// Don't set the default value for fake overrides.
|
||||
|
||||
@@ -242,7 +242,7 @@ class DeclarationStubGenerator(
|
||||
internal fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter = with(descriptor) {
|
||||
symbolTable.irFactory.createValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, computeOrigin(this), IrValueParameterSymbolImpl(this), name, index, type.toIrType(),
|
||||
varargElementType?.toIrType(), isCrossinline, isNoinline
|
||||
varargElementType?.toIrType(), isCrossinline, isNoinline, false
|
||||
).also { irValueParameter ->
|
||||
if (descriptor.declaresDefaultValue()) {
|
||||
irValueParameter.defaultValue =
|
||||
|
||||
@@ -348,7 +348,8 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
declaration.type.remapType(),
|
||||
declaration.varargElementType?.remapType(),
|
||||
declaration.isCrossinline,
|
||||
declaration.isNoinline
|
||||
declaration.isNoinline,
|
||||
false
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
defaultValue = declaration.defaultValue?.transform()
|
||||
|
||||
@@ -524,7 +524,7 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl
|
||||
renderFlagsList(
|
||||
"vararg".takeIf { varargElementType != null },
|
||||
"crossinline".takeIf { isCrossinline },
|
||||
"noinline".takeIf { isNoinline }
|
||||
"noinline".takeIf { isNoinline },
|
||||
)
|
||||
|
||||
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty, data: Nothing?): String =
|
||||
|
||||
@@ -896,7 +896,7 @@ class SymbolTable(
|
||||
valueParameterFactory: (IrValueParameterSymbol) -> IrValueParameter = {
|
||||
irFactory.createValueParameter(
|
||||
startOffset, endOffset, origin, it, nameProvider.nameForDeclaration(descriptor),
|
||||
descriptor.indexOrMinusOne, type, varargElementType, descriptor.isCrossinline, descriptor.isNoinline
|
||||
descriptor.indexOrMinusOne, type, varargElementType, descriptor.isCrossinline, descriptor.isNoinline, false
|
||||
)
|
||||
}
|
||||
): IrValueParameter =
|
||||
|
||||
+2
-1
@@ -1009,7 +1009,8 @@ abstract class IrFileDeserializer(
|
||||
if (proto.hasVarargElementType()) deserializeIrType(proto.varargElementType) else null,
|
||||
flags.isCrossInline,
|
||||
flags.isNoInline,
|
||||
flags.isHidden
|
||||
flags.isHidden,
|
||||
false
|
||||
).apply {
|
||||
if (proto.hasDefaultValue())
|
||||
defaultValue = irFactory.createExpressionBody(deserializeExpressionBody(proto.defaultValue))
|
||||
|
||||
+1
-1
@@ -379,7 +379,7 @@ interface IrBuilderExtension {
|
||||
fun irValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) {
|
||||
factory.createValueParameter(
|
||||
function.startOffset, function.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrValueParameterSymbolImpl(this),
|
||||
name, indexOrMinusOne, type.toIrType(), varargElementType?.toIrType(), isCrossinline, isNoinline
|
||||
name, indexOrMinusOne, type.toIrType(), varargElementType?.toIrType(), isCrossinline, isNoinline, false
|
||||
).also {
|
||||
it.parent = function
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user