[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:
Dmitriy Novozhilov
2022-01-25 12:41:04 +03:00
committed by teamcity
parent cc86ca2a0f
commit 52b72a7dac
98 changed files with 1318 additions and 232 deletions
@@ -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
}
}
@@ -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) }
}
@@ -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