[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. * 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.declarations.FirFunction
import org.jetbrains.kotlin.fir.renderWithType import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol 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.name.Name
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
internal class KtFirValueParameterSymbol( internal class KtFirValueParameterSymbol(
override val firSymbol: FirValueParameterSymbol, override val firSymbol: FirValueParameterSymbol,
@@ -49,7 +51,12 @@ internal class KtFirValueParameterSymbol(
override val returnType by cached { override val returnType by cached {
val returnType = firSymbol.resolvedReturnType val returnType = firSymbol.resolvedReturnType
if (firSymbol.isVararg) { 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 { } else {
builder.typeBuilder.buildKtType(returnType) builder.typeBuilder.buildKtType(returnType)
} }
@@ -2311,9 +2311,10 @@ class LightTreeRawFirDeclarationBuilder(
} }
} }
container += buildFunctionTypeParameter { container += buildFunctionTypeParameter {
source = node.toFirSourceElement() val parameterSource = node.toFirSourceElement()
source = parameterSource
this.name = name this.name = name
this.returnTypeRef = typeRef ?: createNoTypeForParameterTypeRef() this.returnTypeRef = typeRef ?: createNoTypeForParameterTypeRef(parameterSource)
} }
} }
} }
@@ -2373,7 +2374,7 @@ class LightTreeRawFirDeclarationBuilder(
modifiers = modifiers, modifiers = modifiers,
returnTypeRef = firType returnTypeRef = firType
?: when { ?: when {
valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef() valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef(valueParameterSource)
else -> implicitType else -> implicitType
}, },
source = valueParameterSource, 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 * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* that can be found in the license/LICENSE.txt file. * 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 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.appliesToPrimaryConstructorParameter
import org.jetbrains.kotlin.fir.builder.filterUseSiteTarget import org.jetbrains.kotlin.fir.builder.filterUseSiteTarget
import org.jetbrains.kotlin.fir.builder.initContainingClassAttr 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.copy
import org.jetbrains.kotlin.fir.copyWithNewSourceKind import org.jetbrains.kotlin.fir.copyWithNewSourceKind
import org.jetbrains.kotlin.fir.correspondingProperty 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.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType 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.FirImplicitTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
@@ -77,13 +79,18 @@ class ValueParameter(
source = this@ValueParameter.source source = this@ValueParameter.source
moduleData = this@ValueParameter.moduleData moduleData = this@ValueParameter.moduleData
origin = FirDeclarationOrigin.Source 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 this.name = this@ValueParameter.name
symbol = FirValueParameterSymbol(name) symbol = FirValueParameterSymbol(name)
defaultValue = this@ValueParameter.defaultValue defaultValue = this@ValueParameter.defaultValue
isCrossinline = modifiers.hasCrossinline() isCrossinline = modifiers.hasCrossinline()
isNoinline = modifiers.hasNoinline() isNoinline = modifiers.hasNoinline()
isVararg = modifiers.hasVararg()
containingFunctionSymbol = this@ValueParameter.containingFunctionSymbol containingFunctionSymbol = this@ValueParameter.containingFunctionSymbol
?: error("containingFunctionSymbol should present when converting ValueParameter to a FirValueParameter") ?: error("containingFunctionSymbol should present when converting ValueParameter to a FirValueParameter")
@@ -635,15 +635,24 @@ open class PsiRawFirBuilder(
): FirValueParameter { ): FirValueParameter {
val name = convertValueParameterName(nameAsSafeName, valueParameterDeclaration) { nameIdentifier?.node?.text } val name = convertValueParameterName(nameAsSafeName, valueParameterDeclaration) { nameIdentifier?.node?.text }
return buildValueParameter { return buildValueParameter {
source = toFirSourceElement() val parameterSource = toFirSourceElement()
source = parameterSource
moduleData = baseModuleData moduleData = baseModuleData
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
isVararg = isVarArg
returnTypeRef = when { returnTypeRef = when {
typeReference != null -> typeReference.toFirOrErrorType() typeReference != null -> typeReference.toFirOrErrorType()
defaultTypeRef != null -> defaultTypeRef defaultTypeRef != null -> defaultTypeRef
valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef() valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef(parameterSource)
else -> null.toFirOrImplicitType() else -> null.toFirOrImplicitType()
}.let {
if (isVararg && it is FirErrorTypeRef) {
it.wrapIntoArray()
} else {
it
}
} }
this.name = name this.name = name
symbol = FirValueParameterSymbol(name) symbol = FirValueParameterSymbol(name)
defaultValue = if (hasDefaultValue()) { defaultValue = if (hasDefaultValue()) {
@@ -651,7 +660,6 @@ open class PsiRawFirBuilder(
} else null } else null
isCrossinline = hasModifier(CROSSINLINE_KEYWORD) isCrossinline = hasModifier(CROSSINLINE_KEYWORD)
isNoinline = hasModifier(NOINLINE_KEYWORD) isNoinline = hasModifier(NOINLINE_KEYWORD)
isVararg = isVarArg
containingFunctionSymbol = functionSymbol containingFunctionSymbol = functionSymbol
addAnnotationsFrom( addAnnotationsFrom(
this@toFirValueParameter, this@toFirValueParameter,
@@ -673,14 +681,23 @@ open class PsiRawFirBuilder(
private fun KtParameter.toFirProperty(firParameter: FirValueParameter): FirProperty { private fun KtParameter.toFirProperty(firParameter: FirValueParameter): FirProperty {
require(hasValOrVar()) require(hasValOrVar())
val type = typeReference.convertSafe<FirTypeRef>() ?: createNoTypeForParameterTypeRef()
val status = FirDeclarationStatusImpl(visibility, modality).apply { val status = FirDeclarationStatusImpl(visibility, modality).apply {
isExpect = hasExpectModifier() || this@PsiRawFirBuilder.context.containerIsExpect isExpect = hasExpectModifier() || this@PsiRawFirBuilder.context.containerIsExpect
isActual = hasActualModifier() isActual = hasActualModifier()
isOverride = hasModifier(OVERRIDE_KEYWORD) isOverride = hasModifier(OVERRIDE_KEYWORD)
isConst = hasModifier(CONST_KEYWORD) isConst = hasModifier(CONST_KEYWORD)
} }
val propertySource = toFirSourceElement(KtFakeSourceElementKind.PropertyFromParameter) 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 propertyName = nameAsSafeName
val parameterAnnotations = mutableListOf<FirAnnotationCall>() val parameterAnnotations = mutableListOf<FirAnnotationCall>()
for (annotationEntry in annotationEntries) { for (annotationEntry in annotationEntries) {
@@ -2163,11 +2180,12 @@ open class PsiRawFirBuilder(
returnTypeRef = unwrappedElement.returnTypeReference.toFirOrErrorType() returnTypeRef = unwrappedElement.returnTypeReference.toFirOrErrorType()
for (valueParameter in unwrappedElement.parameters) { for (valueParameter in unwrappedElement.parameters) {
parameters += buildFunctionTypeParameter { parameters += buildFunctionTypeParameter {
this.source = valueParameter.toFirSourceElement() val parameterSource = valueParameter.toFirSourceElement()
this.source = parameterSource
name = valueParameter.nameAsName name = valueParameter.nameAsName
returnTypeRef = when { returnTypeRef = when {
valueParameter.typeReference != null -> valueParameter.typeReference.toFirOrErrorType() valueParameter.typeReference != null -> valueParameter.typeReference.toFirOrErrorType()
else -> createNoTypeForParameterTypeRef() else -> createNoTypeForParameterTypeRef(parameterSource)
} }
} }
} }
@@ -2357,12 +2375,13 @@ open class PsiRawFirBuilder(
) { ktParameter.nameIdentifier?.node?.text } ) { ktParameter.nameIdentifier?.node?.text }
buildProperty { buildProperty {
source = ktParameter.toFirSourceElement() val parameterSource = ktParameter.toFirSourceElement()
source = parameterSource
moduleData = baseModuleData moduleData = baseModuleData
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
returnTypeRef = when { returnTypeRef = when {
ktParameter.typeReference != null -> ktParameter.typeReference.toFirOrErrorType() ktParameter.typeReference != null -> ktParameter.typeReference.toFirOrErrorType()
else -> createNoTypeForParameterTypeRef() else -> createNoTypeForParameterTypeRef(parameterSource)
} }
isVar = false isVar = false
status = FirResolvedDeclarationStatusImpl(Visibilities.Local, Modality.FINAL, EffectiveVisibility.Local) status = FirResolvedDeclarationStatusImpl(Visibilities.Local, Modality.FINAL, EffectiveVisibility.Local)
@@ -1,6 +1,6 @@
FILE: noParameterTypRefInPrimaryConstructorWithVararg.kt FILE: noParameterTypRefInPrimaryConstructorWithVararg.kt
public? final? class X : R|kotlin/Any| { 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|> LAZY_super<R|kotlin/Any|>
} }
@@ -1,6 +1,6 @@
FILE: noParameterTypRefInPrimaryConstructorWithVararg.kt FILE: noParameterTypRefInPrimaryConstructorWithVararg.kt
public? final? class X : R|kotlin/Any| { 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|>() super<R|kotlin/Any|>()
} }
@@ -1,10 +1,10 @@
FILE: noParameterTypRefInPrimaryConsturctorValWithVararg.kt FILE: noParameterTypRefInPrimaryConsturctorValWithVararg.kt
public? final? class X : R|kotlin/Any| { 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|> LAZY_super<R|kotlin/Any|>
} }
public? final? val x: <ERROR TYPE REF: No type for parameter> = R|<local>/x| public? final? val x: R|kotlin/Array<out ERROR CLASS: No type for parameter>| = R|<local>/x|
public? get(): <ERROR TYPE REF: No type for parameter> public? get(): R|kotlin/Array<out ERROR CLASS: No type for parameter>|
} }
@@ -1,10 +1,10 @@
FILE: noParameterTypRefInPrimaryConsturctorValWithVararg.kt FILE: noParameterTypRefInPrimaryConsturctorValWithVararg.kt
public? final? class X : R|kotlin/Any| { 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|>() super<R|kotlin/Any|>()
} }
public? final? [IsFromPrimaryConstructor=true, IsFromVarargKey=true] val x: <ERROR TYPE REF: No type for parameter> = R|<local>/x| 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(): <ERROR TYPE REF: No type for parameter> public? [ContainingClassKey=X] get(): R|kotlin/Array<out ERROR CLASS: No type for parameter>|
} }
@@ -1,6 +1,6 @@
FILE: uncompletedTypRefInPrimaryConstructorWithVararg.kt FILE: uncompletedTypRefInPrimaryConstructorWithVararg.kt
public? final? class X : R|kotlin/Any| { 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|> LAZY_super<R|kotlin/Any|>
} }
@@ -1,6 +1,6 @@
FILE: uncompletedTypRefInPrimaryConstructorWithVararg.kt FILE: uncompletedTypRefInPrimaryConstructorWithVararg.kt
public? final? class X : R|kotlin/Any| { 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|>() super<R|kotlin/Any|>()
} }
@@ -1,10 +1,10 @@
FILE: uncompletedTypRefInPrimaryConsturctorValWithVararg.kt FILE: uncompletedTypRefInPrimaryConsturctorValWithVararg.kt
public? final? class X : R|kotlin/Any| { 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|> LAZY_super<R|kotlin/Any|>
} }
public? final? val x: <ERROR TYPE REF: Incomplete code> = R|<local>/x| public? final? val x: R|kotlin/Array<out ERROR CLASS: Incomplete code>| = R|<local>/x|
public? get(): <ERROR TYPE REF: Incomplete code> public? get(): R|kotlin/Array<out ERROR CLASS: Incomplete code>|
} }
@@ -1,10 +1,10 @@
FILE: uncompletedTypRefInPrimaryConsturctorValWithVararg.kt FILE: uncompletedTypRefInPrimaryConsturctorValWithVararg.kt
public? final? class X : R|kotlin/Any| { 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|>() super<R|kotlin/Any|>()
} }
public? final? [IsFromPrimaryConstructor=true, IsFromVarargKey=true] val x: <ERROR TYPE REF: Incomplete code> = R|<local>/x| public? final? [IsFromPrimaryConstructor=true, IsFromVarargKey=true] val x: R|kotlin/Array<out ERROR CLASS: Incomplete code>| = R|<local>/x|
public? [ContainingClassKey=X] get(): <ERROR TYPE REF: Incomplete code> 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) symbol = FirErrorPropertySymbol(diagnostic)
} }
protected fun createNoTypeForParameterTypeRef(): FirErrorTypeRef { protected fun createNoTypeForParameterTypeRef(parameterSource: KtSourceElement): FirErrorTypeRef {
return buildErrorTypeRef { return buildErrorTypeRef {
source = parameterSource
diagnostic = ConeSimpleDiagnostic("No type for parameter", DiagnosticKind.ValueParameterWithNoTypeAnnotation) 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. * 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.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType 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.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.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance 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.constructClassLikeType
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
@@ -705,3 +709,12 @@ fun KtSourceElement.withForcedKindFrom(context: Context<*>): KtSourceElement {
else -> this.realElement() 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)
}
}