[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:
Mads Ager
2020-09-15 13:42:42 +02:00
committed by Alexander Udalov
parent 8d791ca98e
commit 1f2ca606a5
26 changed files with 55 additions and 34 deletions
@@ -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)
@@ -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 {
@@ -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
@@ -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
@@ -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
@@ -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
)
}
@@ -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
@@ -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)
@@ -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)
}
@@ -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(
@@ -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
@@ -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(
@@ -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 =
@@ -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 =
@@ -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))
@@ -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
}