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