[FIR] Get rid of FirIntegerLiteralTypeScope and corresponding stuff
This commit is contained in:
@@ -22,17 +22,13 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.isIteratorNext
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -60,12 +56,6 @@ class Fir2IrVisitor(
|
||||
|
||||
private val annotationGenerator = AnnotationGenerator(this)
|
||||
|
||||
private val integerApproximator = IntegerLiteralTypeApproximationTransformer(
|
||||
session.firSymbolProvider,
|
||||
session.typeContext,
|
||||
session
|
||||
)
|
||||
|
||||
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope)
|
||||
|
||||
private val operatorGenerator = OperatorExpressionGenerator(components, this, conversionScope)
|
||||
@@ -342,12 +332,7 @@ class Fir2IrVisitor(
|
||||
}
|
||||
|
||||
override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrExpression {
|
||||
val convertibleCall = if (functionCall.toResolvedCallableSymbol()?.fir is FirIntegerOperator) {
|
||||
functionCall.copy().transformSingle(integerApproximator, null)
|
||||
} else {
|
||||
functionCall
|
||||
}
|
||||
return convertToIrCall(functionCall = convertibleCall, annotationMode = false)
|
||||
return convertToIrCall(functionCall = functionCall, annotationMode = false)
|
||||
}
|
||||
|
||||
override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Any?): IrElement {
|
||||
|
||||
@@ -157,14 +157,6 @@ class FirCallResolver(
|
||||
bestCandidates, discriminateGenerics = true, discriminateAbstracts = onSuperReference
|
||||
)
|
||||
}
|
||||
if ((reducedCandidates.isEmpty() || !result.currentApplicability.isSuccess) &&
|
||||
explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
) {
|
||||
val approximatedQualifiedAccess = qualifiedAccess.transformExplicitReceiver(components.integerLiteralTypeApproximator, null)
|
||||
if (approximatedQualifiedAccess.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() == null) {
|
||||
return collectCandidates(approximatedQualifiedAccess, name)
|
||||
}
|
||||
}
|
||||
|
||||
return ResolutionResult(info, result.currentApplicability, reducedCandidates)
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerOperatorsTypeUpdater
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
@@ -54,8 +52,6 @@ abstract class BodyResolveComponents : SessionHolder {
|
||||
abstract val doubleColonExpressionResolver: FirDoubleColonExpressionResolver
|
||||
abstract val syntheticCallGenerator: FirSyntheticCallGenerator
|
||||
abstract val dataFlowAnalyzer: FirDataFlowAnalyzer<*>
|
||||
abstract val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer
|
||||
abstract val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater
|
||||
abstract val outerClassManager: FirOuterClassManager
|
||||
}
|
||||
|
||||
|
||||
+1
-8
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||
import org.jetbrains.kotlin.fir.declarations.expandedConeType
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -41,10 +40,7 @@ sealed class DoubleColonLHS(val type: ConeKotlinType) {
|
||||
internal val FirFunctionCall.hasExplicitValueArguments: Boolean
|
||||
get() = true // TODO: hasExplicitArgumentList || hasExplicitLambdaArguments
|
||||
|
||||
class FirDoubleColonExpressionResolver(
|
||||
private val session: FirSession,
|
||||
private val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer
|
||||
) {
|
||||
class FirDoubleColonExpressionResolver(private val session: FirSession) {
|
||||
|
||||
// Returns true if the expression is not a call expression without value arguments (such as "A<B>") or a qualified expression
|
||||
// which contains such call expression as one of its parts.
|
||||
@@ -80,9 +76,6 @@ class FirDoubleColonExpressionResolver(
|
||||
}
|
||||
|
||||
internal fun resolveDoubleColonLHS(doubleColonExpression: FirCallableReferenceAccess): DoubleColonLHS? {
|
||||
if (doubleColonExpression.explicitReceiver is FirConstExpression<*>) {
|
||||
doubleColonExpression.transformExplicitReceiver(integerLiteralTypeApproximator, null)
|
||||
}
|
||||
val resultForExpr = tryResolveLHS(doubleColonExpression, this::shouldTryResolveLHSAsExpression, this::resolveExpressionOnLHS)
|
||||
if (resultForExpr != null && !resultForExpr.isObjectQualifier) {
|
||||
return resultForExpr
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerLiteralTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
|
||||
import org.jetbrains.kotlin.fir.scopes.scope
|
||||
@@ -56,18 +55,7 @@ fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession)
|
||||
}
|
||||
)
|
||||
is ConeDefinitelyNotNullType -> original.scope(useSiteSession, scopeSession)
|
||||
is ConeIntegerLiteralType -> {
|
||||
@Suppress("USELESS_CAST") // TODO: remove once fixed: https://youtrack.jetbrains.com/issue/KT-35635
|
||||
scopeSession.getOrBuild(
|
||||
when {
|
||||
isUnsigned -> FirIntegerLiteralTypeScope.ILTKey.Unsigned
|
||||
else -> FirIntegerLiteralTypeScope.ILTKey.Signed
|
||||
},
|
||||
FirIntegerLiteralTypeScope.SCOPE_SESSION_KEY
|
||||
) {
|
||||
FirIntegerLiteralTypeScope(useSiteSession, isUnsigned)
|
||||
} as FirTypeScope
|
||||
}
|
||||
is ConeIntegerLiteralType -> error("ILT should not be in receiver position")
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclaration
|
||||
import org.jetbrains.kotlin.fir.returnExpressions
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirILTTypeRefPlaceHolder
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -185,11 +182,7 @@ fun Candidate.resolveSubCallArgument(
|
||||
* It's important to extract type from argument neither from symbol, because of symbol contains
|
||||
* placeholder type with value 0, but argument contains type with proper literal value
|
||||
*/
|
||||
val type: ConeKotlinType = if (candidate.symbol.fir is FirIntegerOperator) {
|
||||
(argument as FirFunctionCall).resultType.coneType
|
||||
} else {
|
||||
context.returnTypeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe()).type
|
||||
}
|
||||
val type: ConeKotlinType = context.returnTypeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe()).type
|
||||
val argumentType = candidate.substitutor.substituteOrSelf(type)
|
||||
resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, context, isReceiver, isDispatch, useNullableArgumentType)
|
||||
}
|
||||
@@ -207,14 +200,6 @@ fun Candidate.resolvePlainExpressionArgument(
|
||||
if (expectedType == null) return
|
||||
val argumentType = argument.typeRef.coneTypeSafe<ConeKotlinType>() ?: return
|
||||
resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, context, isReceiver, isDispatch, useNullableArgumentType)
|
||||
checkApplicabilityForIntegerOperatorCall(sink, argument)
|
||||
}
|
||||
|
||||
private fun Candidate.checkApplicabilityForIntegerOperatorCall(sink: CheckerSink, argument: FirExpression) {
|
||||
if (symbol.fir !is FirIntegerOperator) return
|
||||
if (argument !is FirConstExpression<*> && argument !is FirIntegerOperatorCall) {
|
||||
sink.reportDiagnostic(InapplicableCandidate)
|
||||
}
|
||||
}
|
||||
|
||||
fun Candidate.resolvePlainArgumentType(
|
||||
@@ -346,9 +331,6 @@ private fun Candidate.prepareExpectedType(
|
||||
context: ResolutionContext
|
||||
): ConeKotlinType? {
|
||||
if (parameter == null) return null
|
||||
val parameterReturnTypeRef = parameter.returnTypeRef
|
||||
if (parameterReturnTypeRef is FirILTTypeRefPlaceHolder && argument.resultType is FirResolvedTypeRef)
|
||||
return argument.resultType.coneType.takeIf { it in parameterReturnTypeRef.type.possibleTypes } ?: session.builtinTypes.intType.type
|
||||
val basicExpectedType = argument.getExpectedType(session, parameter/*, LanguageVersionSettings*/)
|
||||
val expectedType = getExpectedTypeWithSAMConversion(session, argument, basicExpectedType, context) ?: basicExpectedType
|
||||
return this.substitutor.substituteOrSelf(expectedType)
|
||||
|
||||
+1
-8
@@ -233,13 +233,6 @@ internal open class FirTowerResolveTask(
|
||||
explicitReceiverValue.toMemberScopeTowerLevel(), info, parentGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
|
||||
val shouldProcessExplicitReceiverScopeOnly =
|
||||
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
if (shouldProcessExplicitReceiverScopeOnly) {
|
||||
// Special case (integer literal type)
|
||||
return
|
||||
}
|
||||
|
||||
enumerateTowerLevels(
|
||||
parentGroup = parentGroup,
|
||||
onScope = { scope, group ->
|
||||
@@ -412,4 +405,4 @@ internal open class FirTowerResolveTask(
|
||||
parentGroup.TopPrioritized(index).let { if (depth != null) it.Implicit(depth) else it },
|
||||
explicitReceiverKind,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+13
-14
@@ -72,17 +72,21 @@ class FirCallCompleter(
|
||||
return when (completionMode) {
|
||||
ConstraintSystemCompletionMode.FULL -> {
|
||||
if (inferenceSession.shouldRunCompletion(call)) {
|
||||
completer.complete(candidate.system.asConstraintSystemCompleterContext(), completionMode, listOf(call), initialType, transformer.resolutionContext) {
|
||||
completer.complete(
|
||||
candidate.system.asConstraintSystemCompleterContext(),
|
||||
completionMode,
|
||||
listOf(call),
|
||||
initialType,
|
||||
transformer.resolutionContext
|
||||
) {
|
||||
analyzer.analyze(candidate.system.asPostponedArgumentsAnalyzerContext(), it, candidate)
|
||||
}
|
||||
val finalSubstitutor =
|
||||
candidate.system.asReadOnlyStorage().buildAbstractResultingSubstitutor(session.inferenceComponents.ctx) as ConeSubstitutor
|
||||
val finalSubstitutor = candidate.system.asReadOnlyStorage()
|
||||
.buildAbstractResultingSubstitutor(session.inferenceComponents.ctx) as ConeSubstitutor
|
||||
val completedCall = call.transformSingle(
|
||||
FirCallCompletionResultsWriterTransformer(
|
||||
session, finalSubstitutor, components.returnTypeCalculator,
|
||||
session.inferenceComponents.approximator,
|
||||
components.integerOperatorsTypeUpdater,
|
||||
components.integerLiteralTypeApproximator
|
||||
session.inferenceComponents.approximator
|
||||
),
|
||||
null
|
||||
)
|
||||
@@ -104,9 +108,8 @@ class FirCallCompleter(
|
||||
) {
|
||||
analyzer.analyze(candidate.system.asPostponedArgumentsAnalyzerContext(), it, candidate)
|
||||
}
|
||||
val approximatedCall = call.transformSingle(components.integerOperatorsTypeUpdater, null)
|
||||
inferenceSession.addPartiallyResolvedCall(approximatedCall)
|
||||
CompletionResult(approximatedCall, false)
|
||||
inferenceSession.addPartiallyResolvedCall(call)
|
||||
CompletionResult(call, false)
|
||||
}
|
||||
|
||||
ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA -> throw IllegalStateException()
|
||||
@@ -120,8 +123,6 @@ class FirCallCompleter(
|
||||
return FirCallCompletionResultsWriterTransformer(
|
||||
session, substitutor, components.returnTypeCalculator,
|
||||
session.inferenceComponents.approximator,
|
||||
components.integerOperatorsTypeUpdater,
|
||||
components.integerLiteralTypeApproximator,
|
||||
mode
|
||||
)
|
||||
}
|
||||
@@ -189,9 +190,7 @@ class FirCallCompleter(
|
||||
FirBuilderInferenceSession(transformer.resolutionContext, stubsForPostponedVariables as Map<ConeTypeVariable, ConeStubType>)
|
||||
}
|
||||
|
||||
val localContext = components.towerDataContextForAnonymousFunctions.get(lambdaArgument.symbol) ?: error(
|
||||
""
|
||||
)
|
||||
val localContext = components.towerDataContextForAnonymousFunctions[lambdaArgument.symbol] ?: error("")
|
||||
transformer.context.withTowerDataContext(localContext) {
|
||||
if (builderInferenceSession != null) {
|
||||
transformer.context.withInferenceSession(builderInferenceSession) {
|
||||
|
||||
+5
-22
@@ -48,8 +48,6 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
private val finalSubstitutor: ConeSubstitutor,
|
||||
private val typeCalculator: ReturnTypeCalculator,
|
||||
private val typeApproximator: AbstractTypeApproximator,
|
||||
private val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater,
|
||||
private val integerApproximator: IntegerLiteralTypeApproximationTransformer,
|
||||
private val mode: Mode = Mode.Normal
|
||||
) : FirAbstractTreeTransformer<ExpectedArgumentType?>(phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
|
||||
|
||||
@@ -105,14 +103,8 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
val updatedQualifiedAccess = if (qualifiedAccessExpression is FirFunctionCall) {
|
||||
qualifiedAccessExpression.transformSingle(integerOperatorsTypeUpdater, null)
|
||||
} else {
|
||||
qualifiedAccessExpression
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val result = updatedQualifiedAccess
|
||||
val result = qualifiedAccessExpression
|
||||
.transformCalleeReference(
|
||||
StoreCalleeReference,
|
||||
calleeReference.toResolvedReference(),
|
||||
@@ -137,7 +129,6 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
qualifiedAccessExpression.compose()
|
||||
}
|
||||
val result = prepareQualifiedTransform(qualifiedAccessExpression, calleeReference)
|
||||
.transformExplicitReceiver(integerApproximator, null)
|
||||
val typeRef = result.typeRef as FirResolvedTypeRef
|
||||
val subCandidate = calleeReference.candidate
|
||||
|
||||
@@ -154,13 +145,6 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
return result.compose()
|
||||
}
|
||||
|
||||
override fun transformCheckedSafeCallSubject(
|
||||
checkedSafeCallSubject: FirCheckedSafeCallSubject,
|
||||
data: ExpectedArgumentType?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return checkedSafeCallSubject.transform(integerApproximator, data?.getExpectedType(checkedSafeCallSubject))
|
||||
}
|
||||
|
||||
override fun transformFunctionCall(functionCall: FirFunctionCall, data: ExpectedArgumentType?): CompositeTransformResult<FirStatement> {
|
||||
val calleeReference = functionCall.calleeReference as? FirNamedReferenceWithCandidate
|
||||
?: return functionCall.compose()
|
||||
@@ -174,7 +158,7 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
resultType =
|
||||
typeRef.resolvedTypeFromPrototype(typeRef.coneTypeUnsafe<ConeIntegerLiteralType>().getApproximatedType(expectedType))
|
||||
result.argumentList.transformArguments(this, expectedType?.toExpectedType())
|
||||
result.transformSingle(integerApproximator, expectedType)
|
||||
result
|
||||
}
|
||||
else -> {
|
||||
resultType = typeRef.substituteTypeRef(subCandidate)
|
||||
@@ -186,7 +170,7 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
result.replaceArgumentList(buildResolvedArgumentList(it))
|
||||
}
|
||||
}
|
||||
result.transformExplicitReceiver(integerApproximator, null)
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +309,7 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
return variableAssignment.transformCalleeReference(
|
||||
StoreCalleeReference,
|
||||
calleeReference.toResolvedReference(),
|
||||
).transformExplicitReceiver(integerApproximator, null).apply {
|
||||
).apply {
|
||||
replaceTypeArguments(typeArguments)
|
||||
}.compose()
|
||||
}
|
||||
@@ -565,8 +549,7 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
data: ExpectedArgumentType?,
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
if (data == ExpectedArgumentType.NoApproximation) return constExpression.compose()
|
||||
val expectedType = data?.getExpectedType(constExpression)
|
||||
return constExpression.transform(integerApproximator, expectedType)
|
||||
return constExpression.approximateIfIsIntegerConst(data?.getExpectedType(constExpression)).compose()
|
||||
}
|
||||
|
||||
override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: ExpectedArgumentType?): CompositeTransformResult<FirStatement> {
|
||||
|
||||
+13
-226
@@ -6,36 +6,26 @@
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.propagateTypeFromOriginalReceiver
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstKind
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.types.toConstKind
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
|
||||
class IntegerLiteralTypeApproximationTransformer(
|
||||
private val symbolProvider: FirSymbolProvider,
|
||||
private val inferenceContext: ConeInferenceContext,
|
||||
private val session: FirSession
|
||||
) : FirTransformer<ConeKotlinType?>() {
|
||||
fun FirExpression.approximateIfIsIntegerConst(expectedType: ConeKotlinType? = null): FirExpression {
|
||||
return transformSingle(IntegerLiteralTypeApproximationTransformer, expectedType)
|
||||
}
|
||||
|
||||
private object IntegerLiteralTypeApproximationTransformer : FirTransformer<ConeKotlinType?>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: ConeKotlinType?): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
@@ -52,207 +42,4 @@ class IntegerLiteralTypeApproximationTransformer(
|
||||
constExpression.replaceKind(kind)
|
||||
return constExpression.compose()
|
||||
}
|
||||
|
||||
override fun transformFunctionCall(functionCall: FirFunctionCall, data: ConeKotlinType?): CompositeTransformResult<FirStatement> {
|
||||
val operator = functionCall.toResolvedCallableSymbol()?.fir as? FirIntegerOperator
|
||||
if (operator == null) {
|
||||
if (functionCall is FirIntegerOperatorCall) {
|
||||
// functionCall _was_ a named call whose candidate symbol was an integer operator, but has been transformed to an integer
|
||||
// operator call (by [IntegerOperatorsTypeUpdater]). So, technically, this _was_ a call that this transformer was looking
|
||||
// for, i.e., a call with ILT, but in a resolved form already. Here we just adapt to the expected type if any.
|
||||
//
|
||||
// Note that such inequality can happen to the resolved call, since the call completer doesn't complete the call with the
|
||||
// given, expected type: see [FirCallCompleter#completeCall]. One reason _not_ to propagate the expected type to the call
|
||||
// completing transformation is to handle integer overflow naturally. E.g., if a property with Long, a bigger type, is
|
||||
// intentionally set with an integer operator that overflows, knowing the expected type will hide the overflow. Rather, we
|
||||
// have a second chance here to sort of wrap such overflowed integer with type conversion, like `n.toLong()`.
|
||||
data?.let {
|
||||
functionCall.resultType = functionCall.resultType.resolvedTypeFromPrototype(it)
|
||||
}
|
||||
}
|
||||
return functionCall.compose()
|
||||
}
|
||||
functionCall.transformChildren(this, data)
|
||||
val argumentType = functionCall.arguments.firstOrNull()?.resultType?.coneTypeUnsafe<ConeClassLikeType>()
|
||||
val receiverClassId = functionCall.dispatchReceiver.typeRef.coneTypeUnsafe<ConeClassLikeType>().lookupTag.classId
|
||||
val scope = declaredMemberScope((symbolProvider.getClassLikeSymbolByFqName(receiverClassId) as FirRegularClassSymbol).fir)
|
||||
var resultSymbol: FirFunctionSymbol<*>? = null
|
||||
scope.processFunctionsByName(operator.name) { symbol ->
|
||||
if (resultSymbol != null) {
|
||||
return@processFunctionsByName
|
||||
}
|
||||
if (operator.kind.unary) {
|
||||
resultSymbol = symbol
|
||||
return@processFunctionsByName
|
||||
}
|
||||
val function = symbol.fir
|
||||
val valueParameterType = function.valueParameters.first().returnTypeRef.coneTypeUnsafe<ConeClassLikeType>()
|
||||
if (AbstractTypeChecker.isSubtypeOf(inferenceContext, argumentType!!, valueParameterType)) {
|
||||
resultSymbol = symbol
|
||||
return@processFunctionsByName
|
||||
}
|
||||
}
|
||||
// TODO: Maybe resultType = data?
|
||||
// check black box tests
|
||||
// e.g. Byte doesn't have `and` in member scope. It's an extension. See also: FirBlackBoxCodegenTestGenerated.testIntrinsics
|
||||
if (resultSymbol == null) return functionCall.compose()
|
||||
functionCall.resultType = data?.let { functionCall.resultType.resolvedTypeFromPrototype(it) } ?: resultSymbol!!.fir.returnTypeRef
|
||||
// If the original call has argument mapping, values in that mapping refer to value parameters in that original symbol. We should
|
||||
// map those original value parameters back to indices, and then renew the argument mapping with new value parameters in the result
|
||||
// symbol. Otherwise, while putting the value argument to the converted IR call, it will encounter an unknown value parameter,
|
||||
// resulting in an out-of-bound error.
|
||||
val newArgumentMapping =
|
||||
functionCall.argumentMapping?.mapValues { (_, oldValueParameter) ->
|
||||
val index = operator.valueParameters.indexOf(oldValueParameter)
|
||||
if (index != -1) resultSymbol!!.fir.valueParameters[index] else oldValueParameter
|
||||
}
|
||||
return functionCall.transformCalleeReference(
|
||||
StoreCalleeReference,
|
||||
buildResolvedNamedReference {
|
||||
name = operator.name
|
||||
resolvedSymbol = resultSymbol!!
|
||||
}
|
||||
).apply {
|
||||
newArgumentMapping?.let {
|
||||
replaceArgumentList(buildResolvedArgumentList(it))
|
||||
}
|
||||
}.compose()
|
||||
}
|
||||
|
||||
// TODO: call outside
|
||||
override fun transformTypeOperatorCall(
|
||||
typeOperatorCall: FirTypeOperatorCall,
|
||||
data: ConeKotlinType?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
typeOperatorCall.argumentList.transformArguments(this, null)
|
||||
return typeOperatorCall.compose()
|
||||
}
|
||||
|
||||
override fun transformEqualityOperatorCall(
|
||||
equalityOperatorCall: FirEqualityOperatorCall,
|
||||
data: ConeKotlinType?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
val leftArgument = equalityOperatorCall.arguments[0]
|
||||
val rightArgument = equalityOperatorCall.arguments[1]
|
||||
|
||||
val leftIsIlt = leftArgument.typeRef.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
val rightIsIlt = rightArgument.typeRef.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
|
||||
val expectedType: ConeKotlinType? = when {
|
||||
!leftIsIlt && !rightIsIlt -> return equalityOperatorCall.compose()
|
||||
leftIsIlt && rightIsIlt -> null
|
||||
leftIsIlt -> rightArgument.typeRef.coneType
|
||||
rightIsIlt -> leftArgument.typeRef.coneType
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
|
||||
equalityOperatorCall.argumentList.transformArguments(this, expectedType)
|
||||
return equalityOperatorCall.compose()
|
||||
}
|
||||
|
||||
override fun transformCheckedSafeCallSubject(
|
||||
checkedSafeCallSubject: FirCheckedSafeCallSubject,
|
||||
data: ConeKotlinType?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
val newReceiver =
|
||||
checkedSafeCallSubject.originalReceiverRef.value.transform<FirExpression, ConeKotlinType?>(this, data).single
|
||||
checkedSafeCallSubject.propagateTypeFromOriginalReceiver(newReceiver, session)
|
||||
return super.transformCheckedSafeCallSubject(checkedSafeCallSubject, data)
|
||||
}
|
||||
}
|
||||
|
||||
fun FirFunctionCall.getOriginalFunction(): FirCallableDeclaration<*>? {
|
||||
val symbol: AbstractFirBasedSymbol<*>? = when (val reference = calleeReference) {
|
||||
is FirResolvedNamedReference -> reference.resolvedSymbol
|
||||
is FirNamedReferenceWithCandidate -> reference.candidateSymbol
|
||||
else -> null
|
||||
}
|
||||
return symbol?.fir as? FirCallableDeclaration<*>
|
||||
}
|
||||
|
||||
class IntegerOperatorsTypeUpdater(private val approximator: IntegerLiteralTypeApproximationTransformer) : FirTransformer<Nothing?>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
|
||||
override fun transformFunctionCall(functionCall: FirFunctionCall, data: Nothing?): CompositeTransformResult<FirStatement> {
|
||||
val function: FirCallableDeclaration<*> = functionCall.getOriginalFunction() ?: return functionCall.compose()
|
||||
|
||||
if (function !is FirIntegerOperator) {
|
||||
val expectedType = function.receiverTypeRef?.coneType
|
||||
return functionCall.transformExplicitReceiver(approximator, expectedType).compose()
|
||||
}
|
||||
// TODO: maybe unsafe?
|
||||
val receiverType = functionCall.explicitReceiver!!.typeRef.coneTypeSafe<ConeIntegerLiteralType>() ?: return functionCall.compose()
|
||||
val receiverValue = receiverType.value
|
||||
val kind = function.kind
|
||||
val resultValue = when {
|
||||
kind.unary -> when (kind) {
|
||||
FirIntegerOperator.Kind.UNARY_PLUS -> receiverValue
|
||||
FirIntegerOperator.Kind.UNARY_MINUS -> -receiverValue
|
||||
FirIntegerOperator.Kind.INV -> receiverValue.inv()
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
else -> {
|
||||
// TODO: handle overflow
|
||||
when (val argumentType = functionCall.argument.typeRef.coneType) {
|
||||
is ConeIntegerLiteralType -> {
|
||||
val argumentValue = argumentType.value
|
||||
val divisionByZero = argumentValue == 0L
|
||||
when (kind) {
|
||||
FirIntegerOperator.Kind.PLUS -> receiverValue + argumentValue
|
||||
FirIntegerOperator.Kind.MINUS -> receiverValue - argumentValue
|
||||
FirIntegerOperator.Kind.TIMES -> receiverValue * argumentValue
|
||||
// TODO: maybe add some error reporting (e.g. in userdata)
|
||||
FirIntegerOperator.Kind.DIV -> if (divisionByZero) receiverValue else receiverValue / argumentValue
|
||||
FirIntegerOperator.Kind.REM -> if (divisionByZero) receiverValue else receiverValue % argumentValue
|
||||
// TODO: check that argument can be int
|
||||
FirIntegerOperator.Kind.SHL -> receiverValue shl argumentValue.toInt()
|
||||
FirIntegerOperator.Kind.SHR -> receiverValue shr argumentValue.toInt()
|
||||
FirIntegerOperator.Kind.USHR -> receiverValue ushr argumentValue.toInt()
|
||||
FirIntegerOperator.Kind.XOR -> receiverValue xor argumentValue
|
||||
FirIntegerOperator.Kind.AND -> receiverValue and argumentValue
|
||||
FirIntegerOperator.Kind.OR -> receiverValue or argumentValue
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val expectedType = when (argumentType.classId) {
|
||||
StandardClassIds.Long,
|
||||
StandardClassIds.Float,
|
||||
StandardClassIds.Double -> argumentType
|
||||
else -> ConeIntegerLiteralTypeImpl.createType(StandardClassIds.Int)
|
||||
}
|
||||
functionCall.transformSingle(approximator, expectedType)
|
||||
functionCall.replaceTypeRef(functionCall.resultType.resolvedTypeFromPrototype(expectedType))
|
||||
return functionCall.compose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val newTypeRef = functionCall.resultType.resolvedTypeFromPrototype(
|
||||
ConeIntegerLiteralTypeImpl(
|
||||
resultValue,
|
||||
isUnsigned = receiverType.isUnsigned
|
||||
)
|
||||
)
|
||||
functionCall.replaceTypeRef(newTypeRef)
|
||||
return functionCall.toOperatorCall().compose()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(FirImplementationDetail::class)
|
||||
private fun FirFunctionCall.toOperatorCall(): FirIntegerOperatorCall {
|
||||
if (this is FirIntegerOperatorCall) return this
|
||||
return FirIntegerOperatorCall(
|
||||
source,
|
||||
typeRef,
|
||||
annotations.toMutableList(),
|
||||
typeArguments.toMutableList(),
|
||||
explicitReceiver,
|
||||
dispatchReceiver,
|
||||
extensionReceiver,
|
||||
argumentList,
|
||||
calleeReference,
|
||||
)
|
||||
}
|
||||
|
||||
+5
-8
@@ -20,7 +20,10 @@ import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirAbstractPhaseTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSpecificTypeResolverTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
@@ -88,8 +91,6 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
|
||||
protected inline val dataFlowAnalyzer: FirDataFlowAnalyzer<*> get() = components.dataFlowAnalyzer
|
||||
protected inline val scopeSession: ScopeSession get() = components.scopeSession
|
||||
protected inline val file: FirFile get() = components.file
|
||||
protected inline val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer get() = components.integerLiteralTypeApproximator
|
||||
protected inline val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater get() = components.integerOperatorsTypeUpdater
|
||||
|
||||
val ResolutionMode.expectedType: FirTypeRef?
|
||||
get() = when (this) {
|
||||
@@ -134,11 +135,7 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
|
||||
override val dataFlowAnalyzer: FirDataFlowAnalyzer<*> =
|
||||
FirDataFlowAnalyzer.createFirDataFlowAnalyzer(this, context.dataFlowAnalyzerContext)
|
||||
override val syntheticCallGenerator: FirSyntheticCallGenerator = FirSyntheticCallGenerator(this)
|
||||
override val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer =
|
||||
IntegerLiteralTypeApproximationTransformer(symbolProvider, session.inferenceComponents.ctx, session)
|
||||
override val doubleColonExpressionResolver: FirDoubleColonExpressionResolver =
|
||||
FirDoubleColonExpressionResolver(session, integerLiteralTypeApproximator)
|
||||
override val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater = IntegerOperatorsTypeUpdater(integerLiteralTypeApproximator)
|
||||
override val doubleColonExpressionResolver: FirDoubleColonExpressionResolver = FirDoubleColonExpressionResolver(session)
|
||||
override val outerClassManager: FirOuterClassManager = FirOuterClassManager(session, context.outerLocalClassForNested)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildArrayOfCall
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.getOriginalFunction
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.types.isArrayType
|
||||
|
||||
/**
|
||||
@@ -64,3 +66,12 @@ internal class FirArrayOfCallTransformer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirFunctionCall.getOriginalFunction(): FirCallableDeclaration<*>? {
|
||||
val symbol: AbstractFirBasedSymbol<*>? = when (val reference = calleeReference) {
|
||||
is FirResolvedNamedReference -> reference.resolvedSymbol
|
||||
is FirNamedReferenceWithCandidate -> reference.candidateSymbol
|
||||
else -> null
|
||||
}
|
||||
return symbol?.fir as? FirCallableDeclaration<*>
|
||||
}
|
||||
|
||||
+1
-5
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransf
|
||||
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
@@ -191,10 +190,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
|
||||
} else {
|
||||
ResolutionMode.ContextIndependent
|
||||
}
|
||||
var result = transformer.transformExpression(jump, mode).single
|
||||
if (result is FirReturnExpression) {
|
||||
result = result.transformResult(integerLiteralTypeApproximator, expectedTypeRef!!.coneTypeSafe())
|
||||
}
|
||||
val result = transformer.transformExpression(jump, mode).single
|
||||
dataFlowAnalyzer.exitJump(jump)
|
||||
return result.compose()
|
||||
}
|
||||
|
||||
+4
-10
@@ -138,7 +138,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
withLocalScopeCleanup {
|
||||
addLocalScope(context.getPrimaryConstructorParametersScope())
|
||||
property.transformChildrenWithoutAccessors(returnTypeRef)
|
||||
property.transformInitializer(integerLiteralTypeApproximator, property.returnTypeRef.coneTypeSafe())
|
||||
}
|
||||
if (property.initializer != null) {
|
||||
storeVariableReturnType(property)
|
||||
@@ -253,7 +252,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
(delegateProvider as? FirFunctionCall)?.let { dataFlowAnalyzer.dropSubgraphFromCall(it) }
|
||||
return wrappedDelegateExpression.expression
|
||||
.transformSingle(transformer, ResolutionMode.ContextDependent)
|
||||
.transform(integerLiteralTypeApproximator, null)
|
||||
.approximateIfIsIntegerConst()
|
||||
.compose()
|
||||
} finally {
|
||||
dataFlowAnalyzer.exitDelegateExpression()
|
||||
}
|
||||
@@ -269,7 +269,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
.transformDelegate(transformer, resolutionMode)
|
||||
.transformTypeParameters(transformer, resolutionMode)
|
||||
.transformOtherChildren(transformer, resolutionMode)
|
||||
.transformInitializer(integerLiteralTypeApproximator, null)
|
||||
if (variable.initializer != null) {
|
||||
storeVariableReturnType(variable)
|
||||
}
|
||||
@@ -650,12 +649,9 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
}
|
||||
|
||||
dataFlowAnalyzer.enterValueParameter(valueParameter)
|
||||
val transformedValueParameter =
|
||||
valueParameter.transformInitializer(integerLiteralTypeApproximator, valueParameter.returnTypeRef.coneType)
|
||||
|
||||
val result = transformDeclarationContent(
|
||||
transformedValueParameter,
|
||||
withExpectedType(transformedValueParameter.returnTypeRef)
|
||||
valueParameter,
|
||||
withExpectedType(valueParameter.returnTypeRef)
|
||||
).single as FirValueParameter
|
||||
|
||||
dataFlowAnalyzer.exitValueParameter(result)?.let { graph ->
|
||||
@@ -752,8 +748,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
ConeSubstitutor.Empty,
|
||||
components.returnTypeCalculator,
|
||||
inferenceComponents.approximator,
|
||||
integerOperatorsTypeUpdater,
|
||||
integerLiteralTypeApproximator
|
||||
)
|
||||
lambda.transformSingle(writer, expectedTypeRef.coneTypeSafe<ConeKotlinType>()?.toExpectedType())
|
||||
val returnTypes = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(lambda)
|
||||
|
||||
+3
-14
@@ -309,14 +309,6 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
transformer.onBeforeStatementResolution(block.statements[index])
|
||||
TransformData.Data(value)
|
||||
}
|
||||
if (data == ResolutionMode.ContextIndependent) {
|
||||
block.transformStatements(integerLiteralTypeApproximator, null)
|
||||
} else {
|
||||
block.transformAllStatementsExceptLast(
|
||||
integerLiteralTypeApproximator,
|
||||
null
|
||||
)
|
||||
}
|
||||
block.transformOtherChildren(transformer, data)
|
||||
block.writeResultType(session)
|
||||
|
||||
@@ -336,8 +328,8 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return (comparisonExpression.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirComparisonExpression).also {
|
||||
it.resultType = comparisonExpression.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type)
|
||||
}.transformSingle(integerLiteralTypeApproximator, null)
|
||||
.also(dataFlowAnalyzer::exitComparisonExpressionCall).compose()
|
||||
dataFlowAnalyzer.exitComparisonExpressionCall(it)
|
||||
}.compose()
|
||||
}
|
||||
|
||||
override fun transformAssignmentOperatorStatement(
|
||||
@@ -429,7 +421,6 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
val result = (equalityOperatorCall.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirEqualityOperatorCall)
|
||||
.also { it.resultType = equalityOperatorCall.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type) }
|
||||
.transformSingle(integerLiteralTypeApproximator, null)
|
||||
dataFlowAnalyzer.exitEqualityOperatorCall(result)
|
||||
return result.compose()
|
||||
}
|
||||
@@ -481,7 +472,6 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
val resolved = components.typeResolverTransformer.withAllowedBareTypes {
|
||||
typeOperatorCall.transformConversionTypeRef(transformer, ResolutionMode.ContextIndependent)
|
||||
}.transformOtherChildren(transformer, ResolutionMode.ContextIndependent)
|
||||
resolved.argumentList.transformArguments(integerLiteralTypeApproximator, null)
|
||||
|
||||
val conversionTypeRef = resolved.conversionTypeRef.withTypeArgumentsForBareType(resolved.argument)
|
||||
resolved.transformChildren(object : FirDefaultTransformer<Nothing?>() {
|
||||
@@ -520,7 +510,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
else -> error("Unknown type operator: ${resolved.operation}")
|
||||
}
|
||||
dataFlowAnalyzer.exitTypeOperatorCall(resolved)
|
||||
return resolved.transform(integerLiteralTypeApproximator, null)
|
||||
return resolved.compose()
|
||||
}
|
||||
|
||||
override fun transformCheckNotNullCall(
|
||||
@@ -587,7 +577,6 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType).result // TODO: check
|
||||
val expectedType = components.typeFromCallee(completeAssignment)
|
||||
completeAssignment.transformRValue(transformer, withExpectedType(expectedType))
|
||||
.transformRValue(integerLiteralTypeApproximator, expectedType.coneTypeSafe())
|
||||
} else {
|
||||
// This can happen in erroneous code only
|
||||
resolvedAssignment
|
||||
|
||||
-192
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.resolve.scopeSessionKey
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class FirIntegerLiteralTypeScope(private val session: FirSession, val isUnsigned: Boolean) : FirTypeScope() {
|
||||
sealed class ILTKey {
|
||||
object Signed : ILTKey()
|
||||
object Unsigned : ILTKey()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val BINARY_OPERATOR_NAMES = FirIntegerOperator.Kind.values().filterNot { it.unary }.map { it.operatorName }
|
||||
val FLOATING_BINARY_OPERATOR_NAMES = FirIntegerOperator.Kind.values().filter { it.withFloatingRhs }.map { it.operatorName }
|
||||
val UNARY_OPERATOR_NAMES = FirIntegerOperator.Kind.values().filter { it.unary }.map { it.operatorName }
|
||||
private val ALL_OPERATORS = FirIntegerOperator.Kind.values().map { it.operatorName to it }.toMap()
|
||||
|
||||
val SCOPE_SESSION_KEY = scopeSessionKey<ILTKey, FirTypeScope>()
|
||||
}
|
||||
|
||||
@Suppress("PrivatePropertyName")
|
||||
private val BINARY_OPERATOR_SYMBOLS = BINARY_OPERATOR_NAMES.map { name ->
|
||||
name to FirNamedFunctionSymbol(CallableId(name)).apply {
|
||||
createFirFunction(name, this).apply {
|
||||
valueParameters += createValueParameter(FirILTTypeRefPlaceHolder(isUnsigned))
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
|
||||
private val FLOATING_BINARY_OPERATOR_SYMBOLS = FLOATING_BINARY_OPERATOR_NAMES.map { name ->
|
||||
name to listOf(session.builtinTypes.floatType, session.builtinTypes.doubleType).map { typeRef ->
|
||||
FirNamedFunctionSymbol(CallableId(name)).apply {
|
||||
createFirFunction(name, this, typeRef).apply {
|
||||
valueParameters += createValueParameter(typeRef)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
|
||||
@Suppress("PrivatePropertyName")
|
||||
private val UNARY_OPERATOR_SYMBOLS = UNARY_OPERATOR_NAMES.map { name ->
|
||||
name to FirNamedFunctionSymbol(CallableId(name)).apply { createFirFunction(name, this) }
|
||||
}.toMap()
|
||||
|
||||
@OptIn(FirImplementationDetail::class)
|
||||
private fun createFirFunction(
|
||||
name: Name,
|
||||
symbol: FirNamedFunctionSymbol,
|
||||
returnTypeRef: FirResolvedTypeRef = FirILTTypeRefPlaceHolder(isUnsigned)
|
||||
): FirSimpleFunctionImpl = FirIntegerOperator(
|
||||
source = null,
|
||||
session,
|
||||
returnTypeRef,
|
||||
receiverTypeRef = null,
|
||||
ALL_OPERATORS.getValue(name),
|
||||
FirResolvedDeclarationStatusImpl(Visibilities.Public, Modality.FINAL),
|
||||
symbol
|
||||
).apply {
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
}
|
||||
|
||||
private fun createValueParameter(returnTypeRef: FirResolvedTypeRef): FirValueParameter {
|
||||
return buildValueParameter {
|
||||
source = null
|
||||
origin = FirDeclarationOrigin.Synthetic
|
||||
session = this@FirIntegerLiteralTypeScope.session
|
||||
this.returnTypeRef = returnTypeRef
|
||||
name = Name.identifier("arg")
|
||||
symbol = FirVariableSymbol(name)
|
||||
defaultValue = null
|
||||
isCrossinline = false
|
||||
isNoinline = false
|
||||
isVararg = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) {
|
||||
UNARY_OPERATOR_SYMBOLS[name]?.let {
|
||||
processor(it)
|
||||
return
|
||||
}
|
||||
val symbol = BINARY_OPERATOR_SYMBOLS[name] ?: return
|
||||
processor(symbol)
|
||||
FLOATING_BINARY_OPERATOR_SYMBOLS[name]?.forEach(processor)
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||
}
|
||||
|
||||
override fun processDirectOverriddenFunctionsWithBaseScope(
|
||||
functionSymbol: FirFunctionSymbol<*>,
|
||||
processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction = ProcessorAction.NEXT
|
||||
|
||||
override fun processDirectOverriddenPropertiesWithBaseScope(
|
||||
propertySymbol: FirPropertySymbol,
|
||||
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction = ProcessorAction.NEXT
|
||||
|
||||
override fun getCallableNames(): Set<Name> = ALL_OPERATORS.keys
|
||||
|
||||
override fun getClassifierNames(): Set<Name> = emptySet()
|
||||
}
|
||||
|
||||
@OptIn(FirImplementationDetail::class)
|
||||
class FirIntegerOperator @FirImplementationDetail constructor(
|
||||
source: FirSourceElement?,
|
||||
session: FirSession,
|
||||
returnTypeRef: FirTypeRef,
|
||||
receiverTypeRef: FirTypeRef?,
|
||||
val kind: Kind,
|
||||
status: FirDeclarationStatus,
|
||||
symbol: FirFunctionSymbol<FirSimpleFunction>
|
||||
) : FirSimpleFunctionImpl(
|
||||
source,
|
||||
session,
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE,
|
||||
FirDeclarationOrigin.Synthetic,
|
||||
returnTypeRef,
|
||||
receiverTypeRef,
|
||||
valueParameters = mutableListOf(),
|
||||
body = null,
|
||||
status,
|
||||
containerSource = null,
|
||||
contractDescription = FirEmptyContractDescription,
|
||||
kind.operatorName,
|
||||
symbol,
|
||||
annotations = mutableListOf(),
|
||||
typeParameters = mutableListOf(),
|
||||
) {
|
||||
enum class Kind(val operatorName: Name, val unary: Boolean, val withFloatingRhs: Boolean) {
|
||||
PLUS(OperatorNameConventions.PLUS, unary = false, withFloatingRhs = true),
|
||||
MINUS(OperatorNameConventions.MINUS, unary = false, withFloatingRhs = true),
|
||||
TIMES(OperatorNameConventions.TIMES, unary = false, withFloatingRhs = true),
|
||||
DIV(OperatorNameConventions.DIV, unary = false, withFloatingRhs = true),
|
||||
REM(OperatorNameConventions.REM, unary = false, withFloatingRhs = true),
|
||||
SHL(Name.identifier("shl"), unary = false, withFloatingRhs = false),
|
||||
SHR(Name.identifier("shr"), unary = false, withFloatingRhs = false),
|
||||
USHR(Name.identifier("ushr"), unary = false, withFloatingRhs = false),
|
||||
XOR(Name.identifier("xor"), unary = false, withFloatingRhs = false),
|
||||
AND(Name.identifier("and"), unary = false, withFloatingRhs = false),
|
||||
OR(Name.identifier("or"), unary = false, withFloatingRhs = false),
|
||||
UNARY_PLUS(OperatorNameConventions.UNARY_PLUS, unary = true, withFloatingRhs = false),
|
||||
UNARY_MINUS(OperatorNameConventions.UNARY_MINUS, unary = true, withFloatingRhs = false),
|
||||
INV(Name.identifier("inv"), unary = true, withFloatingRhs = false),
|
||||
}
|
||||
}
|
||||
|
||||
class FirILTTypeRefPlaceHolder(isUnsigned: Boolean) : FirResolvedTypeRef() {
|
||||
override val source: FirSourceElement? get() = null
|
||||
override val annotations: List<FirAnnotationCall> get() = emptyList()
|
||||
override var type: ConeIntegerLiteralType = ConeIntegerLiteralTypeImpl(0, isUnsigned)
|
||||
override val delegatedTypeRef: FirTypeRef? get() = null
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirResolvedTypeRef {
|
||||
return this
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user