[FIR] Create builtin primitive array types for properties

If the primary constructor has a vararg parameter, the corresponding
property has an array type. This commit creates the builtin array
types for such properties if the vararg element type is primitive,
e.g., CharArray instead of Array.
This commit is contained in:
Juan Chen
2020-05-25 09:08:00 -07:00
committed by Denis Zharkov
parent ed6aceca87
commit adba0a03a6
11 changed files with 34 additions and 44 deletions
@@ -24,24 +24,17 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement
import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.builder.*
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.builder.buildUserTypeRef
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
fun String.parseCharacter(): Char? {
// Strip the quotes
@@ -453,18 +446,6 @@ fun FirPropertyBuilder.generateAccessorsByDelegate(
}
}
fun FirTypeRef.convertToArrayType(): FirUserTypeRef = buildUserTypeRef {
source = this@convertToArrayType.source
isMarkedNullable = false
qualifier += FirQualifierPartImpl(StandardClassIds.Array.shortClassName).apply {
typeArguments += buildTypeProjectionWithVariance {
source = this@convertToArrayType.source
typeRef = this@convertToArrayType
variance = Variance.OUT_VARIANCE
}
}
}
private val GET_VALUE = Name.identifier("getValue")
private val SET_VALUE = Name.identifier("setValue")
private val PROVIDE_DELEGATE = Name.identifier("provideDelegate")
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.lightTree.fir
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.convertToArrayType
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
@@ -14,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.declarations.isFromVararg
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.expressions.builder.buildQualifiedAccessExpression
@@ -38,9 +38,6 @@ class ValueParameter(
fun toFirProperty(session: FirSession, callableId: CallableId): FirProperty {
val name = this.firValueParameter.name
var type = this.firValueParameter.returnTypeRef
if (this.firValueParameter.isVararg) {
type = type.convertToArrayType()
}
if (type is FirImplicitTypeRef) {
type = buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax) }
}
@@ -70,6 +67,8 @@ class ValueParameter(
annotations += this@ValueParameter.firValueParameter.annotations
getter = FirDefaultPropertyGetter(null, session, FirDeclarationOrigin.Source, type, modifiers.getVisibility())
setter = if (this.isVar) FirDefaultPropertySetter(null, session, FirDeclarationOrigin.Source, type, modifiers.getVisibility()) else null
}.apply {
this.isFromVararg = firValueParameter.isVararg
}
}
}
@@ -349,9 +349,6 @@ class RawFirBuilder(
private fun KtParameter.toFirProperty(firParameter: FirValueParameter): FirProperty {
require(hasValOrVar())
var type = typeReference.toFirOrErrorType()
if (firParameter.isVararg) {
type = type.convertToArrayType()
}
val status = FirDeclarationStatusImpl(visibility, modality).apply {
isExpect = hasExpectModifier()
isActual = hasActualModifier()
@@ -390,6 +387,8 @@ class RawFirBuilder(
visibility
) else null
extractAnnotationsTo(this)
}.apply {
isFromVararg = firParameter.isVararg
}
}
@@ -91,7 +91,13 @@ class FirTypeResolveTransformer(
override fun transformProperty(property: FirProperty, data: Nothing?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup {
property.addTypeParametersScope()
transformDeclaration(property, data)
val result = transformDeclaration(property, data).single as FirProperty
if (property.isFromVararg == true) {
result.transformTypeToArrayType()
property.getter?.transformReturnTypeRef(StoreType, property.returnTypeRef)
property.setter?.valueParameters?.map { it.transformReturnTypeRef(StoreType, property.returnTypeRef) }
}
result.compose()
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirTypedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.*
@@ -90,14 +91,18 @@ internal object StoreReceiver : FirTransformer<FirExpression>() {
internal fun FirValueParameter.transformVarargTypeToArrayType() {
if (isVararg) {
val returnType = returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
transformReturnTypeRef(
StoreType,
returnTypeRef.withReplacedConeType(ConeKotlinTypeProjectionOut(returnType).createArrayOf())
)
this.transformTypeToArrayType()
}
}
internal fun FirTypedDeclaration.transformTypeToArrayType() {
val returnType = returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
transformReturnTypeRef(
StoreType,
returnTypeRef.withReplacedConeType(ConeKotlinTypeProjectionOut(returnType).createArrayOf())
)
}
inline fun <T> withScopeCleanup(scopes: MutableList<*>, crossinline l: () -> T): T {
val sizeBefore = scopes.size
return try {
@@ -107,4 +107,7 @@ fun FirRegularClass.addDeclaration(declaration: FirDeclaration) {
is FirSealedClassImpl -> declarations += declaration
else -> throw IllegalStateException()
}
}
}
private object IsFromVarargKey: FirDeclarationDataKey()
var FirProperty.isFromVararg: Boolean? by FirDeclarationDataRegistry.data(IsFromVarargKey)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// When inner class extends its outer, there are two instances of the outer present in the inner:
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Foo(val value: String) {
open inner class Inner(val d: Double = -1.0, val s: String, vararg val y: Int) {
@@ -90,15 +90,15 @@ FILE fqName:<root> fileName:/annotationClasses.kt
CONSTRUCTOR visibility:public <> (xs:kotlin.IntArray) returnType:<root>.Test4 [primary]
VALUE_PARAMETER name:xs index:0 type:kotlin.IntArray varargElementType:kotlin.Int [vararg]
PROPERTY name:xs visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.Array<out kotlin.Int> visibility:private [final]
FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.IntArray visibility:private [final]
EXPRESSION_BODY
GET_VAR 'xs: kotlin.IntArray [vararg] declared in <root>.Test4.<init>' type=kotlin.IntArray origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-xs> visibility:public modality:FINAL <> ($this:<root>.Test4) returnType:kotlin.Array<out kotlin.Int>
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-xs> visibility:public modality:FINAL <> ($this:<root>.Test4) returnType:kotlin.IntArray
correspondingProperty: PROPERTY name:xs visibility:public modality:FINAL [val]
$this: VALUE_PARAMETER name:<this> type:<root>.Test4
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-xs> (): kotlin.Array<out kotlin.Int> declared in <root>.Test4'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.Array<out kotlin.Int> visibility:private [final]' type=kotlin.Array<out kotlin.Int> origin=null
RETURN type=kotlin.Nothing from='public final fun <get-xs> (): kotlin.IntArray declared in <root>.Test4'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.IntArray visibility:private [final]' type=kotlin.IntArray origin=null
receiver: GET_VAR '<this>: <root>.Test4 declared in <root>.Test4.<get-xs>' type=<root>.Test4 origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
@@ -4,15 +4,15 @@ FILE fqName:<root> fileName:/varargsInAnnotationArguments.kt
CONSTRUCTOR visibility:public <> (xs:kotlin.IntArray) returnType:<root>.A1 [primary]
VALUE_PARAMETER name:xs index:0 type:kotlin.IntArray varargElementType:kotlin.Int [vararg]
PROPERTY name:xs visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.Array<out kotlin.Int> visibility:private [final]
FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.IntArray visibility:private [final]
EXPRESSION_BODY
GET_VAR 'xs: kotlin.IntArray [vararg] declared in <root>.A1.<init>' type=kotlin.IntArray origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-xs> visibility:public modality:FINAL <> ($this:<root>.A1) returnType:kotlin.Array<out kotlin.Int>
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-xs> visibility:public modality:FINAL <> ($this:<root>.A1) returnType:kotlin.IntArray
correspondingProperty: PROPERTY name:xs visibility:public modality:FINAL [val]
$this: VALUE_PARAMETER name:<this> type:<root>.A1
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-xs> (): kotlin.Array<out kotlin.Int> declared in <root>.A1'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.Array<out kotlin.Int> visibility:private [final]' type=kotlin.Array<out kotlin.Int> origin=null
RETURN type=kotlin.Nothing from='public final fun <get-xs> (): kotlin.IntArray declared in <root>.A1'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.IntArray visibility:private [final]' type=kotlin.IntArray origin=null
receiver: GET_VAR '<this>: <root>.A1 declared in <root>.A1.<get-xs>' type=<root>.A1 origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden: