[FIR] Replace usages of FirExpression.typeRef with coneTypeOrNull

#KT-59855 Fixed
This commit is contained in:
Kirill Rakhman
2023-08-04 10:43:25 +02:00
committed by Space Team
parent f60d81097c
commit 8d7c5b375e
76 changed files with 538 additions and 565 deletions
@@ -72,7 +72,7 @@ internal class KtFirExpressionTypeProvider(
// For unresolved `super`, we manually create an intersection type so that IDE features like completion can work correctly.
val containingClass = (fir.dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol as? FirClassSymbol<*>
if (fir.calleeReference is FirSuperReference && fir.typeRef is FirErrorTypeRef && containingClass != null) {
if (fir.calleeReference is FirSuperReference && fir.coneTypeOrNull is ConeErrorType && containingClass != null) {
val superTypes = containingClass.resolvedSuperTypes
when (superTypes.size) {
0 -> analysisSession.builtinTypes.ANY
@@ -214,9 +214,7 @@ internal class KtFirExpressionTypeProvider(
private fun getExpectedTypeByTypeCast(expression: PsiElement): KtType? {
val typeCastExpression =
expression.unwrapQualified<KtBinaryExpressionWithTypeRHS> { castExpr, expr -> castExpr.left == expr } ?: return null
with(analysisSession) {
return typeCastExpression.right?.getKtType()
}
return getKtExpressionType(typeCastExpression)
}
private fun getExpectedTypeOfFunctionParameter(expression: PsiElement): KtType? {
@@ -178,13 +178,13 @@ internal object FirCompileTimeConstantEvaluator {
val opr1 = evaluate(functionCall.explicitReceiver, mode) ?: return null
opr1.evaluate(function)?.let {
return it.adjustType(functionCall.type)
return it.adjustType(functionCall.coneTypeOrNull)
}
val argument = functionCall.arguments.firstOrNull() ?: return null
val opr2 = evaluate(argument, mode) ?: return null
opr1.evaluate(function, opr2)?.let {
return it.adjustType(functionCall.type)
return it.adjustType(functionCall.coneTypeOrNull)
}
return null
}
@@ -207,7 +207,7 @@ internal object FirCompileTimeConstantEvaluator {
}
// Lastly, we should preserve the resolved type of the original function call.
return expression.apply {
replaceType(expectedType)
replaceConeTypeOrNull(expectedType)
}
}
@@ -422,7 +422,7 @@ internal object FirReferenceResolveHelper {
// accessing the `super` property on `this`, hence this weird looking if condition. In addition, the current class type is available
// from the dispatch receiver `this`.
if (expression is KtLabelReferenceExpression && fir is FirPropertyAccessExpression && fir.calleeReference is FirSuperReference) {
return listOfNotNull(fir.dispatchReceiver.type?.toTargetSymbol(session, symbolBuilder))
return listOfNotNull(fir.dispatchReceiver.coneTypeOrNull?.toTargetSymbol(session, symbolBuilder))
}
val receiverOrImplicitInvoke = if (fir is FirImplicitInvokeCall) {
fir.explicitReceiver?.unwrapSmartcastExpression()
@@ -733,7 +733,7 @@ internal object FirReferenceResolveHelper {
session: FirSession,
symbolBuilder: KtSymbolByFirBuilder
): Collection<KtSymbol> {
val type = fir.type ?: return emptyList()
val type = fir.coneTypeOrNull ?: return emptyList()
return listOfNotNull(type.toTargetSymbol(session, symbolBuilder))
}
@@ -218,7 +218,7 @@ internal open class FirElementsRecorder : FirVisitor<Unit, MutableMap<KtElement,
convertedValue as T,
setType = false
).also {
it.replaceTypeRef(original.typeRef)
it.replaceConeTypeOrNull(original.coneTypeOrNull)
}
}
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.psi.stubs.impl.KotlinClassTypeBean
import org.jetbrains.kotlin.psi.stubs.impl.KotlinPropertyStubImpl
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
import org.jetbrains.kotlin.utils.exceptions.withPsiEntry
class StubBasedAnnotationDeserializer(
private val session: FirSession,
@@ -109,23 +108,20 @@ class StubBasedAnnotationDeserializer(
source = KtRealPsiSourceElement(sourceElement)
val lookupTag = (value.value as KClassValue.Value.NormalClass).classId.toLookupTag()
val referencedType = lookupTag.constructType(ConeTypeProjection.EMPTY_ARRAY, isNullable = false)
val resolvedTypeRef = buildResolvedTypeRef {
type = StandardClassIds.KClass.constructClassLikeType(arrayOf(referencedType), false)
}
val resolvedType = StandardClassIds.KClass.constructClassLikeType(arrayOf(referencedType), false)
argumentList = buildUnaryArgumentList(
buildClassReferenceExpression {
classTypeRef = buildResolvedTypeRef { type = referencedType }
typeRef = resolvedTypeRef
coneTypeOrNull = resolvedType
}
)
coneTypeOrNull = resolvedType
}
is ArrayValue -> {
buildArrayLiteral {
source = KtRealPsiSourceElement(sourceElement)
typeRef = buildResolvedTypeRef {
// Not quite precise, yet doesn't require annotation resolution
type = (inferArrayValueType(value.value) ?: session.builtinTypes.anyType.type).createArrayType()
}
// Not quite precise, yet doesn't require annotation resolution
coneTypeOrNull = (inferArrayValueType(value.value) ?: session.builtinTypes.anyType.type).createArrayType()
argumentList = buildArgumentList {
value.value.mapTo(arguments) { resolveValue(sourceElement, it) }
@@ -208,7 +204,7 @@ class StubBasedAnnotationDeserializer(
kind,
value,
setType = true
).apply { this.replaceTypeRef(typeRef) }
).apply { this.replaceConeTypeOrNull(typeRef.type) }
}
private fun PsiElement.toEnumEntryReferenceExpression(classId: ClassId, entryName: Name): FirExpression {
@@ -228,7 +224,7 @@ class StubBasedAnnotationDeserializer(
name = entryName
}
if (enumEntrySymbol != null) {
typeRef = enumEntrySymbol.returnTypeRef
coneTypeOrNull = enumEntrySymbol.returnTypeRef.coneTypeOrNull
}
}
}
@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolve
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractsDslNames
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForClass
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -399,7 +398,7 @@ private val FirFunction.isCertainlyResolved: Boolean
}
val body = this.body ?: return false // Not completely sure
return body !is FirLazyBlock && body.typeRef is FirResolvedTypeRef
return body !is FirLazyBlock && body.coneTypeOrNull != null
}
private val FirVariable.initializerIfUnresolved: FirExpression?
@@ -472,4 +471,4 @@ private fun requireSameSize(old: List<FirStatement>, new: List<FirStatement>) {
private class LLFirCodeFragmentContext(
override val towerDataContext: FirTowerDataContext,
override val variables: Map<FirBasedSymbol<*>, Set<ConeKotlinType>>
) : FirCodeFragmentContext
) : FirCodeFragmentContext
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvable
import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -49,6 +50,26 @@ internal inline fun checkTypeRefIsResolved(
}
}
internal inline fun checkExpressionTypeIsResolved(
type: ConeKotlinType?,
typeName: String,
owner: FirElementWithResolveState,
extraAttachment: ExceptionAttachmentBuilder.() -> Unit = {},
) {
checkWithAttachment(
condition = type != null,
message = {
buildString {
append("Expected resolved expression type")
append(" for $typeName of ${owner::class.simpleName}(${(owner as? FirDeclaration)?.origin})")
}
}
) {
withFirEntry("firDeclaration", owner)
extraAttachment()
}
}
internal fun <T> checkAnnotationTypeIsResolved(annotationContainer: T) where T : FirAnnotationContainer, T : FirElementWithResolveState {
annotationContainer.annotations.forEach { annotation ->
checkTypeRefIsResolved(annotation.annotationTypeRef, "annotation type", owner = annotationContainer) {
@@ -59,7 +80,7 @@ internal fun <T> checkAnnotationTypeIsResolved(annotationContainer: T) where T :
internal fun checkBodyIsResolved(function: FirFunction) {
val block = function.body ?: return
checkTypeRefIsResolved(block.typeRef, "block type", function) {
checkExpressionTypeIsResolved(block.coneTypeOrNull, "block type", function) {
withFirEntry("block", block)
}
}
@@ -67,7 +88,7 @@ internal fun checkBodyIsResolved(function: FirFunction) {
internal fun checkStatementsAreResolved(script: FirScript) {
for (statement in script.statements) {
if (statement.isScriptStatement && statement is FirExpression) {
checkTypeRefIsResolved(statement.typeRef, "script statement", script) {
checkExpressionTypeIsResolved(statement.coneTypeOrNull, "script statement", script) {
withFirEntry("expression", statement)
}
}
@@ -114,14 +135,14 @@ internal fun checkReferenceIsResolved(
internal fun checkInitializerIsResolved(variable: FirVariable) {
val initializer = variable.initializer ?: return
checkTypeRefIsResolved(initializer.typeRef, "initializer type", variable) {
checkExpressionTypeIsResolved(initializer.coneTypeOrNull, "initializer type", variable) {
withFirEntry("initializer", initializer)
}
}
internal fun checkDefaultValueIsResolved(parameter: FirValueParameter) {
val defaultValue = parameter.defaultValue ?: return
checkTypeRefIsResolved(defaultValue.typeRef, "default value type", parameter) {
checkExpressionTypeIsResolved(defaultValue.coneTypeOrNull, "default value type", parameter) {
withFirEntry("defaultValue", defaultValue)
}
}
@@ -194,7 +215,7 @@ internal fun <T> checkAnnotationArgumentsMappingIsResolved(
}
for (argument in annotation.argumentMapping.mapping.values) {
checkTypeRefIsResolved(argument.typeRef, "annotation argument", annotationContainer) {
checkExpressionTypeIsResolved(argument.coneTypeOrNull, "annotation argument", annotationContainer) {
withFirEntry("firAnnotation", annotation)
withFirEntry("firArgument", argument)
}
@@ -9,7 +9,7 @@ FIR FILE:
FILE: [ResolvedTo(IMPORTS)] javaClassLiteral.kt
public final [ResolvedTo(BODY_RESOLVE)] fun main([ResolvedTo(BODY_RESOLVE)] args: R|kotlin/Array<kotlin/String>|): R|kotlin/Unit| {
[ResolvedTo(BODY_RESOLVE)] lval anyClass: R|kotlin/Any| = R|kotlin/Any.Any|()
R|/funOne|(<ERROR TYPE REF: Qualified expression with unexpected selector>ERROR_EXPR(Incorrect selector expression)R|<local>/anyClass|)
R|/funOne|(ERROR_EXPR(Incorrect selector expression)R|<local>/anyClass|)
}
public final [ResolvedTo(CONTRACTS)] fun funOne([ResolvedTo(CONTRACTS)] x: R|kotlin/Any|): R|kotlin/Unit| {
}
@@ -14,7 +14,7 @@ FILE: [ResolvedTo(IMPORTS)] qualifiedPartOfQualifiedCallUnresolved.kt
public final [ResolvedTo(BODY_RESOLVE)] fun handleLeftBracketInFragment(): R|kotlin/Unit| {
{
[ResolvedTo(BODY_RESOLVE)] lval <receiver>: <ERROR TYPE REF: Unresolved name: peek> = <Unresolved name: peek>#()
[ResolvedTo(BODY_RESOLVE)] lval <receiver>: R|ERROR CLASS: Unresolved name: peek| = <Unresolved name: peek>#()
[ResolvedTo(BODY_RESOLVE)] lval <unary>: <ERROR TYPE REF: Unresolved name: braceBalance> = R|<local>/<receiver>|.<Unresolved name: braceBalance>#
R|<local>/<receiver>|.<Unresolved name: braceBalance># = R|<local>/<unary>|.<Unresolved name: inc>#()
R|<local>/<unary>|
@@ -18,7 +18,7 @@ FILE: [ResolvedTo(IMPORTS)] qualifiedPartOfQualifiedCallUnresolvedScript.kts
public final [ResolvedTo(BODY_RESOLVE)] fun handleLeftBracketInFragment(): R|kotlin/Unit| {
{
[ResolvedTo(BODY_RESOLVE)] lval <receiver>: <ERROR TYPE REF: Unresolved name: peek> = <Unresolved name: peek>#()
[ResolvedTo(BODY_RESOLVE)] lval <receiver>: R|ERROR CLASS: Unresolved name: peek| = <Unresolved name: peek>#()
[ResolvedTo(BODY_RESOLVE)] lval <unary>: <ERROR TYPE REF: Unresolved name: braceBalance> = R|<local>/<receiver>|.<Unresolved name: braceBalance>#
R|<local>/<receiver>|.<Unresolved name: braceBalance># = R|<local>/<unary>|.<Unresolved name: inc>#()
R|<local>/<unary>|
@@ -6,7 +6,7 @@ FILE: a.kt
public abstract interface I : R|kotlin/Any| {
public open fun <T> f(): <ERROR TYPE REF: Qualified expression with unexpected selector> {
^f <ERROR TYPE REF: Qualified expression with unexpected selector>ERROR_EXPR(The expression cannot be a selector (occur after a dot))String()
^f ERROR_EXPR(The expression cannot be a selector (occur after a dot))String()
}
public final class C : R|b/I| {
@@ -17,6 +17,6 @@ import org.jetbrains.kotlin.fir.types.toSymbol
object FirJsModuleGetClassCallChecker : FirGetClassCallChecker() {
override fun check(expression: FirGetClassCall, context: CheckerContext, reporter: DiagnosticReporter) {
val callee = expression.argument.coneTypeOrNull?.toSymbol(context.session) ?: return
checkJsModuleUsage(callee, context, reporter, expression.argument.typeRef.source ?: expression.source)
checkJsModuleUsage(callee, context, reporter, expression.source)
}
}
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
import org.jetbrains.kotlin.fir.delegatedWrapperData
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.packageFqName
@@ -79,7 +78,7 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() {
val receiverParameter = declaration.receiverParameter
if (receiverParameter != null) {
for (receiverAnnotation in receiverParameter.annotations) {
reportIfMfvc(context, reporter, receiverAnnotation, "receivers", receiverParameter.typeRef)
reportIfMfvc(context, reporter, receiverAnnotation, "receivers", receiverParameter.typeRef.coneType)
}
}
}
@@ -103,7 +102,13 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() {
}
}
private fun reportIfMfvc(context: CheckerContext, reporter: DiagnosticReporter, annotation: FirAnnotation, hint: String, type: FirTypeRef) {
private fun reportIfMfvc(
context: CheckerContext,
reporter: DiagnosticReporter,
annotation: FirAnnotation,
hint: String,
type: ConeKotlinType,
) {
if (type.needsMultiFieldValueClassFlattening(context.session)) {
reporter.reportOn(annotation.source, FirErrors.ANNOTATION_ON_ILLEGAL_MULTI_FIELD_VALUE_CLASS_TYPED_TARGET, hint, context)
}
@@ -120,7 +125,8 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() {
val (hint, type) = when (annotation.useSiteTarget) {
FIELD -> "fields" to ((declaration as? FirBackingField)?.returnTypeRef ?: return)
PROPERTY_DELEGATE_FIELD -> "delegate fields" to ((declaration as? FirBackingField)?.propertySymbol?.delegate?.typeRef ?: return)
PROPERTY_DELEGATE_FIELD -> "delegate fields" to ((declaration as? FirBackingField)?.propertySymbol?.delegate?.coneTypeOrNull
?: return)
RECEIVER -> "receivers" to ((declaration as? FirCallableDeclaration)?.receiverParameter?.typeRef ?: return)
FILE, PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, CONSTRUCTOR_PARAMETER, SETTER_PARAMETER, null -> when {
declaration is FirProperty && !declaration.isLocal -> {
@@ -141,7 +147,7 @@ object FirAnnotationChecker : FirBasicDeclarationChecker() {
else -> return
}
}
reportIfMfvc(context, reporter, annotation, hint, type)
reportIfMfvc(context, reporter, annotation, hint, type as? ConeKotlinType ?: (type as FirTypeRef).coneType)
}
private fun checkAnnotationTarget(
@@ -15,11 +15,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
import org.jetbrains.kotlin.fir.types.isNullable
import org.jetbrains.kotlin.fir.types.typeContext
internal fun isInsideExpectClass(containingClass: FirClass, context: CheckerContext): Boolean {
return isInsideSpecificClass(containingClass, context) { klass -> klass is FirRegularClass && klass.isExpect }
@@ -102,8 +99,10 @@ fun FirClassSymbol<*>.primaryConstructorSymbol(session: FirSession): FirConstruc
return fir.primaryConstructorIfAny(session)
}
fun FirTypeRef.needsMultiFieldValueClassFlattening(session: FirSession) = with(session.typeContext) {
coneType.typeConstructor().isMultiFieldValueClass() && !coneType.isNullable
fun FirTypeRef.needsMultiFieldValueClassFlattening(session: FirSession): Boolean = coneType.needsMultiFieldValueClassFlattening(session)
fun ConeKotlinType.needsMultiFieldValueClassFlattening(session: FirSession) = with(session.typeContext) {
typeConstructor().isMultiFieldValueClass() && !isNullable
}
val FirCallableSymbol<*>.hasExplicitReturnType: Boolean
@@ -44,12 +44,11 @@ object FirNamedVarargChecker : FirCallChecker() {
}
return
}
val typeRef = argument.expression.typeRef
if (typeRef is FirErrorTypeRef) return
val type = argument.expression.coneTypeOrNull
if (type is ConeErrorType) return
if (argument.expression is FirArrayLiteral) return
@OptIn(UnexpandedTypeCheck::class)
if (allowAssignArray && typeRef.isArrayType) return
if (allowAssignArray && type?.isArrayType == true) return
if (isAnnotation) {
reporter.reportOn(
@@ -5,16 +5,16 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedReifiedParameterReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeTypeParameterInQualifiedAccess
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.ConeErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
object FirTypeParameterInQualifiedAccessChecker : FirQualifiedAccessExpressionChecker() {
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -36,7 +36,7 @@ object FirTypeParameterInQualifiedAccessChecker : FirQualifiedAccessExpressionCh
val secondLast = context.callsOrAssignments.elementAtOrNull(context.callsOrAssignments.size - 2)
if (secondLast is FirQualifiedAccessExpression && secondLast.explicitReceiver == expression) return
val diagnostic = expression.typeRef.coneTypeParameterInQualifiedAccess ?: return
val diagnostic = expression.coneTypeOrNull?.coneTypeParameterInQualifiedAccess ?: return
val source = expression.source ?: return
reporter.reportOn(source, FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION, diagnostic.symbol, context)
}
@@ -49,7 +49,7 @@ object FirTypeParameterInQualifiedAccessChecker : FirQualifiedAccessExpressionCh
val explicitReceiver = expression.explicitReceiver
val typeParameterSymbol =
(explicitReceiver as? FirResolvedReifiedParameterReference)?.symbol
?: explicitReceiver?.typeRef?.coneTypeParameterInQualifiedAccess?.symbol
?: explicitReceiver?.coneTypeOrNull?.coneTypeParameterInQualifiedAccess?.symbol
?: return
if (expression is FirCallableReferenceAccess) {
reporter.reportOn(expression.source, FirErrors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS, context)
@@ -58,6 +58,6 @@ object FirTypeParameterInQualifiedAccessChecker : FirQualifiedAccessExpressionCh
}
}
private val FirTypeRef.coneTypeParameterInQualifiedAccess: ConeTypeParameterInQualifiedAccess?
get() = (this as? FirErrorTypeRef)?.diagnostic as? ConeTypeParameterInQualifiedAccess
private val ConeKotlinType.coneTypeParameterInQualifiedAccess: ConeTypeParameterInQualifiedAccess?
get() = (this as? ConeErrorType)?.diagnostic as? ConeTypeParameterInQualifiedAccess
}
@@ -5,13 +5,15 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isRefinementUseless
import org.jetbrains.kotlin.fir.analysis.checkers.shouldCheckForExactType
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.expressions.FirOperation
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.argument
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.types.*
@@ -39,7 +41,7 @@ object FirUselessTypeOperationCallChecker : FirTypeOperatorCallChecker() {
FirOperation.IS -> reporter.reportOn(expression.source, FirErrors.USELESS_IS_CHECK, true, context)
FirOperation.NOT_IS -> reporter.reportOn(expression.source, FirErrors.USELESS_IS_CHECK, false, context)
FirOperation.AS, FirOperation.SAFE_AS -> {
if ((arg.typeRef as? FirResolvedTypeRef)?.isFromStubType != true) {
if (!expression.argFromStubType) {
reporter.reportOn(expression.source, FirErrors.USELESS_CAST, context)
}
}
@@ -29,7 +29,7 @@ object FirOptionalExpectationTypeChecker : FirTypeRefChecker() {
}
val annotationContainer = context.annotationContainers.lastOrNull()
if (annotationContainer?.annotations?.any { it.typeRef == typeRef } == true) return
if (annotationContainer?.annotations?.any { it.annotationTypeRef == typeRef } == true) return
reporter.reportOn(source, FirErrors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, context)
}
@@ -6,12 +6,12 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.diagnostics.*
@@ -19,8 +19,12 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.ConeErrorType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.renderForDebugging
class ErrorNodeDiagnosticCollectorComponent(
session: FirSession,
@@ -85,7 +89,7 @@ class ErrorNodeDiagnosticCollectorComponent(
}
private fun FirExpression?.cannotBeResolved(): Boolean {
return when (val diagnostic = (this?.typeRef as? FirErrorTypeRef)?.diagnostic) {
return when (val diagnostic = (this?.coneTypeOrNull as? ConeErrorType)?.diagnostic) {
is ConeUnresolvedNameError, is ConeInstanceAccessBeforeSuperCall, is ConeAmbiguousSuper -> true
is ConeSimpleDiagnostic -> diagnostic.kind == DiagnosticKind.NotASupertype ||
diagnostic.kind == DiagnosticKind.SuperNotAvailable ||
@@ -130,6 +134,11 @@ class ErrorNodeDiagnosticCollectorComponent(
reportFirDiagnostic(errorPrimaryConstructor.diagnostic, errorPrimaryConstructor.source, data)
}
override fun visitThisReference(thisReference: FirThisReference, data: CheckerContext) {
val diagnostic = thisReference.diagnostic ?: return
reportFirDiagnostic(diagnostic, thisReference.source, data)
}
private fun reportFirDiagnostic(
diagnostic: ConeDiagnostic,
source: KtSourceElement?,
@@ -1469,7 +1469,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
}
private fun FlowContent.generate(unitExpression: FirUnitExpression) {
generate(unitExpression.typeRef)
generate(unitExpression.coneType)
}
private fun FlowContent.generate(breakExpression: FirBreakExpression) {
@@ -1530,7 +1530,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
}
private fun FlowContent.generate(expression: FirExpression) {
exprType(expression.typeRef) {
exprType(expression.coneType.toFirResolvedTypeRef()) {
when (expression) {
is FirBlock -> generateBlockIfAny(expression)
is FirGetClassCall -> generate(expression)
@@ -271,16 +271,14 @@ abstract class AbstractAnnotationDeserializer(
val classId = nameResolver.getClassId(value.classId)
val lookupTag = classId.toLookupTag()
val referencedType = lookupTag.constructType(emptyArray(), isNullable = false)
val resolvedTypeRef = buildResolvedTypeRef {
type = StandardClassIds.KClass.constructClassLikeType(arrayOf(referencedType), false)
}
val resolvedType = StandardClassIds.KClass.constructClassLikeType(arrayOf(referencedType), false)
argumentList = buildUnaryArgumentList(
buildClassReferenceExpression {
classTypeRef = buildResolvedTypeRef { type = referencedType }
typeRef = resolvedTypeRef
coneTypeOrNull = resolvedType
}
)
typeRef = resolvedTypeRef
coneTypeOrNull = resolvedType
}
ENUM -> buildPropertyAccessExpression {
val classId = nameResolver.getClassId(value.classId)
@@ -300,7 +298,7 @@ abstract class AbstractAnnotationDeserializer(
name = entryName
}
if (enumEntrySymbol != null) {
typeRef = enumEntrySymbol.returnTypeRef
coneTypeOrNull = enumEntrySymbol.returnTypeRef.coneTypeOrNull
}
}
ARRAY -> {
@@ -309,9 +307,7 @@ abstract class AbstractAnnotationDeserializer(
argumentList = buildArgumentList {
value.arrayElementList.mapTo(arguments) { resolveValue(it, nameResolver) { expectedArrayElementType } }
}
typeRef = buildResolvedTypeRef {
type = expectedArrayElementType.createArrayType()
}
coneTypeOrNull = expectedArrayElementType.createArrayType()
}
}
@@ -320,6 +316,6 @@ abstract class AbstractAnnotationDeserializer(
}
private fun <T> const(kind: ConstantValueKind<T>, value: T, typeRef: FirResolvedTypeRef): FirConstExpression<T> {
return buildConstExpression(null, kind, value, setType = true).apply { this.replaceTypeRef(typeRef) }
return buildConstExpression(null, kind, value, setType = true).apply { this.replaceConeTypeOrNull(typeRef.coneType) }
}
}
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.toLookupTag
@@ -44,9 +43,7 @@ fun FirEnumEntryDeserializedAccessExpression.toQualifiedPropertyAccessExpression
}
}
typeRef = buildResolvedTypeRef {
type = ConeClassLikeTypeImpl(
enumClassId.toLookupTag(), ConeTypeProjection.EMPTY_ARRAY, isNullable = false
)
}
coneTypeOrNull = ConeClassLikeTypeImpl(
enumClassId.toLookupTag(), ConeTypeProjection.EMPTY_ARRAY, isNullable = false
)
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.toEffectiveVisibility
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
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.coneType
@@ -469,7 +470,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers, ::loadContextReceiver)
}.apply {
initializer?.replaceTypeRef(returnTypeRef)
initializer?.replaceConeTypeOrNull(returnTypeRef.type)
this.versionRequirements = versionRequirements
replaceDeprecationsProvider(getDeprecationsProvider(c.session))
setLazyPublishedVisibility(c.session)
@@ -696,6 +697,6 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
}.toList()
}
private fun ProtoBuf.Type.toTypeRef(context: FirDeserializationContext): FirTypeRef =
private fun ProtoBuf.Type.toTypeRef(context: FirDeserializationContext): FirResolvedTypeRef =
context.typeDeserializer.typeRef(this)
}
@@ -108,7 +108,7 @@ class FirTypeDeserializer(
}
}
fun typeRef(proto: ProtoBuf.Type): FirTypeRef {
fun typeRef(proto: ProtoBuf.Type): FirResolvedTypeRef {
return buildResolvedTypeRef {
annotations += annotationDeserializer.loadTypeAnnotations(proto, nameResolver)
type = type(proto, annotations.computeTypeAttributes(moduleData.session, shouldExpandTypeAliases = false))
@@ -288,4 +288,4 @@ class FirTypeDeserializer(
val coneType = type(type)
return coneType.toTypeProjection(variance)
}
}
}
@@ -1098,7 +1098,7 @@ class Fir2IrVisitor(
source = elvisExpression.source
moduleData = session.moduleData
origin = FirDeclarationOrigin.Source
returnTypeRef = elvisExpression.lhs.typeRef
returnTypeRef = elvisExpression.lhs.coneType.toFirResolvedTypeRef()
name = Name.special("<elvis>")
initializer = elvisExpression.lhs
symbol = FirPropertySymbol(name)
@@ -1511,7 +1511,7 @@ class Fir2IrVisitor(
private fun convertToArrayLiteral(arrayLiteral: FirArrayLiteral): IrVararg {
return arrayLiteral.convertWithOffsets { startOffset, endOffset ->
val arrayType = arrayLiteral.coneType.toIrType()
val elementType = if (arrayLiteral.typeRef is FirResolvedTypeRef) {
val elementType = if (arrayLiteral.coneTypeOrNull != null) {
arrayType.getArrayElementType(irBuiltIns)
} else {
createErrorType()
@@ -551,7 +551,7 @@ internal class AdapterGenerator(
private fun needSamConversion(argument: FirExpression, parameter: FirValueParameter): Boolean {
// If the type of the argument is already an explicitly subtype of the type of the parameter, we don't need SAM conversion.
if (argument.typeRef !is FirResolvedTypeRef ||
if (argument.coneTypeOrNull == null ||
AbstractTypeChecker.isSubtypeOf(
session.typeContext.newTypeCheckerState(
errorTypesEqualToAnything = false, stubTypesEqualToAnything = true
@@ -123,9 +123,7 @@ private fun <T> List<T>.createArrayLiteral(session: FirSession, kind: ConstantVa
arguments += element.createConstantOrError(session)
}
}
typeRef = buildResolvedTypeRef {
type = kind.expectedConeType(session).createArrayType()
}
coneTypeOrNull = kind.expectedConeType(session).createArrayType()
}
}
@@ -42,9 +42,7 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
val resolvedClassTypeRef = classId.toLookupTag().toDefaultResolvedTypeRef()
return buildClassReferenceExpression {
classTypeRef = resolvedClassTypeRef
typeRef = buildResolvedTypeRef {
type = StandardClassIds.KClass.constructClassLikeType(arrayOf(resolvedClassTypeRef.type), false)
}
coneTypeOrNull = StandardClassIds.KClass.constructClassLikeType(arrayOf(resolvedClassTypeRef.type), false)
}
}
@@ -52,7 +50,7 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
visitExpression(name, buildGetClassCall {
val argument = value.toFirClassReferenceExpression()
argumentList = buildUnaryArgumentList(argument)
typeRef = argument.typeRef
coneTypeOrNull = argument.coneTypeOrNull
})
}
@@ -78,7 +76,7 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
elements.add(buildGetClassCall {
val argument = value.toFirClassReferenceExpression()
argumentList = buildUnaryArgumentList(argument)
typeRef = argument.typeRef
coneTypeOrNull = argument.coneTypeOrNull
})
}
@@ -96,11 +94,9 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
override fun visitEnd() {
visitExpression(name, buildArrayLiteral {
guessArrayTypeIfNeeded(name, elements)?.let {
typeRef = it
coneTypeOrNull = it.coneTypeOrNull
} ?: elements.firstOrNull()?.coneType?.createOutArrayType()?.let {
typeRef = buildResolvedTypeRef {
type = it
}
coneTypeOrNull = it
}
argumentList = buildArgumentList {
arguments += elements
@@ -24,8 +24,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.unexpandedClassId
import org.jetbrains.kotlin.fir.java.*
import org.jetbrains.kotlin.fir.java.FirJavaTypeConversionMode
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.declarations.*
import org.jetbrains.kotlin.fir.java.resolveIfJavaType
import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
import org.jetbrains.kotlin.load.java.FakePureImplementationsProvider
@@ -54,8 +53,8 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.kotlin.types.model.TypeSystemContext
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
import org.jetbrains.kotlin.util.PrivateForInline
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
class FirSignatureEnhancement(
private val owner: FirRegularClass,
@@ -363,7 +362,7 @@ class FirSignatureEnhancement(
}
}.apply {
val newValueParameters = firMethod.valueParameters.zip(enhancedValueParameterTypes) { valueParameter, enhancedReturnType ->
valueParameter.defaultValue?.replaceTypeRef(enhancedReturnType)
valueParameter.defaultValue?.replaceConeTypeOrNull(enhancedReturnType.coneType)
buildValueParameter {
source = valueParameter.source
@@ -90,9 +90,8 @@ internal fun JavaAnnotationArgument.toFirExpression(
)
is JavaArrayAnnotationArgument -> buildArrayLiteral {
val argumentTypeRef = expectedTypeRef?.let {
typeRef = if (it is FirJavaTypeRef) buildResolvedTypeRef {
type = it.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack)
} else it
coneTypeOrNull =
if (it is FirJavaTypeRef) it.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack) else it.coneType
buildResolvedTypeRef {
type = it.coneTypeSafe<ConeKotlinType>()?.lowerBoundIfFlexible()?.arrayElementType()
?: ConeErrorType(ConeSimpleDiagnostic("expected type is not array type"))
@@ -111,10 +110,10 @@ internal fun JavaAnnotationArgument.toFirExpression(
argumentList = buildUnaryArgumentList(
buildClassReferenceExpression {
classTypeRef = resolvedClassTypeRef
typeRef = resolvedTypeRef
coneTypeOrNull = resolvedTypeRef.coneType
}
)
typeRef = resolvedTypeRef
coneTypeOrNull = resolvedTypeRef.coneType
}
is JavaAnnotationAsAnnotationArgument -> getAnnotation().toFirAnnotationCall(session)
else -> buildErrorExpression {
@@ -168,13 +167,11 @@ private fun buildEnumCall(session: FirSession, classId: ClassId?, entryName: Nam
}
if (classId != null) {
this.typeRef = buildResolvedTypeRef {
type = ConeClassLikeTypeImpl(
classId.toLookupTag(),
emptyArray(),
isNullable = false
)
}
this.coneTypeOrNull = ConeClassLikeTypeImpl(
classId.toLookupTag(),
emptyArray(),
isNullable = false
)
}
}
}
@@ -194,9 +191,7 @@ private fun List<JavaAnnotationArgument>.mapJavaTargetArguments(session: FirSess
isNullable = false,
ConeAttributes.Empty
)
typeRef = buildResolvedTypeRef {
type = elementConeType
}
coneTypeOrNull = elementConeType
varargElementType = buildResolvedTypeRef {
type = elementConeType.createOutArrayType()
}
@@ -88,7 +88,7 @@ public sealed class FunctionBuildingContext<T : FirFunction>(
symbol = FirValueParameterSymbol(name)
if (valueParameter.hasDefaultValue) {
// TODO: check how it will actually work in fir2ir
defaultValue = buildExpressionStub { typeRef = session.builtinTypes.nothingType }
defaultValue = buildExpressionStub { coneTypeOrNull = session.builtinTypes.nothingType.type }
}
this.containingFunctionSymbol = containingFunctionSymbol
isCrossinline = valueParameter.isCrossinline
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.copyWithNewSourceKind
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall
@@ -29,8 +28,11 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.ConeErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.constructType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.SmartcastStability
@@ -116,12 +118,12 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
buildSmartCastExpression {
originalExpression = originalReceiverExpression
smartcastType = buildResolvedTypeRef {
source = originalReceiverExpression.typeRef.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
source = originalReceiverExpression.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
type = this@ImplicitReceiverValue.type
}
typesFromSmartCast = listOf(type)
typesFromSmartCast = listOf(this@ImplicitReceiverValue.type)
smartcastStability = SmartcastStability.STABLE_VALUE
typeRef = smartcastType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
coneTypeOrNull = this@ImplicitReceiverValue.type
}
} else {
originalReceiverExpression
@@ -195,16 +197,15 @@ private fun receiverExpression(
boundSymbol = symbol
this.contextReceiverNumber = contextReceiverNumber
}
val typeRef = type.toFirResolvedTypeRef()
return when (inaccessibleReceiver) {
false -> buildThisReceiverExpression {
this.calleeReference = calleeReference
this.typeRef = typeRef
this.coneTypeOrNull = type
isImplicit = true
}
true -> buildInaccessibleReceiverExpression {
this.calleeReference = calleeReference
this.typeRef = typeRef
this.coneTypeOrNull = type
}
}
}
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
fun ConeKotlinType.ensureResolvedTypeDeclaration(
fun ConeKotlinType?.ensureResolvedTypeDeclaration(
useSiteSession: FirSession,
requiredPhase: FirResolvePhase = FirResolvePhase.DECLARATIONS,
) {
@@ -29,5 +29,5 @@ fun FirTypeRef.ensureResolvedTypeDeclaration(
useSiteSession: FirSession,
requiredPhase: FirResolvePhase = FirResolvePhase.DECLARATIONS,
) {
coneTypeSafe<ConeKotlinType>()?.ensureResolvedTypeDeclaration(useSiteSession, requiredPhase)
coneTypeSafe<ConeKotlinType>().ensureResolvedTypeDeclaration(useSiteSession, requiredPhase)
}
@@ -415,7 +415,6 @@ fun FirTypeRef.withReplacedConeType(
type = newType
annotations += this@withReplacedConeType.annotations
delegatedTypeRef = this@withReplacedConeType.delegatedTypeRef
isFromStubType = this@withReplacedConeType.type is ConeStubType
}
}
}
@@ -25,10 +25,7 @@ import org.jetbrains.kotlin.fir.references.builder.buildImplicitThisReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
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.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
@@ -1116,13 +1113,13 @@ fun <TBase, TSource : TBase, TParameter : TBase> FirRegularClassBuilder.createDa
) =
buildPropertyAccessExpression {
this.source = parameterSource
typeRef = firPropertyReturnTypeRefWithCorrectSourceKind
coneTypeOrNull = firPropertyReturnTypeRefWithCorrectSourceKind.coneTypeOrNull
this.dispatchReceiver = buildThisReceiverExpression {
this.source = parameterSource
calleeReference = buildImplicitThisReference {
boundSymbol = this@createDataClassCopyFunction.symbol
}
typeRef = classTypeRefWithCorrectSourceKind
coneTypeOrNull = classTypeRefWithCorrectSourceKind.coneTypeOrNull
}
calleeReference = buildResolvedNamedReference {
this.source = parameterSource
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirReceiverParameter
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.builder.*
@@ -42,14 +41,16 @@ 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.ConeStarProjection
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
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.impl.*
import org.jetbrains.kotlin.fir.types.constructClassLikeType
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -351,9 +352,7 @@ fun <T> FirPropertyBuilder.generateAccessorsByDelegate(
calleeReference = buildImplicitThisReference {
boundSymbol = ownerRegularOrAnonymousObjectSymbol
}
typeRef = buildResolvedTypeRef {
type = context.dispatchReceiverTypesStack.last()
}
coneTypeOrNull = context.dispatchReceiverTypesStack.last()
}
else -> buildConstExpression(null, ConstantValueKind.Null, null, setType = false)
}
@@ -376,21 +375,27 @@ fun <T> FirPropertyBuilder.generateAccessorsByDelegate(
name = this@generateAccessorsByDelegate.name
resolvedSymbol = this@generateAccessorsByDelegate.symbol
}
typeRef = when {
coneTypeOrNull = when {
!isMember && !isExtension -> if (isVar) {
FirImplicitKMutableProperty0TypeRef(null, ConeStarProjection)
StandardClassIds.KMutableProperty0.constructClassLikeType(arrayOf(ConeStarProjection))
} else {
FirImplicitKProperty0TypeRef(null, ConeStarProjection)
StandardClassIds.KProperty0.constructClassLikeType(arrayOf(ConeStarProjection))
}
isMember && isExtension -> if (isVar) {
FirImplicitKMutableProperty2TypeRef(null, ConeStarProjection, ConeStarProjection, ConeStarProjection)
StandardClassIds.KMutableProperty2.constructClassLikeType(
arrayOf(
ConeStarProjection,
ConeStarProjection,
ConeStarProjection
)
)
} else {
FirImplicitKProperty2TypeRef(null, ConeStarProjection, ConeStarProjection, ConeStarProjection)
StandardClassIds.KProperty2.constructClassLikeType(arrayOf(ConeStarProjection, ConeStarProjection, ConeStarProjection))
}
else -> if (isVar) {
FirImplicitKMutableProperty1TypeRef(null, ConeStarProjection, ConeStarProjection)
StandardClassIds.KMutableProperty1.constructClassLikeType(arrayOf(ConeStarProjection, ConeStarProjection))
} else {
FirImplicitKProperty1TypeRef(null, ConeStarProjection, ConeStarProjection)
StandardClassIds.KProperty1.constructClassLikeType(arrayOf(ConeStarProjection, ConeStarProjection))
}
}
this@generateAccessorsByDelegate.typeParameters.mapTo(typeArguments) {
@@ -118,9 +118,9 @@ class FirCallResolver(
candidate?.updateSourcesOfReceivers()
functionCall
}
val typeRef = components.typeFromCallee(resultFunctionCall)
if (typeRef.type is ConeErrorType) {
resultFunctionCall.resultType = typeRef
val type = components.typeFromCallee(resultFunctionCall).type
if (type is ConeErrorType) {
resultFunctionCall.resultType = type
}
return resultFunctionCall
@@ -344,7 +344,7 @@ class FirCallResolver(
return buildResolvedReifiedParameterReference {
source = nameReference.source
symbol = referencedSymbol
typeRef = typeForReifiedParameterReference(this)
coneTypeOrNull = typeForReifiedParameterReference(this)
}
}
}
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
import org.jetbrains.kotlin.fir.declarations.getDeprecationForCallSite
@@ -19,8 +21,7 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.getSingleVisibleClassifier
import org.jetbrains.kotlin.fir.resolve.createCurrentScopeList
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDeprecated
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.typeForQualifier
import org.jetbrains.kotlin.fir.resolve.setTypeOfQualifier
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -41,7 +42,7 @@ fun BodyResolveComponents.resolveRootPartOfQualifier(
this.nonFatalDiagnostics.addAll(nonFatalDiagnosticsFromExpression.orEmpty())
annotations += qualifiedAccess.annotations
}.apply {
resultType = typeForQualifier(this)
setTypeOfQualifier(session)
}
}
@@ -77,7 +78,7 @@ fun BodyResolveComponents.resolveRootPartOfQualifier(
)
annotations += qualifiedAccess.annotations
}.apply {
resultType = typeForQualifier(this)
setTypeOfQualifier(session)
}
}
}
@@ -126,7 +127,7 @@ fun FirResolvedQualifier.continueQualifier(
)
)
}.apply {
resultType = components.typeForQualifier(this)
setTypeOfQualifier(components.session)
}
}
}
@@ -154,7 +155,7 @@ private fun FqName.continueQualifierInPackage(
this.nonFatalDiagnostics.addAll(nonFatalDiagnosticsFromExpression.orEmpty())
annotations += qualifiedAccess.annotations
}.apply {
resultType = components.typeForQualifier(this)
setTypeOfQualifier(components.session)
}
}
@@ -179,7 +180,7 @@ private fun FqName.continueQualifierInPackage(
isFullyQualified = true
annotations += qualifiedAccess.annotations
}.apply {
resultType = components.typeForQualifier(this)
setTypeOfQualifier(components.session)
}
}
@@ -65,8 +65,7 @@ fun FirAnonymousFunction.addReturnToLastStatementIfNeeded(session: FirSession) {
val lastStatement = body.statements.lastOrNull() as? FirExpression ?: return
if (lastStatement is FirReturnExpression) return
val returnType = (body.typeRef as? FirResolvedTypeRef) ?: return
@OptIn(UnexpandedTypeCheck::class)
val returnType = body.coneTypeOrNull ?: return
if (returnType.isNothing) return
val returnTarget = FirFunctionTarget(null, isLambda = isLambda).also { it.bind(this) }
@@ -212,50 +211,51 @@ fun BodyResolveComponents.buildResolvedQualifierForClass(
this.nonFatalDiagnostics.addAll(nonFatalDiagnostics)
this.annotations.addAll(annotations)
}.build().apply {
resultType = if (classId.isLocal) {
typeForQualifierByDeclaration(regularClass.fir, resultType, session)
?: session.builtinTypes.unitType
if (classId.isLocal) {
resultType = typeForQualifierByDeclaration(regularClass.fir, resultType, session)
?.also { replaceCanBeValue(true) }
?: session.builtinTypes.unitType.type
} else {
typeForQualifier(this)
setTypeOfQualifier(session)
}
}
}
fun BodyResolveComponents.typeForQualifier(resolvedQualifier: FirResolvedQualifier): FirTypeRef {
val classSymbol = resolvedQualifier.symbol
val resultType = resolvedQualifier.resultType
fun FirResolvedQualifier.setTypeOfQualifier(session: FirSession) {
val classSymbol = symbol
val resultType = resultType
if (classSymbol != null) {
classSymbol.lazyResolveToPhase(FirResolvePhase.TYPES)
val declaration = classSymbol.fir
if (declaration !is FirTypeAlias || resolvedQualifier.typeArguments.isEmpty()) {
typeForQualifierByDeclaration(declaration, resultType, session)?.let { return it }
if (declaration !is FirTypeAlias || typeArguments.isEmpty()) {
val typeByDeclaration = typeForQualifierByDeclaration(declaration, resultType, session)
if (typeByDeclaration != null) {
this.resultType = typeByDeclaration
replaceCanBeValue(true)
return
}
}
}
return session.builtinTypes.unitType
this.resultType = session.builtinTypes.unitType.type
}
internal fun typeForReifiedParameterReference(parameterReferenceBuilder: FirResolvedReifiedParameterReferenceBuilder): FirTypeRef {
val resultType = parameterReferenceBuilder.typeRef
internal fun typeForReifiedParameterReference(parameterReferenceBuilder: FirResolvedReifiedParameterReferenceBuilder): ConeLookupTagBasedType {
val typeParameterSymbol = parameterReferenceBuilder.symbol
return resultType.resolvedTypeFromPrototype(typeParameterSymbol.constructType(emptyArray(), false))
return typeParameterSymbol.constructType(emptyArray(), false)
}
internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultType: FirTypeRef, session: FirSession): FirTypeRef? {
internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultType: ConeKotlinType?, session: FirSession): ConeKotlinType? {
if (declaration is FirTypeAlias) {
val expandedDeclaration = declaration.expandedConeType?.lookupTag?.toSymbol(session)?.fir ?: return null
return typeForQualifierByDeclaration(expandedDeclaration, resultType, session)
}
if (declaration is FirRegularClass) {
if (declaration.classKind == ClassKind.OBJECT) {
return resultType.resolvedTypeFromPrototype(
declaration.symbol.constructType(emptyArray(), false),
)
return declaration.symbol.constructType(emptyArray(), false)
} else {
val companionObjectSymbol = declaration.companionObjectSymbol
if (companionObjectSymbol != null) {
return resultType.resolvedTypeFromPrototype(
companionObjectSymbol.constructType(emptyArray(), false),
)
return companionObjectSymbol.constructType(emptyArray(), false)
}
}
}
@@ -395,11 +395,11 @@ private val ConeKotlinType.isKindOfNothing
get() = lowerBoundIfFlexible().let { it.isNothing || it.isNullableNothing }
private fun FirSmartCastExpressionBuilder.applyResultTypeRef() {
typeRef =
coneTypeOrNull =
if (smartcastStability == SmartcastStability.STABLE_VALUE)
smartcastType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
smartcastType.coneTypeOrNull
else
originalExpression.typeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
originalExpression.coneTypeOrNull
}
private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSmartcastInfo(
@@ -424,10 +424,8 @@ private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSm
val intersectedType = ConeTypeIntersector.intersectTypes(session.typeContext, allTypes)
if (intersectedType == originalType && intersectedType !is ConeDynamicType) return null
val intersectedTypeRef = buildResolvedTypeRef {
source = expression.resultType.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
source = expression.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
type = intersectedType
annotations += expression.resultType.annotations
delegatedTypeRef = expression.resultType
}
// Example (1): if (x is String) { ... }, where x: dynamic
@@ -443,10 +441,8 @@ private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSm
val reducedTypes = typesFromSmartCast.filterTo(mutableListOf()) { !it.isKindOfNothing }
val reducedIntersectedType = ConeTypeIntersector.intersectTypes(session.typeContext, reducedTypes)
val reducedIntersectedTypeRef = buildResolvedTypeRef {
source = expression.resultType.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
source = expression.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
type = reducedIntersectedType
annotations += expression.resultType.annotations
delegatedTypeRef = expression.resultType
}
return buildSmartCastExpression {
originalExpression = expression
@@ -474,17 +470,17 @@ fun FirCheckedSafeCallSubject.propagateTypeFromOriginalReceiver(
) {
// If the receiver expression is smartcast to `null`, it would have `Nothing?` as its type, which may not have members called by user
// code. Hence, we fallback to the type before intersecting with `Nothing?`.
val receiverType = ((nullableReceiverExpression as? FirSmartCastExpression)
val receiverType = (nullableReceiverExpression as? FirSmartCastExpression)
?.takeIf { it.isStable }
?.smartcastTypeWithoutNullableNothing
?: nullableReceiverExpression.typeRef)
.coneTypeSafe<ConeKotlinType>() ?: return
?.coneTypeSafe<ConeKotlinType>()
?: nullableReceiverExpression.coneTypeOrNull
?: return
val expandedReceiverType = receiverType.fullyExpandedType(session)
val updatedReceiverType = expandedReceiverType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext).independentInstance()
val resolvedTypeRef = typeRef.resolvedTypeFromPrototype(updatedReceiverType)
replaceTypeRef(resolvedTypeRef)
session.lookupTracker?.recordTypeResolveAsLookup(resolvedTypeRef, source, file.source)
replaceConeTypeOrNull(updatedReceiverType)
session.lookupTracker?.recordTypeResolveAsLookup(updatedReceiverType, source, file.source)
}
fun FirSafeCallExpression.propagateTypeFromQualifiedAccessAfterNullCheck(
@@ -505,9 +501,9 @@ fun FirSafeCallExpression.propagateTypeFromQualifiedAccessAfterNullCheck(
}
}
val resolvedTypeRef = typeRef.resolvedTypeFromPrototype(resultingType.independentInstance())
replaceTypeRef(resolvedTypeRef)
session.lookupTracker?.recordTypeResolveAsLookup(resolvedTypeRef, source, file.source)
val independentInstance = resultingType.independentInstance()
replaceConeTypeOrNull(independentInstance)
session.lookupTracker?.recordTypeResolveAsLookup(independentInstance, source, file.source)
}
private val FirExpression.isCallToStatementLikeFunction: Boolean
@@ -17,14 +17,10 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.builder.buildNamedArgumentExpression
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
import org.jetbrains.kotlin.fir.resolve.createFunctionType
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedCallableReferenceTarget
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.extractInputOutputTypesFromCallableReferenceExpectedType
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.*
@@ -408,18 +404,18 @@ private fun createFakeArgumentsForReference(
}
class FirFakeArgumentForCallableReference(
val index: Int
val index: Int,
) : FirExpression() {
override val source: KtSourceElement?
get() = null
override val typeRef: FirTypeRef
override val coneTypeOrNull: ConeKotlinType
get() = shouldNotBeCalled()
override val annotations: List<FirAnnotation>
get() = shouldNotBeCalled()
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
override fun replaceConeTypeOrNull(newConeTypeOrNull: ConeKotlinType?) {
shouldNotBeCalled()
}
@@ -8,7 +8,8 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirVisibilityChecker
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
@@ -103,12 +104,12 @@ private fun removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiver: FirEx
buildSmartCastExpression {
this.originalExpression = originalExpression
smartcastType = buildResolvedTypeRef {
source = originalExpression.typeRef.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
source = originalExpression.source?.fakeElement(KtFakeSourceElementKind.SmartCastedTypeRef)
type = originalTypeNotNullable
}
typesFromSmartCast = listOf(originalTypeNotNullable)
smartcastStability = expressionWithSmartcastIfStable.smartcastStability
typeRef = smartcastType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
coneTypeOrNull = originalTypeNotNullable
}
else -> originalExpression
}
@@ -310,7 +310,7 @@ private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
candidate
)
dispatchReceiver = candidate.dispatchReceiverExpression()
this.typeRef = returnTypeCalculator.tryCalculateReturnType(symbol.fir)
coneTypeOrNull = returnTypeCalculator.tryCalculateReturnType(symbol.fir).type
if (!invokeBuiltinExtensionMode) {
extensionReceiver = extensionReceiverExpression
@@ -15,14 +15,13 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.setTypeOfQualifier
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirWhenSubjectImportingScope
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
@@ -113,7 +112,7 @@ internal abstract class FirBaseTowerResolveTask(
this.symbol = it
this.source = source?.fakeElement(KtFakeSourceElementKind.ImplicitReceiver)
}.apply {
resultType = components.typeForQualifier(this)
setTypeOfQualifier(components.session)
}
ExpressionReceiverValue(resolvedQualifier)
}
@@ -231,13 +230,10 @@ internal open class FirTowerResolveTask(
processClassifierScope(info, qualifierReceiver)
if (resolvedQualifier.symbol != null) {
val typeRef = resolvedQualifier.typeRef
if (info.callKind == CallKind.CallableReference && info.lhs is DoubleColonLHS.Type) {
val stubReceiver = buildExpressionStub {
source = info.explicitReceiver?.source
this.typeRef = buildResolvedTypeRef {
type = info.lhs.type
}
this.coneTypeOrNull = info.lhs.type
}
val stubReceiverInfo = info.replaceExplicitReceiver(stubReceiver)
@@ -245,8 +241,8 @@ internal open class FirTowerResolveTask(
runResolverForExpressionReceiver(stubReceiverInfo, stubReceiver, parentGroup = TowerGroup.QualifierValue)
}
// NB: yet built-in Unit is used for "no-value" type
if (typeRef !is FirImplicitBuiltinTypeRef) {
// NB: canBeValue means it's resolved to an object or companion object
if (resolvedQualifier.canBeValue) {
runResolverForExpressionReceiver(info, resolvedQualifier, parentGroup = TowerGroup.QualifierValue)
}
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.FirDefaultStarImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectOrStaticData
@@ -337,7 +336,7 @@ class ScopeTowerLevel(
this.symbol = this@toResolvedQualifierExpressionReceiver
this.source = source?.fakeElement(KtFakeSourceElementKind.ImplicitReceiver)
}.apply {
resultType = bodyResolveComponents.typeForQualifier(this)
setTypeOfQualifier(bodyResolveComponents.session)
}
return ExpressionReceiverValue(resolvedQualifier)
}
@@ -31,7 +31,10 @@ import org.jetbrains.kotlin.fir.scopes.getFunctions
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.ConstantValueKind
@@ -906,7 +909,7 @@ abstract class FirDataFlowAnalyzer(
}
fun exitConstExpression(constExpression: FirConstExpression<*>) {
if (constExpression.resultType is FirResolvedTypeRef) return
if (constExpression.coneTypeOrNull != null) return
graphBuilder.exitConstExpression(constExpression).mergeIncomingFlow()
}
@@ -1129,7 +1132,7 @@ abstract class FirDataFlowAnalyzer(
val elvisVariable by lazy { variableStorage.createSynthetic(elvisExpression) }
// If (x ?: null) != null then x != null
if (elvisExpression.rhs.resultType.isNullableNothing) {
if (elvisExpression.rhs.resultType?.isNullableNothing == true) {
val lhsVariable = variableStorage.getOrCreateIfReal(flow, elvisExpression.lhs)
if (lhsVariable != null) {
flow.addImplication((elvisVariable notEq null) implies (lhsVariable notEq null))
@@ -1137,7 +1140,7 @@ abstract class FirDataFlowAnalyzer(
}
// If (null ?: x) != null then x != null
if (elvisExpression.lhs.resultType.isNullableNothing) {
if (elvisExpression.lhs.resultType?.isNullableNothing == true) {
val rhsVariable = variableStorage.getOrCreateIfReal(flow, elvisExpression.rhs)
if (rhsVariable != null) {
flow.addImplication((elvisVariable notEq null) implies (rhsVariable notEq null))
@@ -1083,9 +1083,8 @@ class ControlFlowGraphBuilder {
// it would be much easier if we could build calls after full completion only, at least for Nothing calls
// KT-59726
// @returns `true` if node actually returned Nothing
@OptIn(UnexpandedTypeCheck::class)
private fun completeFunctionCall(node: FunctionCallNode): Boolean {
if (!node.fir.resultType.isNothing) return false
if (node.fir.resultType?.isNothing != true) return false
val stub = StubNode(node.owner, node.level)
val edges = node.followingNodes.map { it to node.edgeTo(it) }
CFGNode.removeAllOutgoingEdges(node)
@@ -1101,9 +1100,8 @@ class ControlFlowGraphBuilder {
// ----------------------------------- Resolvable call -----------------------------------
@OptIn(UnexpandedTypeCheck::class)
fun exitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression): QualifiedAccessNode {
val returnsNothing = qualifiedAccessExpression.resultType.isNothing
val returnsNothing = qualifiedAccessExpression.resultType?.isNothing == true
val node = createQualifiedAccessNode(qualifiedAccessExpression)
if (returnsNothing) {
addNonSuccessfullyTerminatingNode(node)
@@ -1113,9 +1111,8 @@ class ControlFlowGraphBuilder {
return node
}
@OptIn(UnexpandedTypeCheck::class)
fun exitSmartCastExpression(smartCastExpression: FirSmartCastExpression): SmartCastExpressionExitNode {
val returnsNothing = smartCastExpression.resultType.isNothing
val returnsNothing = smartCastExpression.resultType?.isNothing == true
val node = createSmartCastExitNode(smartCastExpression)
if (returnsNothing) {
addNonSuccessfullyTerminatingNode(node)
@@ -1147,9 +1144,8 @@ class ControlFlowGraphBuilder {
return argumentListSplitNodes.pop()?.also { addNewSimpleNode(it) }
}
@OptIn(UnexpandedTypeCheck::class)
fun exitFunctionCall(functionCall: FirFunctionCall, callCompleted: Boolean): FunctionCallNode {
val returnsNothing = functionCall.resultType.isNothing
val returnsNothing = functionCall.resultType?.isNothing == true
val node = createFunctionCallNode(functionCall)
unifyDataFlowFromPostponedLambdas(node, callCompleted)
if (returnsNothing) {
@@ -1193,11 +1189,10 @@ class ControlFlowGraphBuilder {
return createThrowExceptionNode(throwExpression).also { addNonSuccessfullyTerminatingNode(it) }
}
@OptIn(UnexpandedTypeCheck::class)
fun exitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, callCompleted: Boolean): CheckNotNullCallNode {
val node = createCheckNotNullCallNode(checkNotNullCall)
unifyDataFlowFromPostponedLambdas(node, callCompleted)
if (checkNotNullCall.resultType.isNothing) {
if (checkNotNullCall.resultType?.isNothing == true) {
addNonSuccessfullyTerminatingNode(node)
} else {
addNewSimpleNode(node)
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
@@ -19,7 +18,6 @@ import org.jetbrains.kotlin.fir.resolve.calls.candidate
import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.replaceStubsAndTypeVariablesToErrors
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
import org.jetbrains.kotlin.fir.visitors.transformSingle
@@ -27,7 +25,9 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.inference.model.BuilderInferencePosition
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.inference.registerTypeVariableIfNotPresent
import org.jetbrains.kotlin.resolve.descriptorUtil.BUILDER_INFERENCE_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
@@ -268,10 +268,27 @@ class FirStubTypeTransformer(private val substitutor: ConeSubstitutor) : FirDefa
if (element is FirResolvable) {
element.candidate()?.let { processCandidate(it) }
}
// Since FirExpressions don't have typeRefs, they need to be updated separately.
// FirAnonymousFunctionExpression doesn't support replacing the type
// since it delegates the getter to the underlying FirAnonymousFunction.
if (element is FirExpression && element !is FirAnonymousFunctionExpression) {
element.coneTypeOrNull
?.let(substitutor::substituteOrNull)
?.let { element.replaceConeTypeOrNull(it) }
}
@Suppress("UNCHECKED_CAST")
return element.transformChildren(this, data = null) as E
}
override fun transformTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Nothing?): FirStatement {
if (typeOperatorCall.argument.coneTypeOrNull is ConeStubType) {
typeOperatorCall.replaceArgFromStubType(true)
}
return super.transformTypeOperatorCall(typeOperatorCall, data)
}
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?): FirTypeRef =
substitutor.substituteOrNull(resolvedTypeRef.type)?.let {
resolvedTypeRef.withReplacedConeType(it)
@@ -64,9 +64,8 @@ class FirCallCompleter(
val initialType = typeRef.initialTypeOfCandidate(candidate)
if (call is FirExpression) {
val resolvedTypeRef = typeRef.resolvedTypeFromPrototype(initialType)
call.resultType = resolvedTypeRef
session.lookupTracker?.recordTypeResolveAsLookup(resolvedTypeRef, call.source, components.context.file.source)
call.resultType = initialType
session.lookupTracker?.recordTypeResolveAsLookup(initialType, call.source, components.context.file.source)
}
addConstraintFromExpectedType(
@@ -17,8 +17,6 @@ import org.jetbrains.kotlin.fir.resolve.shouldReturnUnit
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
@@ -84,20 +82,14 @@ class PostponedArgumentsAnalyzer(
callableReferenceAccess.apply {
replaceCalleeReference(namedReference)
val typeForCallableReference = atom.resultingTypeForCallableReference
val resolvedTypeRef = when {
typeForCallableReference != null -> buildResolvedTypeRef {
type = typeForCallableReference
}
namedReference is FirErrorReferenceWithCandidate -> buildErrorTypeRef {
diagnostic = namedReference.diagnostic
}
else -> buildErrorTypeRef {
diagnostic = ConeUnresolvedReferenceError(callableReferenceAccess.calleeReference.name)
}
val resolvedType = when {
typeForCallableReference != null -> typeForCallableReference
namedReference is FirErrorReferenceWithCandidate -> ConeErrorType(namedReference.diagnostic)
else -> ConeErrorType(ConeUnresolvedReferenceError(callableReferenceAccess.calleeReference.name))
}
replaceTypeRef(resolvedTypeRef)
replaceConeTypeOrNull(resolvedType)
resolutionContext.session.lookupTracker?.recordTypeResolveAsLookup(
resolvedTypeRef, source, resolutionContext.bodyResolveComponents.file.source
resolvedType, source, resolutionContext.bodyResolveComponents.file.source
)
}
}
@@ -5,9 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isInline
@@ -40,7 +38,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildStarProjection
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
@@ -102,20 +99,12 @@ class FirCallCompletionResultsWriterTransformer(
val subCandidate = calleeReference.candidate
val declaration = subCandidate.symbol.fir
val typeArguments = computeTypeArguments(qualifiedAccessExpression, subCandidate)
val typeRef = if (declaration is FirCallableDeclaration) {
val type = if (declaration is FirCallableDeclaration) {
val calculated = typeCalculator.tryCalculateReturnType(declaration)
if (calculated !is FirErrorTypeRef) {
buildResolvedTypeRef {
source = calculated.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
annotations += calculated.annotations
type = calculated.type
}
calculated.type
} else {
buildErrorTypeRef {
source = calculated.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
type = calculated.type
diagnostic = calculated.diagnostic
}
ConeErrorType(calculated.diagnostic)
}
} else {
// this branch is for cases when we have
@@ -123,14 +112,12 @@ class FirCallCompletionResultsWriterTransformer(
// e.g. `T::toString` where T is a generic type.
// in these cases we should report an error on
// the calleeReference.source which is not a fake source.
buildErrorTypeRef {
source = calleeReference.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
diagnostic =
when (declaration) {
is FirTypeParameter -> ConeTypeParameterInQualifiedAccess(declaration.symbol)
else -> ConeSimpleDiagnostic("Callee reference to candidate without return type: ${declaration.render()}")
}
}
ConeErrorType(
when (declaration) {
is FirTypeParameter -> ConeTypeParameterInQualifiedAccess(declaration.symbol)
else -> ConeSimpleDiagnostic("Callee reference to candidate without return type: ${declaration.render()}")
}
)
}
var dispatchReceiver = subCandidate.dispatchReceiverExpression()
@@ -159,12 +146,12 @@ class FirCallCompletionResultsWriterTransformer(
qualifiedAccessExpression.replaceNonFatalDiagnostics(nonFatalDiagnostics)
}
qualifiedAccessExpression.replaceTypeRef(typeRef)
qualifiedAccessExpression.replaceConeTypeOrNull(type)
if (declaration !is FirErrorFunction) {
qualifiedAccessExpression.replaceTypeArguments(typeArguments)
}
session.lookupTracker?.recordTypeResolveAsLookup(typeRef, qualifiedAccessExpression.source, context.file.source)
session.lookupTracker?.recordTypeResolveAsLookup(type, qualifiedAccessExpression.source, context.file.source)
return qualifiedAccessExpression
}
@@ -181,12 +168,11 @@ class FirCallCompletionResultsWriterTransformer(
qualifiedAccessExpression
}
val result = prepareQualifiedTransform(qualifiedAccessExpression, calleeReference)
val typeRef = result.typeRef as FirResolvedTypeRef
val subCandidate = calleeReference.candidate
val resultType = typeRef.substituteTypeRef(subCandidate)
val resultType = result.coneTypeOrNull?.substituteType(subCandidate)
resultType.ensureResolvedTypeDeclaration(session)
result.replaceTypeRef(resultType)
result.replaceConeTypeOrNull(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, qualifiedAccessExpression.source, context.file.source)
if (mode == Mode.DelegatedPropertyCompletion) {
@@ -208,10 +194,8 @@ class FirCallCompletionResultsWriterTransformer(
val calleeReference = functionCall.calleeReference as? FirNamedReferenceWithCandidate
?: return functionCall
val result = prepareQualifiedTransform(functionCall, calleeReference)
val typeRef = result.typeRef as FirResolvedTypeRef
val subCandidate = calleeReference.candidate
val resultType: FirTypeRef
resultType = typeRef.substituteTypeRef(subCandidate)
val resultType = result.coneType.substituteType(subCandidate)
if (calleeReference.isError) {
subCandidate.argumentMapping?.let {
result.replaceArgumentList(buildArgumentListForErrorCall(result.argumentList, it))
@@ -238,7 +222,7 @@ class FirCallCompletionResultsWriterTransformer(
}
val expectedArgumentsTypeMapping = runIf(!calleeReference.isError) { subCandidate.createArgumentsMapping() }
result.argumentList.transformArguments(this, expectedArgumentsTypeMapping)
result.replaceTypeRef(resultType)
result.replaceConeTypeOrNull(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, functionCall.source, context.file.source)
if (mode == Mode.DelegatedPropertyCompletion) {
@@ -308,19 +292,19 @@ class FirCallCompletionResultsWriterTransformer(
}
}
private fun <D : FirExpression> D.replaceTypeRefWithSubstituted(
private fun <D : FirExpression> D.replaceTypeWithSubstituted(
calleeReference: FirNamedReferenceWithCandidate,
typeRef: FirResolvedTypeRef,
): D {
val resultTypeRef = typeRef.substituteTypeRef(calleeReference.candidate)
replaceTypeRef(resultTypeRef)
session.lookupTracker?.recordTypeResolveAsLookup(resultTypeRef, source, context.file.source)
val resultType = typeRef.type.substituteType(calleeReference.candidate)
replaceConeTypeOrNull(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, source, context.file.source)
return this
}
private fun FirResolvedTypeRef.substituteTypeRef(
private fun ConeKotlinType.substituteType(
candidate: Candidate,
): FirResolvedTypeRef {
): ConeKotlinType {
val initialType = candidate.substitutor.substituteOrSelf(type)
val substitutedType = finallySubstituteOrNull(initialType)
val finalType = typeApproximator.approximateToSuperType(
@@ -332,9 +316,7 @@ class FirCallCompletionResultsWriterTransformer(
//
// In FE1.0, it's not necessary since the annotation for elvis have some strange form (see org.jetbrains.kotlin.resolve.descriptorUtil.AnnotationsWithOnly)
// that is not propagated further.
val withRemovedExactAttribute = finalType?.removeExactAttribute()
return withReplacedConeType(withRemovedExactAttribute)
return finalType?.removeExactAttribute() ?: this
}
private fun ConeKotlinType.removeExactAttribute(): ConeKotlinType {
@@ -370,15 +352,16 @@ class FirCallCompletionResultsWriterTransformer(
val subCandidate = calleeReference.candidate
val typeArguments = computeTypeArguments(callableReferenceAccess, subCandidate)
val typeRef = callableReferenceAccess.typeRef as FirResolvedTypeRef
val initialType = calleeReference.candidate.substitutor.substituteOrSelf(typeRef.type)
val initialType = calleeReference.candidate.substitutor.substituteOrSelf(callableReferenceAccess.coneType)
val finalType = finallySubstituteOrSelf(initialType)
val resultType = typeRef.withReplacedConeType(finalType)
callableReferenceAccess.replaceTypeRef(resultType)
callableReferenceAccess.replaceConeTypeOrNull(finalType)
callableReferenceAccess.replaceTypeArguments(typeArguments)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, typeRef.source ?: callableReferenceAccess.source, context.file.source)
session.lookupTracker?.recordTypeResolveAsLookup(
finalType,
callableReferenceAccess.source ?: callableReferenceAccess.source,
context.file.source
)
val resolvedReference = when (calleeReference) {
is FirErrorReferenceWithCandidate -> calleeReference.toErrorReference(calleeReference.diagnostic)
@@ -413,9 +396,8 @@ class FirCallCompletionResultsWriterTransformer(
): FirStatement {
val originalType = qualifiedAccessExpression.coneType
val substitutedReceiverType = finallySubstituteOrNull(originalType) ?: return qualifiedAccessExpression
val resolvedTypeRef = qualifiedAccessExpression.typeRef.resolvedTypeFromPrototype(substitutedReceiverType)
qualifiedAccessExpression.replaceTypeRef(resolvedTypeRef)
session.lookupTracker?.recordTypeResolveAsLookup(resolvedTypeRef, qualifiedAccessExpression.source, context.file.source)
qualifiedAccessExpression.replaceConeTypeOrNull(substitutedReceiverType)
session.lookupTracker?.recordTypeResolveAsLookup(substitutedReceiverType, qualifiedAccessExpression.source, context.file.source)
return qualifiedAccessExpression
}
@@ -651,16 +633,15 @@ class FirCallCompletionResultsWriterTransformer(
override fun transformBlock(block: FirBlock, data: ExpectedArgumentType?): FirStatement {
val initialType = block.coneTypeSafe<ConeKotlinType>()
if (initialType != null) {
val finalType = finallySubstituteOrNull(initialType)
var resultType = block.resultType.withReplacedConeType(finalType)
resultType.coneTypeSafe<ConeIntegerLiteralType>()?.let {
resultType = resultType.resolvedTypeFromPrototype(it.getApproximatedType(data?.getExpectedType(block)?.fullyExpandedType(session)))
var resultType = finallySubstituteOrNull(initialType) ?: block.resultType
(resultType as? ConeIntegerLiteralType)?.let {
resultType = it.getApproximatedType(data?.getExpectedType(block)?.fullyExpandedType(session))
}
block.replaceTypeRef(resultType)
block.replaceConeTypeOrNull(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, block.source, context.file.source)
}
transformElement(block, data)
if (block.resultType is FirErrorTypeRef) {
if (block.resultType is ConeErrorType) {
block.writeResultType(session)
}
return block
@@ -709,7 +690,7 @@ class FirCallCompletionResultsWriterTransformer(
}
val typeRef = typeCalculator.tryCalculateReturnType(declaration)
syntheticCall.replaceTypeRefWithSubstituted(calleeReference, typeRef)
syntheticCall.replaceTypeWithSubstituted(calleeReference, typeRef)
transformSyntheticCallChildren(syntheticCall, data)
return syntheticCall.apply {
@@ -761,7 +742,7 @@ class FirCallCompletionResultsWriterTransformer(
}
override fun transformArrayLiteral(arrayLiteral: FirArrayLiteral, data: ExpectedArgumentType?): FirStatement {
if (arrayLiteral.typeRef !is FirImplicitTypeRef) return arrayLiteral
if (arrayLiteral.coneTypeOrNull != null) return arrayLiteral
val expectedArrayType = data?.getExpectedType(arrayLiteral)
val expectedArrayElementType = expectedArrayType?.arrayElementType()
arrayLiteral.transformChildren(this, expectedArrayElementType?.toExpectedType())
@@ -770,9 +751,8 @@ class FirCallCompletionResultsWriterTransformer(
typeApproximator.approximateToSuperType(it, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference)
?: it
} ?: expectedArrayElementType ?: session.builtinTypes.nullableAnyType.type
arrayLiteral.resultType = arrayLiteral.typeRef.resolvedTypeFromPrototype(
arrayLiteral.resultType =
arrayElementType.createArrayType(createPrimitiveArrayTypeIfPossible = expectedArrayType?.isPrimitiveArray == true)
)
return arrayLiteral
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
@@ -15,6 +15,9 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.lookupTracker
import org.jetbrains.kotlin.fir.recordTypeLookup
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.FirTypeResolutionResult
import org.jetbrains.kotlin.fir.resolve.SupertypeSupplier
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedDefaultValueInFunctionType
@@ -238,9 +241,7 @@ class FirSpecificTypeResolverTransformer(
override fun transformValueParameter(valueParameter: FirValueParameter, data: ScopeClassDeclaration): FirStatement {
val result = transformElement(valueParameter, data)
result.defaultValue?.let {
it.resultType = buildErrorTypeRef {
diagnostic = ConeUnsupportedDefaultValueInFunctionType(it.source)
}
it.resultType = ConeErrorType(ConeUnsupportedDefaultValueInFunctionType(it.source))
}
return result
}
@@ -192,7 +192,7 @@ class FirSyntheticCallGenerator(
source = arrayLiteral.source
}.also {
if (arrayOfSymbol == null) {
it.resultType = components.typeFromCallee(it)
it.resultType = components.typeFromCallee(it).type
}
}
}
@@ -242,7 +242,7 @@ class FirSyntheticCallGenerator(
// If the callable reference cannot be resolved with the expected type, let's try to resolve it with any type and report
// something like INITIALIZER_TYPE_MISMATCH or NONE_APPLICABLE instead of UNRESOLVED_REFERENCE.
check(callableReferenceAccess.calleeReference is FirSimpleNamedReference && callableReferenceAccess.typeRef is FirImplicitTypeRef) {
check(callableReferenceAccess.calleeReference is FirSimpleNamedReference && callableReferenceAccess.coneTypeOrNull == null) {
"Expected FirCallableReferenceAccess to be unresolved."
}
@@ -9,12 +9,18 @@ import org.jetbrains.kotlin.contracts.description.LogicOperationKind
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
import org.jetbrains.kotlin.fir.declarations.getSealedClassInheritors
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.enumWhenTracker
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.reportEnumUsageInWhen
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
@@ -217,8 +223,7 @@ private object WhenOnNullableExhaustivenessChecker : WhenExhaustivenessChecker()
private object ConditionChecker : AbstractConditionChecker<Flags>() {
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Flags) {
val argument = equalityOperatorCall.arguments[1]
@OptIn(UnexpandedTypeCheck::class)
if (argument.typeRef.isNullableNothing) {
if (argument.coneTypeOrNull?.isNullableNothing == true) {
data.containsNull = true
}
}
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.getFunctions
import org.jetbrains.kotlin.fir.scopes.impl.originalForWrappedIntegerOperator
@@ -64,7 +63,7 @@ class IntegerLiteralAndOperatorApproximationTransformer(
): FirStatement {
val type = constExpression.coneTypeSafe<ConeIntegerLiteralType>() ?: return constExpression
val approximatedType = type.getApproximatedType(data?.fullyExpandedType(session))
constExpression.resultType = constExpression.resultType.resolvedTypeFromPrototype(approximatedType)
constExpression.resultType = approximatedType
@Suppress("UNCHECKED_CAST")
val kind = approximatedType.toConstKind() as ConstantValueKind<T>
constExpression.replaceKind(kind)
@@ -83,7 +82,7 @@ class IntegerLiteralAndOperatorApproximationTransformer(
call.transformExtensionReceiver(this, null)
call.argumentList.transformArguments(this, null)
call.resultType = call.resultType.resolvedTypeFromPrototype(approximatedType)
call.resultType = approximatedType
val calleeReference = call.calleeReference
// callee reference may also be an error reference and it's ok if wrapped operator function leaks throw it
@@ -110,15 +109,15 @@ class IntegerLiteralAndOperatorApproximationTransformer(
if (approximatedType.isInt || approximatedType.isUInt) return call
val typeBeforeConversion = if (operatorType.isUnsigned) {
session.builtinTypes.uIntType
session.builtinTypes.uIntType.type
} else {
session.builtinTypes.intType
session.builtinTypes.intType.type
}
call.replaceTypeRef(typeBeforeConversion)
call.replaceConeTypeOrNull(typeBeforeConversion)
return buildFunctionCall {
source = call.source?.fakeElement(KtFakeSourceElementKind.IntToLongConversion)
typeRef = session.builtinTypes.longType
coneTypeOrNull = session.builtinTypes.longType.type
explicitReceiver = call
dispatchReceiver = call
this.calleeReference = buildResolvedNamedReference {
@@ -5,8 +5,10 @@
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
@@ -16,15 +18,14 @@ import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildVarargArgumentsExpression
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.ConstantValueKind
internal inline var FirExpression.resultType: FirTypeRef
get() = typeRef
internal inline var FirExpression.resultType: ConeKotlinType?
get() = coneTypeOrNull
set(type) {
replaceTypeRef(type)
replaceConeTypeOrNull(type)
}
internal fun remapArgumentsWithVararg(
@@ -43,7 +44,7 @@ internal fun remapArgumentsWithVararg(
val varargArgument = buildVarargArgumentsExpression {
// TODO: ideally we should use here a source from the use-site and not from the declaration-site, KT-59682
this.varargElementType = varargParameterTypeRef.withReplacedConeType(varargElementType, KtFakeSourceElementKind.VarargArgument)
this.typeRef = varargParameterTypeRef.withReplacedConeType(varargArrayType, KtFakeSourceElementKind.VarargArgument)
this.coneTypeOrNull = varargArrayType
var startOffset = Int.MAX_VALUE
var endOffset = 0
var firstVarargElementSource: KtSourceElement? = null
@@ -87,16 +88,9 @@ fun FirBlock.writeResultType(session: FirSession) {
else -> null
}
resultType = if (resultExpression == null) {
resultType.resolvedTypeFromPrototype(session.builtinTypes.unitType.type)
session.builtinTypes.unitType.type
} else {
val theType = resultExpression.resultType
if (theType is FirResolvedTypeRef) {
theType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
} else {
buildErrorTypeRef {
diagnostic = ConeSimpleDiagnostic("No type for block", DiagnosticKind.InferenceError)
}
}
resultExpression.resultType ?: ConeErrorType(ConeSimpleDiagnostic("No type for block", DiagnosticKind.InferenceError))
}
}
@@ -45,7 +45,7 @@ class FirArrayOfCallTransformer : FirDefaultTransformer<FirSession>() {
}
}
}
typeRef = functionCall.typeRef
coneTypeOrNull = functionCall.coneTypeOrNull
}
val calleeReference = functionCall.calleeReference
@@ -10,11 +10,13 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.calls.isUnitOrFlexibleUnit
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.transformWhenSubjectExpressionUsingSmartcastInfo
import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator
import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.resolve.withExpectedType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.transformSingle
@@ -54,7 +56,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
// ------------------------------- When expressions -------------------------------
override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ResolutionMode): FirStatement {
if (whenExpression.calleeReference is FirResolvedNamedReference && whenExpression.resultType !is FirImplicitTypeRef) {
if (whenExpression.calleeReference is FirResolvedNamedReference && whenExpression.resultType != null) {
return whenExpression
}
whenExpression.annotations.forEach { it.accept(this, data) }
@@ -114,7 +116,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
private fun FirWhenExpression.replaceReturnTypeIfNotExhaustive(): FirWhenExpression {
if (!isProperlyExhaustive) {
resultType = resultType.resolvedTypeFromPrototype(session.builtinTypes.unitType.type)
resultType = session.builtinTypes.unitType.type
}
return this
}
@@ -141,7 +143,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
data: ResolutionMode
): FirStatement {
val parentWhen = whenSubjectExpression.whenRef.value
val subjectType = parentWhen.subject?.resultType ?: parentWhen.subjectVariable?.returnTypeRef
val subjectType = parentWhen.subject?.resultType ?: parentWhen.subjectVariable?.returnTypeRef?.coneTypeOrNull
if (subjectType != null) {
whenSubjectExpression.resultType = subjectType
}
@@ -152,7 +154,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
// ------------------------------- Try/catch expressions -------------------------------
override fun transformTryExpression(tryExpression: FirTryExpression, data: ResolutionMode): FirStatement {
if (tryExpression.calleeReference is FirResolvedNamedReference && tryExpression.resultType !is FirImplicitTypeRef) {
if (tryExpression.calleeReference is FirResolvedNamedReference && tryExpression.resultType != null) {
return tryExpression
}
@@ -215,7 +217,6 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
data: ResolutionMode,
): FirStatement {
return throwExpression.apply {
replaceTypeRef(throwExpression.typeRef.transform(transformer, data))
transformAnnotations(transformer, data)
transformException(transformer, withExpectedType(session.builtinTypes.throwableType))
dataFlowAnalyzer.exitThrowExceptionNode(this)
@@ -268,7 +269,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
val newReturnType =
lhsType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
.convertToNonRawVersion()
result.replaceTypeRef(result.typeRef.resolvedTypeFromPrototype(newReturnType))
result.replaceConeTypeOrNull(newReturnType)
isLhsNotNull = true
}
}
@@ -279,8 +280,8 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
) {
// Sometimes return type for special call for elvis operator might be nullable,
// but result is not nullable if the right type is not nullable
result.replaceTypeRef(
result.typeRef.withReplacedConeType(result.coneType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext))
result.replaceConeTypeOrNull(
result.coneType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
)
}
}
@@ -228,29 +228,29 @@ open class FirDeclarationsResolveTransformer(
// get() = delegate.getValue(thisRef, kProperty: KProperty0/1/2<..., SomeType>)
// set() = delegate.getValue(thisRef, kProperty: KProperty0/1/2<..., SomeType>, value)
val propertyReferenceAccess = resolvedArgumentMapping?.keys?.toList()?.getOrNull(1) as? FirCallableReferenceAccess ?: return
val typeRef = propertyReferenceAccess.typeRef
if (typeRef is FirResolvedTypeRef && property.returnTypeRef is FirResolvedTypeRef) {
val typeArguments = (typeRef.type as ConeClassLikeType).typeArguments
val type = propertyReferenceAccess.coneTypeOrNull
if (type != null && property.returnTypeRef is FirResolvedTypeRef) {
val typeArguments = (type.type as ConeClassLikeType).typeArguments
val extensionType = property.receiverParameter?.typeRef?.coneType
val dispatchType = context.containingClass?.let { containingClass ->
containingClass.symbol.constructStarProjectedType(containingClass.typeParameters.size)
}
propertyReferenceAccess.replaceTypeRef(
buildResolvedTypeRef {
source = typeRef.source
annotations.addAll(typeRef.annotations)
type = (typeRef.type as ConeClassLikeType).lookupTag.constructClassType(
typeArguments.mapIndexed { index, argument ->
when (index) {
typeArguments.lastIndex -> property.returnTypeRef.coneType
0 -> extensionType ?: dispatchType
else -> dispatchType
} ?: argument
}.toTypedArray(),
isNullable = false
propertyReferenceAccess.replaceConeTypeOrNull(
(type.type as ConeClassLikeType).lookupTag.constructClassType(
typeArguments.mapIndexed { index, argument ->
when (index) {
typeArguments.lastIndex -> property.returnTypeRef.coneType
0 -> extensionType ?: dispatchType
else -> dispatchType
} ?: argument
}.toTypedArray(),
isNullable = false
).also {
session.lookupTracker?.recordTypeResolveAsLookup(
it,
propertyReferenceAccess.source ?: source,
components.file.source
)
}.also {
session.lookupTracker?.recordTypeResolveAsLookup(it, propertyReferenceAccess.source ?: source, components.file.source)
}
)
}
@@ -343,9 +343,9 @@ open class FirDeclarationsResolveTransformer(
val substitutor = createTypeSubstitutorByTypeConstructor(
typeVariableTypeToStubType, session.typeContext, approximateIntegerLiterals = true
)
val delegateExpressionTypeRef = delegateExpression.typeRef
val stubTypeSubstituted = substitutor.substituteOrNull(delegateExpressionTypeRef.coneType)
delegateExpression.replaceTypeRef(delegateExpressionTypeRef.withReplacedConeType(stubTypeSubstituted))
val delegateExpressionType = delegateExpression.coneType
val stubTypeSubstituted = substitutor.substituteOrNull(delegateExpressionType)
delegateExpression.replaceConeTypeOrNull(stubTypeSubstituted)
}
}
@@ -377,7 +377,7 @@ open class FirDeclarationsResolveTransformer(
)
)
provideDelegateCall.replaceTypeRef(provideDelegateCall.typeRef.resolvedTypeFromPrototype(stubTypeSubstituted))
provideDelegateCall.replaceConeTypeOrNull(stubTypeSubstituted)
return provideDelegateCall
}
@@ -643,19 +643,19 @@ open class FirDeclarationsResolveTransformer(
if (result.returnTypeRef is FirImplicitTypeRef) {
val simpleFunction = function as? FirSimpleFunction
val returnExpression = (body?.statements?.singleOrNull() as? FirReturnExpression)?.result
val returnTypeRef = if (returnExpression?.typeRef is FirResolvedTypeRef) {
returnExpression.resultType.approximateDeclarationType(
val expressionType = returnExpression?.coneTypeOrNull
val returnTypeRef = expressionType
?.toFirResolvedTypeRef(result.returnTypeRef.source)
?.approximateDeclarationType(
session,
simpleFunction?.visibilityForApproximation(),
isLocal = simpleFunction?.isLocal == true,
isInlineFunction = simpleFunction?.isInline == true
).copyWithNewSource(result.returnTypeRef.source)
} else {
buildErrorTypeRef {
)
?: buildErrorTypeRef {
source = result.returnTypeRef.source
diagnostic = ConeSimpleDiagnostic("empty body", DiagnosticKind.Other)
}
}
result.transformReturnTypeRef(transformer, withExpectedType(returnTypeRef))
}
@@ -982,7 +982,7 @@ open class FirDeclarationsResolveTransformer(
val inferredType = if (backingField is FirDefaultPropertyBackingField) {
propertyType
} else {
backingField.initializer?.unwrapSmartcastExpression()?.typeRef
backingField.initializer?.unwrapSmartcastExpression()?.coneTypeOrNull?.toFirResolvedTypeRef()
}
val resultType = inferredType
?: return backingField.transformReturnTypeRef(
@@ -1011,7 +1011,7 @@ open class FirDeclarationsResolveTransformer(
val resultType = when {
initializer != null -> {
val unwrappedInitializer = initializer.unwrapSmartcastExpression()
unwrappedInitializer.resultType
unwrappedInitializer.resultType?.toFirResolvedTypeRef()
}
variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> variable.getter?.returnTypeRef
else -> null
@@ -1094,10 +1094,10 @@ open class FirDeclarationsResolveTransformer(
private val FirVariable.initializerResolved: Boolean
get() {
val initializer = initializer ?: return false
return initializer.typeRef is FirResolvedTypeRef && initializer !is FirErrorExpression
return initializer.coneTypeOrNull != null && initializer !is FirErrorExpression
}
protected val FirFunction.bodyResolved: Boolean
get() = body !is FirLazyBlock && body?.typeRef is FirResolvedTypeRef
get() = body !is FirLazyBlock && body?.coneTypeOrNull != null
}
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperatorForUnsignedT
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.TransformData
@@ -68,15 +68,13 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
override fun transformExpression(expression: FirExpression, data: ResolutionMode): FirStatement {
if (expression.resultType is FirImplicitTypeRef && expression !is FirWrappedExpression) {
val type = buildErrorTypeRef {
source = expression.source
diagnostic = ConeSimpleDiagnostic(
if (expression.resultType == null && expression !is FirWrappedExpression) {
expression.resultType = ConeErrorType(
ConeSimpleDiagnostic(
"Type calculating for ${expression::class} is not supported",
DiagnosticKind.InferenceError
)
}
expression.resultType = type
)
}
return (expression.transformChildren(transformer, data) as FirStatement)
}
@@ -97,7 +95,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
data: ResolutionMode,
isUsedAsReceiver: Boolean,
): FirStatement {
if (qualifiedAccessExpression.typeRef is FirResolvedTypeRef && qualifiedAccessExpression.calleeReference !is FirSimpleNamedReference) {
if (qualifiedAccessExpression.coneTypeOrNull != null && qualifiedAccessExpression.calleeReference !is FirSimpleNamedReference) {
return qualifiedAccessExpression
}
@@ -115,21 +113,16 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
}
val implicitType = implicitReceiver?.originalType
qualifiedAccessExpression.resultType = when {
implicitReceiver is InaccessibleImplicitReceiverValue -> buildErrorTypeRef {
source = qualifiedAccessExpression.source
diagnostic = ConeInstanceAccessBeforeSuperCall("<this>")
}
implicitType != null -> implicitType.toFirResolvedTypeRef(callee.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef))
labelName != null -> buildErrorTypeRef {
source = qualifiedAccessExpression.source
diagnostic = ConeSimpleDiagnostic("Unresolved this@$labelName", DiagnosticKind.UnresolvedLabel)
}
else -> buildErrorTypeRef {
source = qualifiedAccessExpression.source
diagnostic = ConeSimpleDiagnostic("'this' is not defined in this context", DiagnosticKind.NoThis)
}
val resultType: ConeKotlinType = when {
implicitReceiver is InaccessibleImplicitReceiverValue -> ConeErrorType(ConeInstanceAccessBeforeSuperCall("<this>"))
implicitType != null -> implicitType
labelName != null -> ConeErrorType(ConeSimpleDiagnostic("Unresolved this@$labelName", DiagnosticKind.UnresolvedLabel))
else -> ConeErrorType(ConeSimpleDiagnostic("'this' is not defined in this context", DiagnosticKind.NoThis))
}
(resultType as? ConeErrorType)?.diagnostic?.let {
callee.replaceDiagnostic(it)
}
qualifiedAccessExpression.resultType = resultType
qualifiedAccessExpression
}
is FirSuperReference -> {
@@ -141,12 +134,12 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
is FirDelegateFieldReference -> {
val delegateFieldSymbol = callee.resolvedSymbol
qualifiedAccessExpression.resultType = delegateFieldSymbol.fir.delegate!!.typeRef
qualifiedAccessExpression.resultType = delegateFieldSymbol.fir.delegate!!.coneTypeOrNull
qualifiedAccessExpression
}
is FirResolvedNamedReference,
is FirErrorNamedReference -> {
if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) {
if (qualifiedAccessExpression.coneTypeOrNull == null) {
storeTypeFromCallee(qualifiedAccessExpression, isLhsOfAssignment = false)
}
qualifiedAccessExpression
@@ -271,7 +264,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
return markSuperReferenceError(diagnostic, superReferenceContainer, superReference)
}
superTypeRef is FirResolvedTypeRef -> {
superReferenceContainer.resultType = superTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.SuperCallExplicitType)
superReferenceContainer.resultType = superTypeRef.type
}
superTypeRef !is FirImplicitTypeRef -> {
components.typeResolverTransformer.withBareTypes {
@@ -302,8 +295,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
source = superTypeRef.source
diagnostic = ConeSimpleDiagnostic("Not a super type", DiagnosticKind.NotASupertype)
}
superReferenceContainer.resultType =
actualSuperTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.SuperCallExplicitType)
superReferenceContainer.resultType = actualSuperTypeRef.type
superReference.replaceSuperTypeRef(actualSuperTypeRef)
}
else -> {
@@ -320,8 +312,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
diagnostic = ConeAmbiguousSuper(types)
}
}
superReferenceContainer.resultType =
resultType.copyWithNewSourceKind(KtFakeSourceElementKind.SuperCallExplicitType)
superReferenceContainer.resultType = resultType.type
superReference.replaceSuperTypeRef(resultType)
}
}
@@ -336,7 +327,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val resultType = buildErrorTypeRef {
diagnostic = superNotAvailableDiagnostic
}
superReferenceContainer.resultType = resultType
superReferenceContainer.resultType = resultType.type
superReference.replaceSuperTypeRef(resultType)
superReferenceContainer.replaceCalleeReference(buildErrorNamedReference {
source = superReferenceContainer.source?.fakeElement(KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess)
@@ -404,7 +395,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val calleeReference = functionCall.calleeReference
if (
(calleeReference is FirResolvedNamedReference || calleeReference is FirErrorNamedReference) &&
functionCall.resultType is FirImplicitTypeRef
functionCall.resultType == null
) {
storeTypeFromCallee(functionCall, isLhsOfAssignment = false)
}
@@ -496,7 +487,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val integerOperatorCall = buildIntegerLiteralOperatorCall {
source = originalCall.source
typeRef = originalCall.typeRef.resolvedTypeFromPrototype(integerOperatorType)
coneTypeOrNull = integerOperatorType
annotations.addAll(originalCall.annotations)
typeArguments.addAll(originalCall.typeArguments)
calleeReference = originalCall.calleeReference
@@ -543,7 +534,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
block.transformOtherChildren(transformer, data)
if (data is ResolutionMode.WithExpectedType && data.expectedTypeRef.coneTypeSafe<ConeKotlinType>()?.isUnitOrFlexibleUnit == true) {
// Unit-coercion
block.resultType = data.expectedTypeRef
block.resultType = data.expectedTypeRef.type
} else {
// Bottom-up propagation: from the return type of the last expression in the block to the block type
block.writeResultType(session)
@@ -568,7 +559,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
data: ResolutionMode
): FirStatement = whileAnalysing(session, comparisonExpression) {
return (comparisonExpression.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirComparisonExpression).also {
it.resultType = comparisonExpression.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type)
it.resultType = builtinTypes.booleanType.type
dataFlowAnalyzer.exitComparisonExpressionCall(it)
}
}
@@ -729,7 +720,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
source = desugaredSource,
name = name,
initializer = initializer,
typeRef = initializer.typeRef.copyWithNewSource(desugaredSource),
typeRef = initializer.coneTypeOrNull?.toFirResolvedTypeRef(desugaredSource),
)
fun buildAndResolveOperatorCall(receiver: FirExpression): FirFunctionCall = buildFunctionCall {
@@ -786,7 +777,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
statements += unaryVariable.toQualifiedAccess()
}
}.apply {
replaceTypeRef((statements.last() as FirExpression).typeRef.copyWithNewSource(null))
replaceConeTypeOrNull((statements.last() as FirExpression).coneTypeOrNull)
}
return if (originalExpression is FirSafeCallExpression) {
@@ -813,7 +804,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
equalityOperatorCall
.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
.replaceArgumentList(buildBinaryArgumentList(leftArgumentTransformed, rightArgumentTransformed))
equalityOperatorCall.resultType = equalityOperatorCall.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type)
equalityOperatorCall.resultType = builtinTypes.booleanType.type
dataFlowAnalyzer.exitEqualityOperatorCall(equalityOperatorCall)
return equalityOperatorCall
@@ -887,22 +878,15 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
when (resolved.operation) {
FirOperation.IS, FirOperation.NOT_IS -> {
resolved.resultType = session.builtinTypes.booleanType
resolved.resultType = session.builtinTypes.booleanType.type
}
FirOperation.AS -> {
resolved.resultType = buildResolvedTypeRef {
source = conversionTypeRef.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
type = conversionTypeRef.coneType
annotations += conversionTypeRef.annotations
}
resolved.resultType = conversionTypeRef.coneType
}
FirOperation.SAFE_AS -> {
resolved.resultType =
conversionTypeRef.withReplacedConeType(
conversionTypeRef.coneType.withNullability(
ConeNullability.NULLABLE, session.typeContext,
),
)
resolved.resultType = conversionTypeRef.coneType.withNullability(
ConeNullability.NULLABLE, session.typeContext,
)
}
else -> error("Unknown type operator: ${resolved.operation}")
}
@@ -949,7 +933,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
// fun <K> checkNotNull(arg: K?): K
// ...in order to get the not-nullable type of the argument.
if (checkNotNullCall.calleeReference is FirResolvedNamedReference && checkNotNullCall.resultType !is FirImplicitTypeRef) {
if (checkNotNullCall.calleeReference is FirResolvedNamedReference && checkNotNullCall.resultType != null) {
return checkNotNullCall
}
@@ -970,7 +954,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
binaryLogicExpression: FirBinaryLogicExpression,
data: ResolutionMode,
): FirStatement = whileAnalysing(session, binaryLogicExpression) {
val booleanType = binaryLogicExpression.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type)
val booleanType = builtinTypes.booleanType.type.toFirResolvedTypeRef()
return binaryLogicExpression.also(dataFlowAnalyzer::enterBinaryLogicExpression)
.transformLeftOperand(this, ResolutionMode.WithExpectedType(booleanType))
.also(dataFlowAnalyzer::exitLeftBinaryLogicExpressionArgument)
@@ -978,25 +962,22 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
.transformRightOperand(this, ResolutionMode.WithExpectedType(booleanType))
.also(dataFlowAnalyzer::exitBinaryLogicExpression)
.transformOtherChildren(transformer, ResolutionMode.WithExpectedType(booleanType))
.also { it.resultType = booleanType }
.also { it.resultType = booleanType.type }
}
override fun transformDesugaredAssignmentValueReferenceExpression(
desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression,
data: ResolutionMode
data: ResolutionMode,
): FirStatement {
val referencedExpression = desugaredAssignmentValueReferenceExpression.expressionRef.value
if (referencedExpression is FirQualifiedAccessExpression) {
val typeFromCallee = components.typeFromCallee(referencedExpression)
desugaredAssignmentValueReferenceExpression.resultType = typeFromCallee.withReplacedConeType(
session.typeApproximator.approximateToSubType(
typeFromCallee.type,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
)
desugaredAssignmentValueReferenceExpression.resultType = session.typeApproximator.approximateToSubType(
typeFromCallee.type,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
) ?: typeFromCallee.type
} else {
desugaredAssignmentValueReferenceExpression.resultType =
referencedExpression.resultType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
desugaredAssignmentValueReferenceExpression.resultType = referencedExpression.resultType
}
return desugaredAssignmentValueReferenceExpression
}
@@ -1036,7 +1017,10 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val result = variableAssignment.transformRValue(
transformer,
withExpectedType(variableAssignment.lValue.typeRef, expectedTypeMismatchIsReportedInChecker = true),
withExpectedType(
variableAssignment.lValue.coneTypeOrNull?.toFirResolvedTypeRef() ?: FirImplicitTypeRefImplWithoutSource,
expectedTypeMismatchIsReportedInChecker = true
),
)
(result as? FirVariableAssignment)?.let { dataFlowAnalyzer.exitVariableAssignment(it) }
@@ -1089,7 +1073,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
getClassCall.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
val arg = getClassCall.argument
val dataForLhs = if (arg is FirConstExpression<*>) {
withExpectedType(arg.typeRef.resolvedTypeFromPrototype(arg.kind.expectedConeType(session)))
withExpectedType(arg.kind.expectedConeType(session).toFirResolvedTypeRef())
} else {
ResolutionMode.ContextIndependent
}
@@ -1124,14 +1108,14 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
ConeStarProjection
}
}
val coneType = symbol?.constructType(typeArguments, isNullable = false)
if (coneType != null) {
lhs.replaceTypeRef(
buildResolvedTypeRef { type = coneType }.also {
val type = symbol?.constructType(typeArguments, isNullable = false)
if (type != null) {
lhs.replaceConeTypeOrNull(
type.also {
session.lookupTracker?.recordTypeResolveAsLookup(it, getClassCall.source, components.file.source)
}
)
coneType
type
} else {
lhs.coneType
}
@@ -1143,18 +1127,15 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
else -> {
if (!shouldComputeTypeOfGetClassCallWithNotQualifierInLhs(getClassCall)) return transformedGetClassCall
val resultType = lhs.resultType
if (resultType is FirErrorTypeRef) {
resultType.coneType
if (resultType is ConeErrorType) {
resultType
} else {
ConeKotlinTypeProjectionOut(resultType.coneType)
ConeKotlinTypeProjectionOut(resultType!!)
}
}
}
transformedGetClassCall.resultType =
buildResolvedTypeRef {
type = StandardClassIds.KClass.constructClassLikeType(arrayOf(typeOfExpression), false)
}
transformedGetClassCall.resultType = StandardClassIds.KClass.constructClassLikeType(arrayOf(typeOfExpression), false)
dataFlowAnalyzer.exitGetClassCall(transformedGetClassCall)
return transformedGetClassCall
}
@@ -1206,7 +1187,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
dataFlowAnalyzer.exitConstExpression(constExpression as FirConstExpression<*>)
constExpression.resultType = constExpression.resultType.resolvedTypeFromPrototype(type)
constExpression.resultType = type
return when (val resolvedType = constExpression.coneType) {
is ConeErrorType -> buildErrorExpression {
@@ -1513,11 +1494,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
statements += indexVariables
statements += setCall
}.also {
it.replaceTypeRef(
buildResolvedTypeRef {
type = session.builtinTypes.unitType.type
}
)
it.replaceConeTypeOrNull(session.builtinTypes.unitType.type)
}
}
}
@@ -1537,7 +1514,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
source = lhsGetCall.explicitReceiver?.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment),
name = SpecialNames.ARRAY,
initializer = initializer,
typeRef = initializer.typeRef.copyWithNewSourceKind(KtFakeSourceElementKind.DesugaredCompoundAssignment),
typeRef = initializer.coneTypeOrNull?.toFirResolvedTypeRef(initializer.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)),
)
val indexVariables = lhsGetCall.arguments.flatMap {
@@ -1551,7 +1528,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
source = index.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment),
name = SpecialNames.subscribeOperatorIndex(i),
initializer = index,
typeRef = index.typeRef,
typeRef = index.coneTypeOrNull?.toFirResolvedTypeRef(),
)
}
@@ -1581,7 +1558,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
arguments += indicesQualifiedAccess.subList(i, i + varargSize)
i += varargSize
source = argument.source
typeRef = argument.typeRef
coneTypeOrNull = argument.coneTypeOrNull
varargElementType = argument.varargElementType
}
} else {
@@ -1590,7 +1567,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
}
}
origin = FirFunctionCallOrigin.Operator
typeRef = lhsGetCall.typeRef
coneTypeOrNull = lhsGetCall.coneTypeOrNull
}
val generator = GeneratorOfPlusAssignCalls(
@@ -1665,14 +1642,11 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
override fun transformAnonymousObjectExpression(
anonymousObjectExpression: FirAnonymousObjectExpression,
data: ResolutionMode
data: ResolutionMode,
): FirStatement {
anonymousObjectExpression.transformAnonymousObject(transformer, data)
if (anonymousObjectExpression.typeRef !is FirResolvedTypeRef) {
anonymousObjectExpression.resultType = buildResolvedTypeRef {
source = anonymousObjectExpression.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
this.type = anonymousObjectExpression.anonymousObject.defaultType()
}
if (anonymousObjectExpression.coneTypeOrNull == null) {
anonymousObjectExpression.resultType = anonymousObjectExpression.anonymousObject.defaultType()
}
dataFlowAnalyzer.exitAnonymousObjectExpression(anonymousObjectExpression)
return anonymousObjectExpression
@@ -1690,17 +1664,15 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
internal fun storeTypeFromCallee(access: FirQualifiedAccessExpression, isLhsOfAssignment: Boolean) {
val typeFromCallee = components.typeFromCallee(access)
access.resultType = typeFromCallee.withReplacedConeType(
if (isLhsOfAssignment) {
session.typeApproximator.approximateToSubType(
typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
} else {
session.typeApproximator.approximateToSuperType(
typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
}
)
access.resultType = if (isLhsOfAssignment) {
session.typeApproximator.approximateToSubType(
typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
} else {
session.typeApproximator.approximateToSuperType(
typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
} ?: typeFromCallee.type
}
}
@@ -156,7 +156,7 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
val resolvedContractCall = withContractModeDisabled {
contractDescription.contractCall
.transformSingle(transformer, ResolutionMode.ContextIndependent)
.apply { replaceTypeRef(session.builtinTypes.unitType) }
.apply { replaceConeTypeOrNull(session.builtinTypes.unitType.type) }
}
if (resolvedContractCall.toResolvedCallableSymbol()?.callableId != FirContractsDslNames.CONTRACT) {
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.fir.types.builder.buildStarProjection
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.builder.buildUserTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirQualifierPartImpl
import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
@@ -144,7 +143,7 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
source = receiver.source
packageFqName = symbol.classId.packageFqName
relativeClassFqName = symbol.classId.relativeClassName
typeRef = FirImplicitUnitTypeRef(receiver.typeRef.source)
coneTypeOrNull = session.builtinTypes.unitType.type
this.symbol = symbol
isFullyQualified = segments.isNotEmpty()
}
@@ -190,7 +189,7 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
calleeSymbol.containingClassLookupTag()
?.let { ConeClassLikeTypeImpl(it, emptyArray(), false) }
?.let { replaceTypeRef(typeRef.resolvedTypeFromPrototype(it)) }
?.let { replaceConeTypeOrNull(it) }
}
}
@@ -37,25 +37,25 @@ fun FirLookupTrackerComponent.recordTypeLookup(typeRef: FirTypeRef, inScopes: Li
fun FirLookupTrackerComponent.recordTypeResolveAsLookup(typeRef: FirTypeRef, source: KtSourceElement?, fileSource: KtSourceElement?) {
if (typeRef !is FirResolvedTypeRef) return // TODO: check if this is the correct behavior
if (source == null && fileSource == null) return // TODO: investigate all cases
recordTypeResolveAsLookup(typeRef.type, source, fileSource)
}
fun recordIfValid(type: ConeKotlinType) {
if (type is ConeErrorType) return // TODO: investigate whether some cases should be recorded, e.g. unresolved
type.classId?.let {
if (!it.isLocal) {
if (it.shortClassName.asString() != "Companion") {
recordLookup(it.shortClassName, it.packageFqName.asString(), source, fileSource)
} else {
recordLookup(it.outerClassId!!.shortClassName, it.outerClassId!!.packageFqName.asString(), source, fileSource)
}
fun FirLookupTrackerComponent.recordTypeResolveAsLookup(type: ConeKotlinType?, source: KtSourceElement?, fileSource: KtSourceElement?) {
if (type == null) return
if (source == null && fileSource == null) return // TODO: investigate all cases
if (type is ConeErrorType) return // TODO: investigate whether some cases should be recorded, e.g. unresolved
type.classId?.let {
if (!it.isLocal) {
if (it.shortClassName.asString() != "Companion") {
recordLookup(it.shortClassName, it.packageFqName.asString(), source, fileSource)
} else {
recordLookup(it.outerClassId!!.shortClassName, it.outerClassId!!.packageFqName.asString(), source, fileSource)
}
}
type.typeArguments.forEach {
if (it is ConeKotlinType) recordIfValid(it)
}
}
recordIfValid(typeRef.type)
type.typeArguments.forEach {
if (it is ConeKotlinType) recordTypeResolveAsLookup(it, source, fileSource)
}
}
@@ -16,13 +16,13 @@ import org.jetbrains.kotlin.fir.resolve.dfa.FlowPath
import org.jetbrains.kotlin.fir.resolve.dfa.PersistentFlow
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.UnexpandedTypeCheck
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.impl.FirImplicitNothingTypeRef
import org.jetbrains.kotlin.fir.types.constructClassLikeType
import org.jetbrains.kotlin.fir.types.isNothing
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.utils.SmartList
@RequiresOptIn
@@ -869,16 +869,14 @@ class WhenSubjectExpressionExitNode(owner: ControlFlowGraph, override val fir: F
object FirStub : FirExpression() {
override val source: KtSourceElement? get() = null
override val typeRef: FirTypeRef = FirImplicitNothingTypeRef(null)
override val coneTypeOrNull: ConeKotlinType = StandardClassIds.Nothing.constructClassLikeType()
override val annotations: List<FirAnnotation> get() = listOf()
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirExpression = this
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement = this
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) { assert(newAnnotations.isEmpty()) }
@OptIn(UnexpandedTypeCheck::class)
override fun replaceTypeRef(newTypeRef: FirTypeRef) { assert(newTypeRef.isNothing) }
override fun replaceConeTypeOrNull(newConeTypeOrNull: ConeKotlinType?) { assert(newConeTypeOrNull?.isNothing == true) }
}
class FakeExpressionEnterNode(owner: ControlFlowGraph, level: Int) : CFGNode<FirStub>(owner, level), GraphEnterNodeMarker, GraphExitNodeMarker {
@@ -69,7 +69,7 @@ fun FirRegularClassBuilder.generateValuesFunction(
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUES))
resolvePhase = this@generateValuesFunction.resolvePhase
body = buildEmptyExpressionBlock().also {
it.replaceType(returnTypeRef.type)
it.replaceConeTypeOrNull(returnTypeRef.type)
}
}.apply {
containingClassForStaticMemberAttr = this@generateValuesFunction.symbol.toLookupTag()
@@ -126,7 +126,7 @@ fun FirRegularClassBuilder.generateValueOfFunction(
}
resolvePhase = this@generateValueOfFunction.resolvePhase
body = buildEmptyExpressionBlock().also {
it.replaceType(returnTypeRef.type)
it.replaceConeTypeOrNull(returnTypeRef.type)
}
}.apply {
containingClassForStaticMemberAttr = this@generateValueOfFunction.symbol.toLookupTag()
@@ -24,20 +24,20 @@ fun <T> buildConstExpression(
return FirConstExpressionImpl(source, null, annotations.toMutableOrEmpty(), kind, value).also {
if (setType) {
when (kind) {
ConstantValueKind.Boolean -> it.type = StandardClassIds.Boolean.constructClassLikeType()
ConstantValueKind.Byte -> it.type = StandardClassIds.Byte.constructClassLikeType()
ConstantValueKind.Char -> it.type = StandardClassIds.Char.constructClassLikeType()
ConstantValueKind.Double -> it.type = StandardClassIds.Double.constructClassLikeType()
ConstantValueKind.Float -> it.type = StandardClassIds.Float.constructClassLikeType()
ConstantValueKind.Int -> it.type = StandardClassIds.Int.constructClassLikeType()
ConstantValueKind.Long -> it.type = StandardClassIds.Long.constructClassLikeType()
ConstantValueKind.Null -> it.type = StandardClassIds.Any.constructClassLikeType(isNullable = true)
ConstantValueKind.Short -> it.type = StandardClassIds.Short.constructClassLikeType()
ConstantValueKind.String -> it.type = StandardClassIds.String.constructClassLikeType()
ConstantValueKind.UnsignedByte -> it.type = StandardClassIds.UByte.constructClassLikeType()
ConstantValueKind.UnsignedInt -> it.type = StandardClassIds.UInt.constructClassLikeType()
ConstantValueKind.UnsignedLong -> it.type = StandardClassIds.ULong.constructClassLikeType()
ConstantValueKind.UnsignedShort -> it.type = StandardClassIds.UShort.constructClassLikeType()
ConstantValueKind.Boolean -> it.coneTypeOrNull = StandardClassIds.Boolean.constructClassLikeType()
ConstantValueKind.Byte -> it.coneTypeOrNull = StandardClassIds.Byte.constructClassLikeType()
ConstantValueKind.Char -> it.coneTypeOrNull = StandardClassIds.Char.constructClassLikeType()
ConstantValueKind.Double -> it.coneTypeOrNull = StandardClassIds.Double.constructClassLikeType()
ConstantValueKind.Float -> it.coneTypeOrNull = StandardClassIds.Float.constructClassLikeType()
ConstantValueKind.Int -> it.coneTypeOrNull = StandardClassIds.Int.constructClassLikeType()
ConstantValueKind.Long -> it.coneTypeOrNull = StandardClassIds.Long.constructClassLikeType()
ConstantValueKind.Null -> it.coneTypeOrNull = StandardClassIds.Any.constructClassLikeType(isNullable = true)
ConstantValueKind.Short -> it.coneTypeOrNull = StandardClassIds.Short.constructClassLikeType()
ConstantValueKind.String -> it.coneTypeOrNull = StandardClassIds.String.constructClassLikeType()
ConstantValueKind.UnsignedByte -> it.coneTypeOrNull = StandardClassIds.UByte.constructClassLikeType()
ConstantValueKind.UnsignedInt -> it.coneTypeOrNull = StandardClassIds.UInt.constructClassLikeType()
ConstantValueKind.UnsignedLong -> it.coneTypeOrNull = StandardClassIds.ULong.constructClassLikeType()
ConstantValueKind.UnsignedShort -> it.coneTypeOrNull = StandardClassIds.UShort.constructClassLikeType()
ConstantValueKind.IntegerLiteral,
ConstantValueKind.UnsignedIntegerLiteral,
ConstantValueKind.Error,
@@ -209,11 +209,6 @@ sealed class KtFakeSourceElementKind(final override val shouldSkipErrorTypeRepor
// where `Supertype` has a fake source
object SuperCallImplicitType : KtFakeSourceElementKind()
// Consider `super<Supertype>.foo()`. The source PSI `Supertype` is referenced by both the qualified access expression
// `super<Supertype>` and the calleeExpression `super<Supertype>`. To avoid having two FIR elements sharing the same source, this fake
// source is assigned to the qualified access expression.
object SuperCallExplicitType : KtFakeSourceElementKind(shouldSkipErrorTypeReporting = true)
// fun foo(vararg args: Int) {}
// fun bar(1, 2, 3) --> [resolved] fun bar(VarargArgument(1, 2, 3))
object VarargArgument : KtFakeSourceElementKind()
+1 -1
View File
@@ -17,7 +17,7 @@ class MyColor(val x: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>, y: Color.<!ENUM_ENTRY_A
class Local : Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>
fun local(arg: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>): Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> = arg
val temp: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> = Color.RED
temp as? Color.<!ENUM_ENTRY_AS_TYPE, ENUM_ENTRY_AS_TYPE!>RED<!>
temp as? Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>
if (temp is <!IS_ENUM_ENTRY!>Color.RED<!>) {
return temp as Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>
}
+1 -1
View File
@@ -1,7 +1,7 @@
fun <K> foo(x: K) {}
val x1 = foo<(<!UNRESOLVED_REFERENCE!>unresolved<!>) -> Float> { it.<!UNRESOLVED_REFERENCE!>toFloat<!>() }
val x2 = foo<(<!UNRESOLVED_REFERENCE!>unresolved<!>) -> Float> { <!CANNOT_INFER_PARAMETER_TYPE!>it<!> -> it.<!UNRESOLVED_REFERENCE!>toFloat<!>() }
val x3 = foo<<!UNRESOLVED_REFERENCE!>unresolved<!>.() -> Float> { this.<!UNRESOLVED_REFERENCE!>toFloat<!>() }
val x3 = foo<<!UNRESOLVED_REFERENCE!>unresolved<!>.() -> Float> { <!CANNOT_INFER_PARAMETER_TYPE!>this<!>.<!UNRESOLVED_REFERENCE!>toFloat<!>() }
val x4 = foo<(Array<<!UNRESOLVED_REFERENCE!>unresolved<!>>) -> Int> { it.size }
fun <T> bar() = foo<(T) -> String> { it.toString() }
@@ -40,7 +40,7 @@ open class A {
fun foo() {
<!UNRESOLVED_REFERENCE!>topLevelFun<!>()
<!UNRESOLVED_REFERENCE!>topLevelFun<!>(1)
<!UNRESOLVED_REFERENCE!>topLevelProperty<!><!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>++<!>
<!UNRESOLVED_REFERENCE!>topLevelProperty<!><!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>++<!>
"".<!UNRESOLVED_REFERENCE!>topLevelExtensionFun<!>()
1.<!UNRESOLVED_REFERENCE!>topLevelExtensionFun<!>()
"".<!UNRESOLVED_REFERENCE!>topLevelExtensionProperty<!>
@@ -75,3 +75,12 @@ fun test5() {
c.x<!UNSAFE_CALL!>.<!>length // bad
d.x.length // ok
}
fun test6() {
var c: C? = null
var maybeC: C? = C("")
if (c == null) {
c = maybeC ?: throw Exception()
}
c.x
}
@@ -75,3 +75,12 @@ fun test5() {
c.x<!UNSAFE_CALL!>.<!>length // bad
<!DEBUG_INFO_SMARTCAST!>d.x<!>.length // ok
}
fun test6() {
var c: C? = null
var maybeC: C? = C("")
if (c == null) {
c = maybeC ?: throw Exception()
}
<!DEBUG_INFO_SMARTCAST!>c<!>.x
}
@@ -25,7 +25,7 @@ fun <M> materialize(): Processor<M> = TODO()
private fun foo(model: Model) {
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER("M")!>materialize<!>().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER("T")!>apply<!> {
context(
this,
<!CANNOT_INFER_PARAMETER_TYPE!>this<!>,
Exec { m, p -> p.process(m) } // Note: Builder inference
)
}
@@ -47,7 +47,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
private fun Stack.push(
levelName: String,
defaultValues: MutableList<String> = mutableListOf()
defaultValues: MutableList<String> = mutableListOf(),
) = this.add(levelName to defaultValues)
private fun Stack.pop() = this.removeAt(this.size - 1)
@@ -164,7 +164,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
if (function.isLocal) stack.addName(function.name ?: ANONYMOUS_NAME)
stack.push((function.name ?: ANONYMOUS_NAME))
if (function.equalsToken != null) {
function.bodyExpression!!.firstOfTypeWithRender<FirReturnExpression>(function.equalsToken) { this.result.typeRef }
function.bodyExpression!!.firstOfTypeWithRender<FirReturnExpression>(function.equalsToken) { this.result.coneType.toFirResolvedTypeRef() }
?: function.firstOfTypeWithRender<FirCallableDeclaration>(function.equalsToken) { this.returnTypeRef }
}
super.visitNamedFunction(function)
@@ -249,12 +249,12 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
}
override fun visitIfExpression(expression: KtIfExpression) {
expression.firstOfTypeWithRender<FirWhenExpression> { this.typeRef }
expression.firstOfTypeWithRender<FirWhenExpression> { this.coneType.toFirResolvedTypeRef() }
super.visitIfExpression(expression)
}
override fun visitWhenExpression(expression: KtWhenExpression) {
expression.firstOfTypeWithRender<FirWhenExpression> { this.typeRef }
expression.firstOfTypeWithRender<FirWhenExpression> { this.coneType.toFirResolvedTypeRef() }
super.visitWhenExpression(expression)
}
@@ -306,7 +306,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
}
override fun visitWhenEntry(ktWhenEntry: KtWhenEntry) {
ktWhenEntry.firstOfTypeWithRender<FirWhenBranch>(ktWhenEntry.expression) { this.result.typeRef }
ktWhenEntry.firstOfTypeWithRender<FirWhenBranch>(ktWhenEntry.expression) { this.result.coneType.toFirResolvedTypeRef() }
super.visitWhenEntry(ktWhenEntry)
}
@@ -564,7 +564,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
fir.receiverParameter?.accept(this, data)
data.append(".").append(callableName)
}
call.dispatchReceiver.typeRef.annotations.any { it.isExtensionFunctionAnnotationCall } -> {
call.dispatchReceiver.coneType.isExtensionFunctionType -> {
withExtensionFunctionType = true
fir.valueParameters.first().returnTypeRef.accept(this, data)
data.append(".").append(callableName)
@@ -786,7 +786,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: StringBuilder) {
when (constExpression.kind) {
ConstantValueKind.String -> return
ConstantValueKind.Null -> constExpression.typeRef.accept(this, data)
ConstantValueKind.Null -> constExpression.coneType.tryToRenderConeAsFunctionType(data)
else -> data.append(constExpression.kind)
}
}
@@ -796,7 +796,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
when {
fir is FirRegularClass && fir.classKind != ClassKind.ENUM_CLASS && fir.companionObjectSymbol?.defaultType() == resolvedQualifier.coneTypeSafe() -> {
data.append("companion object ")
data.append(resolvedQualifier.typeRef.render()).append(": ")
data.append(resolvedQualifier.coneType.toFirResolvedTypeRef().render()).append(": ")
data.append(fir.symbol.classId.asString().removeCurrentFilePackage())
}
fir is FirClass -> {
@@ -54,7 +54,7 @@ class FirAssignmentPluginAssignAltererExtension(
source = variableAssignment.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
explicitReceiver = buildPropertyAccessExpression {
source = leftArgument.source
typeRef = leftResolvedType
coneTypeOrNull = leftResolvedType.type
calleeReference = leftArgument
(variableAssignment.lValue as? FirQualifiedAccessExpression)?.typeArguments?.let(typeArguments::addAll)
annotations += variableAssignment.annotations
@@ -71,4 +71,4 @@ class FirAssignmentPluginAssignAltererExtension(
origin = FirFunctionCallOrigin.Regular
}
}
}
}
@@ -57,7 +57,7 @@ class MembersOfSerializerGenerator(session: FirSession) : FirDeclarationGenerati
val function = createMemberFunction(owner, Key, callableId.callableName, session.builtinTypes.unitType.type) {
valueParameter(X_NAME, argumentClassId.createConeType(session))
}.apply {
replaceBody(buildBlock {}.apply { replaceTypeRef(session.builtinTypes.unitType) })
replaceBody(buildBlock {}.apply { replaceConeTypeOrNull(session.builtinTypes.unitType.type) })
}
return listOf(function.symbol)
}
@@ -26,8 +26,11 @@ import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.builder.buildUserTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeOrNull
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
import org.jetbrains.kotlin.fir.types.impl.FirQualifierPartImpl
import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl
import org.jetbrains.kotlin.fir.types.toFirResolvedTypeRef
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -148,12 +151,12 @@ class FirScriptConfiguratorExtensionImpl(
moduleData = session.moduleData
origin = FirDeclarationOrigin.ScriptCustomization.ResultProperty
initializer = lastExpression
returnTypeRef = lastExpression.typeRef
returnTypeRef = lastExpression.coneTypeOrNull?.toFirResolvedTypeRef() ?: FirImplicitTypeRefImplWithoutSource
getter = FirDefaultPropertyGetter(
lastExpression.source,
session.moduleData,
FirDeclarationOrigin.ScriptCustomization.ResultProperty,
lastExpression.typeRef,
lastExpression.coneTypeOrNull?.toFirResolvedTypeRef() ?: FirImplicitTypeRefImplWithoutSource,
Visibilities.Public,
this.symbol,
)