[FIR builder] create error types for vararg parameters correctly

Otherwise, such types are treated as resolved, but anyway
requires transformation on type phase.
Also, this commit drops the redundant duplicated transformation of
typeReference from primary constructor property generator

^KT-61422
This commit is contained in:
Dmitrii Gridin
2023-09-06 18:31:42 +02:00
committed by Space Team
parent c0c1966555
commit f1e5a9b223
14 changed files with 84 additions and 36 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -24,8 +24,10 @@ import org.jetbrains.kotlin.fir.correspondingProperty
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.varargElementType
import org.jetbrains.kotlin.fir.types.arrayElementType
import org.jetbrains.kotlin.fir.utils.exceptions.withFirSymbolEntry
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
internal class KtFirValueParameterSymbol(
override val firSymbol: FirValueParameterSymbol,
@@ -49,7 +51,12 @@ internal class KtFirValueParameterSymbol(
override val returnType by cached {
val returnType = firSymbol.resolvedReturnType
if (firSymbol.isVararg) {
builder.typeBuilder.buildKtType(returnType.varargElementType())
// There SHOULD always be an array element type (even if it is an error type, e.g., unresolved).
val arrayElementType = returnType.arrayElementType()
?: errorWithAttachment("No array element type for vararg value parameter") {
withFirSymbolEntry("symbol", firSymbol)
}
builder.typeBuilder.buildKtType(arrayElementType)
} else {
builder.typeBuilder.buildKtType(returnType)
}
@@ -2311,9 +2311,10 @@ class LightTreeRawFirDeclarationBuilder(
}
}
container += buildFunctionTypeParameter {
source = node.toFirSourceElement()
val parameterSource = node.toFirSourceElement()
source = parameterSource
this.name = name
this.returnTypeRef = typeRef ?: createNoTypeForParameterTypeRef()
this.returnTypeRef = typeRef ?: createNoTypeForParameterTypeRef(parameterSource)
}
}
}
@@ -2373,7 +2374,7 @@ class LightTreeRawFirDeclarationBuilder(
modifiers = modifiers,
returnTypeRef = firType
?: when {
valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef()
valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef(valueParameterSource)
else -> implicitType
},
source = valueParameterSource,
@@ -1,6 +1,6 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.lightTree.fir
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.builder.Context
import org.jetbrains.kotlin.fir.builder.appliesToPrimaryConstructorParameter
import org.jetbrains.kotlin.fir.builder.filterUseSiteTarget
import org.jetbrains.kotlin.fir.builder.initContainingClassAttr
import org.jetbrains.kotlin.fir.builder.wrapIntoArray
import org.jetbrains.kotlin.fir.copy
import org.jetbrains.kotlin.fir.copyWithNewSourceKind
import org.jetbrains.kotlin.fir.correspondingProperty
@@ -38,6 +39,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
@@ -77,13 +79,18 @@ class ValueParameter(
source = this@ValueParameter.source
moduleData = this@ValueParameter.moduleData
origin = FirDeclarationOrigin.Source
returnTypeRef = this@ValueParameter.returnTypeRef
isVararg = modifiers.hasVararg()
returnTypeRef = if (isVararg && this@ValueParameter.returnTypeRef is FirErrorTypeRef) {
this@ValueParameter.returnTypeRef.wrapIntoArray()
} else {
this@ValueParameter.returnTypeRef
}
this.name = this@ValueParameter.name
symbol = FirValueParameterSymbol(name)
defaultValue = this@ValueParameter.defaultValue
isCrossinline = modifiers.hasCrossinline()
isNoinline = modifiers.hasNoinline()
isVararg = modifiers.hasVararg()
containingFunctionSymbol = this@ValueParameter.containingFunctionSymbol
?: error("containingFunctionSymbol should present when converting ValueParameter to a FirValueParameter")
@@ -635,15 +635,24 @@ open class PsiRawFirBuilder(
): FirValueParameter {
val name = convertValueParameterName(nameAsSafeName, valueParameterDeclaration) { nameIdentifier?.node?.text }
return buildValueParameter {
source = toFirSourceElement()
val parameterSource = toFirSourceElement()
source = parameterSource
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
isVararg = isVarArg
returnTypeRef = when {
typeReference != null -> typeReference.toFirOrErrorType()
defaultTypeRef != null -> defaultTypeRef
valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef()
valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef(parameterSource)
else -> null.toFirOrImplicitType()
}.let {
if (isVararg && it is FirErrorTypeRef) {
it.wrapIntoArray()
} else {
it
}
}
this.name = name
symbol = FirValueParameterSymbol(name)
defaultValue = if (hasDefaultValue()) {
@@ -651,7 +660,6 @@ open class PsiRawFirBuilder(
} else null
isCrossinline = hasModifier(CROSSINLINE_KEYWORD)
isNoinline = hasModifier(NOINLINE_KEYWORD)
isVararg = isVarArg
containingFunctionSymbol = functionSymbol
addAnnotationsFrom(
this@toFirValueParameter,
@@ -673,14 +681,23 @@ open class PsiRawFirBuilder(
private fun KtParameter.toFirProperty(firParameter: FirValueParameter): FirProperty {
require(hasValOrVar())
val type = typeReference.convertSafe<FirTypeRef>() ?: createNoTypeForParameterTypeRef()
val status = FirDeclarationStatusImpl(visibility, modality).apply {
isExpect = hasExpectModifier() || this@PsiRawFirBuilder.context.containerIsExpect
isActual = hasActualModifier()
isOverride = hasModifier(OVERRIDE_KEYWORD)
isConst = hasModifier(CONST_KEYWORD)
}
val propertySource = toFirSourceElement(KtFakeSourceElementKind.PropertyFromParameter)
// We can't just reuse a type from firParameter to avoid annotation leak.
val type = (typeReference.convertSafe<FirTypeRef>() ?: createNoTypeForParameterTypeRef(propertySource)).let {
if (it is FirErrorTypeRef && firParameter.isVararg) {
it.wrapIntoArray()
} else {
it
}
}
val propertyName = nameAsSafeName
val parameterAnnotations = mutableListOf<FirAnnotationCall>()
for (annotationEntry in annotationEntries) {
@@ -2163,11 +2180,12 @@ open class PsiRawFirBuilder(
returnTypeRef = unwrappedElement.returnTypeReference.toFirOrErrorType()
for (valueParameter in unwrappedElement.parameters) {
parameters += buildFunctionTypeParameter {
this.source = valueParameter.toFirSourceElement()
val parameterSource = valueParameter.toFirSourceElement()
this.source = parameterSource
name = valueParameter.nameAsName
returnTypeRef = when {
valueParameter.typeReference != null -> valueParameter.typeReference.toFirOrErrorType()
else -> createNoTypeForParameterTypeRef()
else -> createNoTypeForParameterTypeRef(parameterSource)
}
}
}
@@ -2357,12 +2375,13 @@ open class PsiRawFirBuilder(
) { ktParameter.nameIdentifier?.node?.text }
buildProperty {
source = ktParameter.toFirSourceElement()
val parameterSource = ktParameter.toFirSourceElement()
source = parameterSource
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
returnTypeRef = when {
ktParameter.typeReference != null -> ktParameter.typeReference.toFirOrErrorType()
else -> createNoTypeForParameterTypeRef()
else -> createNoTypeForParameterTypeRef(parameterSource)
}
isVar = false
status = FirResolvedDeclarationStatusImpl(Visibilities.Local, Modality.FINAL, EffectiveVisibility.Local)
@@ -1,6 +1,6 @@
FILE: noParameterTypRefInPrimaryConstructorWithVararg.kt
public? final? class X : R|kotlin/Any| {
public? constructor(vararg x: <ERROR TYPE REF: No type for parameter>): R|X| {
public? constructor(vararg x: R|kotlin/Array<out ERROR CLASS: No type for parameter>|): R|X| {
LAZY_super<R|kotlin/Any|>
}
@@ -1,6 +1,6 @@
FILE: noParameterTypRefInPrimaryConstructorWithVararg.kt
public? final? class X : R|kotlin/Any| {
public? [ContainingClassKey=X] constructor(vararg x: <ERROR TYPE REF: No type for parameter>): R|X| {
public? [ContainingClassKey=X] constructor(vararg x: R|kotlin/Array<out ERROR CLASS: No type for parameter>|): R|X| {
super<R|kotlin/Any|>()
}
@@ -1,10 +1,10 @@
FILE: noParameterTypRefInPrimaryConsturctorValWithVararg.kt
public? final? class X : R|kotlin/Any| {
public? constructor(vararg x: <ERROR TYPE REF: No type for parameter>): R|X| {
public? constructor(vararg x: R|kotlin/Array<out ERROR CLASS: No type for parameter>|): R|X| {
LAZY_super<R|kotlin/Any|>
}
public? final? val x: <ERROR TYPE REF: No type for parameter> = R|<local>/x|
public? get(): <ERROR TYPE REF: No type for parameter>
public? final? val x: R|kotlin/Array<out ERROR CLASS: No type for parameter>| = R|<local>/x|
public? get(): R|kotlin/Array<out ERROR CLASS: No type for parameter>|
}
@@ -1,10 +1,10 @@
FILE: noParameterTypRefInPrimaryConsturctorValWithVararg.kt
public? final? class X : R|kotlin/Any| {
public? [ContainingClassKey=X] constructor([CorrespondingProperty=/X.x] vararg x: <ERROR TYPE REF: No type for parameter>): R|X| {
public? [ContainingClassKey=X] constructor([CorrespondingProperty=/X.x] vararg x: R|kotlin/Array<out ERROR CLASS: No type for parameter>|): R|X| {
super<R|kotlin/Any|>()
}
public? final? [IsFromPrimaryConstructor=true, IsFromVarargKey=true] val x: <ERROR TYPE REF: No type for parameter> = R|<local>/x|
public? [ContainingClassKey=X] get(): <ERROR TYPE REF: No type for parameter>
public? final? [IsFromPrimaryConstructor=true, IsFromVarargKey=true] val x: R|kotlin/Array<out ERROR CLASS: No type for parameter>| = R|<local>/x|
public? [ContainingClassKey=X] get(): R|kotlin/Array<out ERROR CLASS: No type for parameter>|
}
@@ -1,6 +1,6 @@
FILE: uncompletedTypRefInPrimaryConstructorWithVararg.kt
public? final? class X : R|kotlin/Any| {
public? constructor(vararg x: <ERROR TYPE REF: Incomplete code>): R|X| {
public? constructor(vararg x: R|kotlin/Array<out ERROR CLASS: Incomplete code>|): R|X| {
LAZY_super<R|kotlin/Any|>
}
@@ -1,6 +1,6 @@
FILE: uncompletedTypRefInPrimaryConstructorWithVararg.kt
public? final? class X : R|kotlin/Any| {
public? [ContainingClassKey=X] constructor(vararg x: <ERROR TYPE REF: Incomplete code>): R|X| {
public? [ContainingClassKey=X] constructor(vararg x: R|kotlin/Array<out ERROR CLASS: Incomplete code>|): R|X| {
super<R|kotlin/Any|>()
}
@@ -1,10 +1,10 @@
FILE: uncompletedTypRefInPrimaryConsturctorValWithVararg.kt
public? final? class X : R|kotlin/Any| {
public? constructor(vararg x: <ERROR TYPE REF: Incomplete code>): R|X| {
public? constructor(vararg x: R|kotlin/Array<out ERROR CLASS: Incomplete code>|): R|X| {
LAZY_super<R|kotlin/Any|>
}
public? final? val x: <ERROR TYPE REF: Incomplete code> = R|<local>/x|
public? get(): <ERROR TYPE REF: Incomplete code>
public? final? val x: R|kotlin/Array<out ERROR CLASS: Incomplete code>| = R|<local>/x|
public? get(): R|kotlin/Array<out ERROR CLASS: Incomplete code>|
}
@@ -1,10 +1,10 @@
FILE: uncompletedTypRefInPrimaryConsturctorValWithVararg.kt
public? final? class X : R|kotlin/Any| {
public? [ContainingClassKey=X] constructor([CorrespondingProperty=/X.x] vararg x: <ERROR TYPE REF: Incomplete code>): R|X| {
public? [ContainingClassKey=X] constructor([CorrespondingProperty=/X.x] vararg x: R|kotlin/Array<out ERROR CLASS: Incomplete code>|): R|X| {
super<R|kotlin/Any|>()
}
public? final? [IsFromPrimaryConstructor=true, IsFromVarargKey=true] val x: <ERROR TYPE REF: Incomplete code> = R|<local>/x|
public? [ContainingClassKey=X] get(): <ERROR TYPE REF: Incomplete code>
public? final? [IsFromPrimaryConstructor=true, IsFromVarargKey=true] val x: R|kotlin/Array<out ERROR CLASS: Incomplete code>| = R|<local>/x|
public? [ContainingClassKey=X] get(): R|kotlin/Array<out ERROR CLASS: Incomplete code>|
}
@@ -1078,8 +1078,9 @@ abstract class AbstractRawFirBuilder<T>(val baseSession: FirSession, val context
symbol = FirErrorPropertySymbol(diagnostic)
}
protected fun createNoTypeForParameterTypeRef(): FirErrorTypeRef {
protected fun createNoTypeForParameterTypeRef(parameterSource: KtSourceElement): FirErrorTypeRef {
return buildErrorTypeRef {
source = parameterSource
diagnostic = ConeSimpleDiagnostic("No type for parameter", DiagnosticKind.ValueParameterWithNoTypeAnnotation)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -40,10 +40,14 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinTypeProjectionOut
import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.constructClassLikeType
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
@@ -705,3 +709,12 @@ fun KtSourceElement.withForcedKindFrom(context: Context<*>): KtSourceElement {
else -> this.realElement()
}
}
fun FirErrorTypeRef.wrapIntoArray(): FirResolvedTypeRef {
val typeRef = this
return buildResolvedTypeRef {
source = typeRef.source
type = StandardClassIds.Array.constructClassLikeType(arrayOf(ConeKotlinTypeProjectionOut(typeRef.coneType)))
delegatedTypeRef = typeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ArrayTypeFromVarargParameter)
}
}