[FIR] Implement Int -> Long conversions for literals and operators over them
^KT-38895 ^KT-50996 Fixed ^KT-51000 Fixed ^KT-51003 Fixed ^KT-51018 Fixed
This commit is contained in:
committed by
teamcity
parent
cc86ca2a0f
commit
52b72a7dac
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithFakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.getOrBuildScopeForIntegerConstantOperatorType
|
||||
import org.jetbrains.kotlin.fir.scopes.scopeForClass
|
||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
@@ -90,7 +91,8 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope
|
||||
this
|
||||
)
|
||||
is ConeDefinitelyNotNullType -> original.scope(useSiteSession, scopeSession, requiredPhase)
|
||||
is ConeIntegerLiteralType -> error("ILT should not be in receiver position")
|
||||
is ConeIntegerConstantOperatorType -> scopeSession.getOrBuildScopeForIntegerConstantOperatorType(useSiteSession, this)
|
||||
is ConeIntegerLiteralConstantType -> error("ILT should not be in receiver position")
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
object ConvertibleIntegerOperators {
|
||||
val operatorsNames: Set<Name> = listOf(
|
||||
"plus", "minus", "times", "div", "rem",
|
||||
"and", "or", "xor",
|
||||
"shl", "shr", "ushr"
|
||||
).mapTo(mutableSetOf()) { Name.identifier(it) }
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.resolve.scopeSessionKey
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
class FirIntegerConstantOperatorScope(
|
||||
val session: FirSession,
|
||||
val scopeSession: ScopeSession,
|
||||
val isUnsigned: Boolean
|
||||
) : FirTypeScope() {
|
||||
private val baseScope: FirTypeScope = run {
|
||||
val baseType = when (isUnsigned) {
|
||||
true -> session.builtinTypes.uIntType
|
||||
false -> session.builtinTypes.intType
|
||||
}.type
|
||||
baseType.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing) ?: error("Scope for $baseType not found")
|
||||
}
|
||||
|
||||
private val mappedFunctions = mutableMapOf<Name, FirNamedFunctionSymbol>()
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||
if (name !in ConvertibleIntegerOperators.operatorsNames) {
|
||||
return baseScope.processFunctionsByName(name, processor)
|
||||
}
|
||||
val wrappedSymbol = mappedFunctions.getOrPut(name) {
|
||||
val allFunctions = baseScope.getFunctions(name)
|
||||
val functionSymbol = allFunctions.first {
|
||||
val coneType = it.fir.valueParameters.first().returnTypeRef.coneType
|
||||
if (isUnsigned) {
|
||||
coneType.isUInt
|
||||
} else {
|
||||
coneType.isInt
|
||||
}
|
||||
}
|
||||
wrapIntOperator(functionSymbol)
|
||||
}
|
||||
processor(wrappedSymbol)
|
||||
baseScope.processFunctionsByName(name, processor)
|
||||
}
|
||||
|
||||
private fun wrapIntOperator(originalSymbol: FirNamedFunctionSymbol): FirNamedFunctionSymbol {
|
||||
val originalFunction = originalSymbol.fir
|
||||
val wrappedFunction = buildSimpleFunctionCopy(originalFunction) {
|
||||
symbol = FirNamedFunctionSymbol(originalSymbol.callableId)
|
||||
origin = FirDeclarationOrigin.WrappedIntegerOperator
|
||||
returnTypeRef = buildResolvedTypeRef {
|
||||
type = ConeIntegerConstantOperatorTypeImpl(isUnsigned, ConeNullability.NOT_NULL)
|
||||
}
|
||||
|
||||
}.also {
|
||||
it.originalForWrappedIntegerOperator = originalSymbol
|
||||
it.isUnsignedWrappedIntegerOperator = isUnsigned
|
||||
}
|
||||
return wrappedFunction.symbol
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||
baseScope.processPropertiesByName(name, processor)
|
||||
}
|
||||
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
baseScope.processDeclaredConstructors(processor)
|
||||
}
|
||||
|
||||
override fun mayContainName(name: Name): Boolean {
|
||||
return baseScope.mayContainName(name)
|
||||
}
|
||||
|
||||
override fun getCallableNames(): Set<Name> {
|
||||
return baseScope.getCallableNames()
|
||||
}
|
||||
|
||||
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
||||
// Int types don't have nested classifiers
|
||||
}
|
||||
|
||||
override fun getClassifierNames(): Set<Name> {
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
override fun processDirectOverriddenFunctionsWithBaseScope(
|
||||
functionSymbol: FirNamedFunctionSymbol,
|
||||
processor: (FirNamedFunctionSymbol, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction {
|
||||
return ProcessorAction.NONE
|
||||
}
|
||||
|
||||
override fun processDirectOverriddenPropertiesWithBaseScope(
|
||||
propertySymbol: FirPropertySymbol,
|
||||
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction {
|
||||
return ProcessorAction.NONE
|
||||
}
|
||||
}
|
||||
|
||||
fun ScopeSession.getOrBuildScopeForIntegerConstantOperatorType(
|
||||
session: FirSession,
|
||||
type: ConeIntegerConstantOperatorType
|
||||
): FirIntegerConstantOperatorScope {
|
||||
return getOrBuild(type.isUnsigned, INTEGER_CONSTANT_OPERATOR_SCOPE) {
|
||||
FirIntegerConstantOperatorScope(session, this, type.isUnsigned)
|
||||
}
|
||||
}
|
||||
|
||||
private val INTEGER_CONSTANT_OPERATOR_SCOPE = scopeSessionKey<Boolean, FirIntegerConstantOperatorScope>()
|
||||
|
||||
private object OriginalForWrappedIntegerOperator : FirDeclarationDataKey()
|
||||
private object IsUnsignedForWrappedIntegerOperator : FirDeclarationDataKey()
|
||||
|
||||
var FirSimpleFunction.originalForWrappedIntegerOperator: FirNamedFunctionSymbol? by FirDeclarationDataRegistry.data(
|
||||
OriginalForWrappedIntegerOperator
|
||||
)
|
||||
|
||||
private var FirSimpleFunction.isUnsignedWrappedIntegerOperator: Boolean? by FirDeclarationDataRegistry.data(
|
||||
IsUnsignedForWrappedIntegerOperator
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun FirDeclaration.isWrappedIntegerOperator(): Boolean {
|
||||
contract {
|
||||
returns(true) implies (this@isWrappedIntegerOperator is FirSimpleFunction)
|
||||
}
|
||||
return (this as? FirSimpleFunction)?.originalForWrappedIntegerOperator != null
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun FirBasedSymbol<*>.isWrappedIntegerOperator(): Boolean {
|
||||
contract {
|
||||
returns(true) implies (this@isWrappedIntegerOperator is FirNamedFunctionSymbol)
|
||||
}
|
||||
return fir.isWrappedIntegerOperator()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun FirBasedSymbol<*>.isWrappedIntegerOperatorForUnsignedType(): Boolean {
|
||||
return (this as? FirNamedFunctionSymbol)?.fir?.isUnsignedWrappedIntegerOperator ?: false
|
||||
}
|
||||
@@ -43,6 +43,14 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
||||
return this is ConeIntegerLiteralType
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isIntegerLiteralConstantTypeConstructor(): Boolean {
|
||||
return this is ConeIntegerLiteralConstantType
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isIntegerConstantOperatorTypeConstructor(): Boolean {
|
||||
return this is ConeIntegerConstantOperatorType
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isLocalType(): Boolean {
|
||||
if (this !is ConeClassLikeLookupTag) return false
|
||||
return classId.isLocal
|
||||
|
||||
Reference in New Issue
Block a user