FIR: support resolving to objects

This commit is contained in:
Simon Ogorodnik
2019-04-09 20:21:47 +03:00
committed by Mikhail Glukhikh
parent b38f3a1272
commit c6aff9380b
21 changed files with 160 additions and 61 deletions
@@ -187,24 +187,35 @@ abstract class TowerDataConsumer {
kind: TowerDataKind,
implicitReceiverType: ConeKotlinType?,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector
resultCollector: CandidateCollector,
group: Int
): ProcessorAction
}
fun createVariableConsumer(
fun createVariableAndObjectConsumer(
session: FirSession,
name: Name,
callInfo: CallInfo,
inferenceComponents: InferenceComponents
): TowerDataConsumer {
return createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Properties,
callInfo,
inferenceComponents
return PrioritizedTowerDataConsumer(
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Properties,
callInfo,
inferenceComponents
),
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Objects,
callInfo,
inferenceComponents
)
)
}
fun createFunctionConsumer(
@@ -248,6 +259,28 @@ fun createSimpleConsumer(
}
}
class PrioritizedTowerDataConsumer(
vararg val consumers: TowerDataConsumer
) : TowerDataConsumer() {
override fun consume(
kind: TowerDataKind,
implicitReceiverType: ConeKotlinType?,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector,
group: Int
): ProcessorAction {
for ((index, consumer) in consumers.withIndex()) {
val action = consumer.consume(kind, implicitReceiverType, towerScopeLevel, resultCollector, group * consumers.size + index)
if (action.stop()) {
return ProcessorAction.STOP
}
}
return ProcessorAction.NEXT
}
}
class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
val session: FirSession,
val name: Name,
@@ -256,15 +289,14 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
val candidateFactory: CandidateFactory
) : TowerDataConsumer() {
var groupId = 0
override fun consume(
kind: TowerDataKind,
implicitReceiverType: ConeKotlinType?,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector
resultCollector: CandidateCollector,
group: Int
): ProcessorAction {
groupId++
return when (kind) {
TowerDataKind.EMPTY ->
MemberScopeTowerLevel(session, explicitReceiver).processElementsByName(
@@ -274,7 +306,7 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
resultCollector.consumeCandidate(
groupId,
group,
candidateFactory.createCandidate(
symbol,
boundDispatchReceiver,
@@ -285,7 +317,8 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
}
}
)
TowerDataKind.TOWER_LEVEL ->
TowerDataKind.TOWER_LEVEL -> {
if (token == TowerScopeLevel.Token.Objects) return ProcessorAction.NEXT
towerScopeLevel.processElementsByName(
token,
name,
@@ -293,7 +326,7 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
resultCollector.consumeCandidate(
groupId,
group,
candidateFactory.createCandidate(
symbol,
boundDispatchReceiver,
@@ -304,6 +337,7 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
}
}
)
}
}
}
@@ -315,16 +349,15 @@ class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
val token: TowerScopeLevel.Token<T>,
val candidateFactory: CandidateFactory
) : TowerDataConsumer() {
var groupId = 0
override fun consume(
kind: TowerDataKind,
implicitReceiverType: ConeKotlinType?,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector
resultCollector: CandidateCollector,
group: Int
): ProcessorAction {
groupId++
return when (kind) {
TowerDataKind.TOWER_LEVEL -> {
@@ -335,7 +368,7 @@ class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
resultCollector.consumeCandidate(
groupId,
group,
candidateFactory.createCandidate(symbol, boundDispatchReceiver, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER)
)
return ProcessorAction.NEXT
@@ -358,10 +391,12 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val session: FirSes
fun runTowerResolver(towerDataConsumer: TowerDataConsumer): CandidateCollector {
val collector = CandidateCollector(callInfo!!)
towerDataConsumer.consume(TowerDataKind.EMPTY, null, TowerScopeLevel.Empty, collector)
var group = 0
towerDataConsumer.consume(TowerDataKind.EMPTY, null, TowerScopeLevel.Empty, collector, group++)
for (scope in scopes!!) {
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, null, ScopeTowerLevel(session, scope), collector)
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, null, ScopeTowerLevel(session, scope), collector, group++)
}
return collector
@@ -5,8 +5,8 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
@@ -18,12 +18,12 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystem
internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val csBuilder = candidate.system.getBuilder()
val declaration = candidate.symbol.firUnsafe<FirCallableDeclaration>()
val declaration = candidate.symbol.firUnsafe<FirDeclaration>()
if (declaration !is FirCallableMemberDeclaration || declaration.typeParameters.isEmpty()) {
candidate.substitutor = ConeSubstitutor.Empty
return
}
val csBuilder = candidate.system.getBuilder()
val (substitutor, freshVariables) = createToFreshVariableSubstitutorAndAddInitialConstraints(declaration, candidate, csBuilder)
candidate.substitutor = substitutor
@@ -8,8 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
import org.jetbrains.kotlin.name.Name
class FirNamedReferenceWithCandidate(session: FirSession, psi: PsiElement?, name: Name, val candidate: Candidate) :
FirResolvedCallableReferenceImpl(session, psi, name, candidate.symbol as ConeCallableSymbol)
FirResolvedCallableReferenceImpl(session, psi, name, candidate.symbol)
@@ -111,10 +111,10 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
}
FirOperation.SAFE_AS -> {
resolved.resultType =
resolved.conversionTypeRef.withReplacedConeType(
session,
resolved.conversionTypeRef.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE)
)
resolved.conversionTypeRef.withReplacedConeType(
session,
resolved.conversionTypeRef.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE)
)
}
else -> error("Unknown type operator")
}
@@ -148,8 +148,19 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
return when (val newCallee = access.calleeReference) {
is FirErrorNamedReference ->
FirErrorTypeRefImpl(session, access.psi, newCallee.errorReason)
is FirResolvedCallableReference ->
jump.tryCalculateReturnType(newCallee.callableSymbol.firUnsafe())
is FirResolvedCallableReference -> {
val symbol = newCallee.coneSymbol
if (symbol is ConeCallableSymbol) {
jump.tryCalculateReturnType(symbol.firUnsafe())
} else if (symbol is ConeClassifierSymbol) {
FirResolvedTypeRefImpl(
session, null, symbol.constructType(emptyArray(), isNullable = false),
isMarkedNullable = false, annotations = emptyList()
)
} else {
error("WTF ! $symbol")
}
}
else -> error("Failed to extract type from: $newCallee")
}
}
@@ -186,13 +197,13 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
}
is FirSuperReference -> {
qualifiedAccessExpression.resultType =
FirErrorTypeRefImpl(session, qualifiedAccessExpression.psi, "Unsupported: super type") //TODO
FirErrorTypeRefImpl(session, qualifiedAccessExpression.psi, "Unsupported: super type") //TODO
}
is FirResolvedCallableReference -> {
if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) {
qualifiedAccessExpression.resultType =
jump.tryCalculateReturnType(callee.callableSymbol.firUnsafe<FirCallableDeclaration>())
jump.tryCalculateReturnType(callee.coneSymbol.firUnsafe<FirCallableDeclaration>())
}
}
}
@@ -205,7 +216,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
resolver.callInfo = info
resolver.scopes = (scopes + localScopes).asReversed()
val consumer = createVariableConsumer(
val consumer = createVariableAndObjectConsumer(
session,
callee.name,
info, inferenceComponents
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substituteOrNull
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
@@ -77,7 +76,7 @@ class FirCallCompleterTransformer(
calleeReference.session,
calleeReference.psi,
calleeReference.name,
calleeReference.callableSymbol
calleeReference.coneSymbol
)
).compose()
+3 -3
View File
@@ -23,7 +23,7 @@ FILE: enum.kt
public final enum entry FIRST : R|SomeEnum| {
public constructor(): R|SomeEnum.FIRST| {
super<R|SomeEnum|>(<Unresolved name: O1>#)
super<R|SomeEnum|>(R|/O1|)
}
public final override fun check(y: R|Some|): R|kotlin/Boolean| {
@@ -34,11 +34,11 @@ FILE: enum.kt
public final enum entry SECOND : R|SomeEnum| {
public constructor(): R|SomeEnum.SECOND| {
super<R|SomeEnum|>(<Unresolved name: O2>#)
super<R|SomeEnum|>(R|/O2|)
}
public final override fun check(y: R|Some|): R|kotlin/Boolean| {
^check ==(R|<local>/y|, <Unresolved name: O2>#)
^check ==(R|<local>/y|, R|/O2|)
}
}
@@ -0,0 +1,12 @@
object A
val A = 10
fun foo() = A
fun bar() {
val A = ""
val b = A
}
@@ -0,0 +1,14 @@
FILE: objectVsProperty.kt
public final object A : R|kotlin/Any| {
public constructor(): super<R|kotlin/Any|>()
}
public final val A: R|kotlin/Int| = Int(10)
public get(): R|kotlin/Int|
public final fun foo(): R|kotlin/Int| {
^foo R|/A|
}
public final fun bar(): R|kotlin/Unit| {
lval A: R|kotlin/String| = String()
lval b: R|kotlin/String| = R|<local>/A|
}
@@ -0,0 +1,6 @@
object A {
fun foo() = this
}
fun use() = A
fun bar() = A.foo()
@@ -0,0 +1,15 @@
FILE: objects.kt
public final object A : R|kotlin/Any| {
public constructor(): super<R|kotlin/Any|>()
public final fun foo(): R|A| {
^foo this#
}
}
public final fun use(): R|A| {
^use R|/A|
}
public final fun bar(): R|A| {
^bar R|/A|.R|/A.foo|()
}
@@ -1,5 +1,5 @@
FILE: reflectionClass.kt
public final val javaClass: R|java/lang/Class<kotlin/String>| = <getClass>(<Unresolved name: String>#).<Unresolved name: java>#
public final val javaClass: R|java/lang/Class<kotlin/String>| = <getClass>(R|kotlin/String|).<Unresolved name: java>#
public get(): R|java/lang/Class<kotlin/String>|
public final val kotlinClass: R|kotlin/reflect/KClass<kotlin/String>| = <getClass>(<Unresolved name: String>#)
public final val kotlinClass: R|kotlin/reflect/KClass<kotlin/String>| = <getClass>(R|kotlin/String|)
public get(): R|kotlin/reflect/KClass<kotlin/String>|
@@ -179,6 +179,16 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/expresssions/localImplicitBodies.kt");
}
@TestMetadata("objectVsProperty.kt")
public void testObjectVsProperty() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/objectVsProperty.kt");
}
@TestMetadata("objects.kt")
public void testObjects() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/objects.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/simple.kt");
@@ -14,6 +14,8 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirWhenSubjectExpression
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.*
@@ -763,13 +765,16 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
override fun visitResolvedCallableReference(resolvedCallableReference: FirResolvedCallableReference) {
print("R|")
val isFakeOverride = (resolvedCallableReference.callableSymbol as? FirFunctionSymbol)?.isFakeOverride == true
val isFakeOverride = (resolvedCallableReference.coneSymbol as? FirFunctionSymbol)?.isFakeOverride == true
if (isFakeOverride) {
print("FakeOverride<")
}
val symbol = resolvedCallableReference.callableSymbol
print(symbol.callableId)
val symbol = resolvedCallableReference.coneSymbol
if (symbol is ConeCallableSymbol)
print(symbol.callableId)
else if (symbol is ConeClassLikeSymbol)
print(symbol.classId)
if (isFakeOverride) {
when (symbol) {
is FirFunctionSymbol -> {
@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.fir.visitors.FirVisitor
interface FirResolvedCallableReference : FirNamedReference {
val callableSymbol: ConeCallableSymbol
val coneSymbol: ConeSymbol
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitResolvedCallableReference(this, data)
@@ -28,6 +28,7 @@ fun FirExpression.toResolvedCallableReference(): FirResolvedCallableReference? {
return (this as? FirQualifiedAccess)?.calleeReference as? FirResolvedCallableReference
}
fun FirExpression.toResolvedCallableSymbol(): ConeCallableSymbol? {
return toResolvedCallableReference()?.callableSymbol
return toResolvedCallableReference()?.coneSymbol as ConeCallableSymbol?
}
@@ -16,5 +16,5 @@ class FirPropertyFromParameterCallableReference(
session: FirSession,
psi: PsiElement?,
override val name: Name,
override val callableSymbol: FirVariableSymbol
override val coneSymbol: FirVariableSymbol
) : FirAbstractElement(session, psi), FirResolvedCallableReference
@@ -9,12 +9,12 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirAbstractElement
import org.jetbrains.kotlin.fir.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.name.Name
open class FirResolvedCallableReferenceImpl(
session: FirSession,
psi: PsiElement?,
override val name: Name,
override val callableSymbol: ConeCallableSymbol
override val coneSymbol: ConeSymbol
) : FirAbstractElement(session, psi), FirResolvedCallableReference
@@ -1,6 +0,0 @@
FILE fqName:<root> fileName:/implicitCastOnPlatformType.kt
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test (): kotlin.String declared in <root>'
ERROR_CALL 'Unresolved reference: <Unresolved name: getProperty>#' type=IrErrorType
CONST String type=kotlin.String value="test"
@@ -1,2 +1,4 @@
// FIR_IDENTICAL
fun test(): String =
System.getProperty("test")
@@ -1,5 +0,0 @@
FILE fqName:<root> fileName:/javaStaticMethod.kt
FUN name:test visibility:public modality:FINAL <> () returnType:IrErrorType
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test (): IrErrorType declared in <root>'
ERROR_CALL 'Unresolved reference: <Unresolved name: bar>#' type=IrErrorType
+1
View File
@@ -6,5 +6,6 @@ public class J {
}
// FILE: javaStaticMethod.kt
// FIR_IDENTICAL
fun test() = J.bar()