Make FirNamedReferenceWithCandidate not resolved, fix receiver completion

Counting it as resolved provokes a lot of difficult to discover errors
This commit is contained in:
Mikhail Glukhikh
2019-07-12 13:32:10 +03:00
parent 08f44d4f14
commit 592cf4f4e8
14 changed files with 132 additions and 54 deletions
@@ -7,8 +7,12 @@ 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.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.name.Name
class FirNamedReferenceWithCandidate(session: FirSession, psi: PsiElement?, name: Name, val candidate: Candidate) :
FirResolvedCallableReferenceImpl(session, psi, name, candidate.symbol)
FirSimpleNamedReference(session, psi, name) {
override val candidateSymbol: ConeSymbol
get() = candidate.symbol
}
@@ -26,10 +26,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.FirTopLevelDeclaredMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
@@ -204,39 +201,51 @@ open class FirBodyResolveTransformer(
access.resultType = typeFromCallee(access)
}
private fun typeFromSymbol(symbol: ConeSymbol, makeNullable: Boolean): FirResolvedTypeRef {
return when (symbol) {
is FirCallableSymbol<*> -> {
val returnType = jump.tryCalculateReturnType(symbol.fir)
if (makeNullable) {
returnType.withReplacedConeType(
session,
returnType.coneTypeUnsafe<ConeKotlinType>().withNullability(ConeNullability.NULLABLE)
)
} else {
returnType
}
}
is ConeClassifierSymbol -> {
val fir = (symbol as? FirBasedSymbol<*>)?.fir
// TODO: unhack
if (fir is FirEnumEntry) {
(fir.superTypeRefs.firstOrNull() as? FirResolvedTypeRef) ?: FirErrorTypeRefImpl(
session,
null,
"no enum item supertype"
)
} else
FirResolvedTypeRefImpl(
session, null, symbol.constructType(emptyArray(), isNullable = false),
annotations = emptyList()
)
}
else -> error("WTF ! $symbol")
}
}
private fun <T> typeFromCallee(access: T): FirResolvedTypeRef where T : FirQualifiedAccess {
val makeNullable: Boolean by lazy {
access.safe && access.explicitReceiver!!.resultType.coneTypeUnsafe<ConeKotlinType>().isNullable
}
return when (val newCallee = access.calleeReference) {
is FirErrorNamedReference ->
FirErrorTypeRefImpl(session, access.psi, newCallee.errorReason)
is FirNamedReferenceWithCandidate -> {
typeFromSymbol(newCallee.candidateSymbol, makeNullable)
}
is FirResolvedCallableReference -> {
val symbol = newCallee.coneSymbol
if (symbol is FirCallableSymbol<*>) {
val returnType = jump.tryCalculateReturnType(symbol.fir)
if (access.safe && access.explicitReceiver!!.resultType.coneTypeUnsafe<ConeKotlinType>().isNullable) {
returnType.withReplacedConeType(
session,
returnType.coneTypeUnsafe<ConeKotlinType>().withNullability(ConeNullability.NULLABLE)
)
} else {
returnType
}
} else if (symbol is ConeClassifierSymbol && symbol is FirBasedSymbol<*>) {
val fir = symbol.fir
// TODO: unhack
if (fir is FirEnumEntry) {
(fir.superTypeRefs.firstOrNull() as? FirResolvedTypeRef) ?: FirErrorTypeRefImpl(
session,
null,
"no enum item supertype"
)
} else
FirResolvedTypeRefImpl(
session, null, symbol.constructType(emptyArray(), isNullable = false),
annotations = emptyList()
)
} else {
error("WTF ! $symbol")
}
typeFromSymbol(newCallee.coneSymbol, makeNullable)
}
is FirThisReference -> {
val labelName = newCallee.labelName
@@ -358,12 +367,14 @@ open class FirBodyResolveTransformer(
tryResolveAsQualifier()?.let { return it }
}
if (nameReference is FirResolvedCallableReference) {
val symbol = nameReference.coneSymbol as? ConeClassLikeSymbol
if (symbol != null) {
return FirResolvedQualifierImpl(session, nameReference.psi, symbol.classId).apply {
resultType = typeForQualifier(this)
}
val referencedSymbol = when (nameReference) {
is FirResolvedCallableReference -> nameReference.coneSymbol
is FirNamedReferenceWithCandidate -> nameReference.candidateSymbol
else -> null
}
if (referencedSymbol is ConeClassLikeSymbol) {
return FirResolvedQualifierImpl(session, nameReference.psi, referencedSymbol.classId).apply {
resultType = typeForQualifier(this)
}
}
@@ -747,7 +758,13 @@ open class FirBodyResolveTransformer(
val expectedTypeRef = data as FirTypeRef?
val completeInference =
try {
val initialExplicitReceiver = functionCall.explicitReceiver
val resultExpression = resolveCallAndSelectCandidate(functionCall, expectedTypeRef)
val resultExplicitReceiver = resultExpression.explicitReceiver
if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccess) {
// name.invoke() case
completeTypeInference(resultExplicitReceiver, null)
}
completeTypeInference(resultExpression, expectedTypeRef)
} catch (e: Throwable) {
throw RuntimeException("While resolving call ${functionCall.render()}", e)
@@ -42,7 +42,7 @@ class FirCallCompleterTransformer(
qualifiedAccessExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return qualifiedAccessExpression.compose()
calleeReference.candidate.substitutor
val typeRef = typeCalculator.tryCalculateReturnType(calleeReference.coneSymbol.firUnsafe())
val typeRef = typeCalculator.tryCalculateReturnType(calleeReference.candidateSymbol.firUnsafe())
val initialType = calleeReference.candidate.substitutor.substituteOrNull(typeRef.type)
val finalType = finalSubstitutor.substituteOrNull(initialType)
@@ -56,7 +56,7 @@ class FirCallCompleterTransformer(
calleeReference.session,
calleeReference.psi,
calleeReference.name,
calleeReference.coneSymbol
calleeReference.candidateSymbol
)
).compose()
}
@@ -73,7 +73,7 @@ class FirCallCompleterTransformer(
calleeReference.session,
calleeReference.psi,
calleeReference.name,
calleeReference.coneSymbol
calleeReference.candidateSymbol
)
).compose()
}
@@ -123,7 +123,7 @@ class FirCallCompleterTransformer(
calleeReference.session,
calleeReference.psi,
calleeReference.name,
calleeReference.coneSymbol
calleeReference.candidateSymbol
)
).compose()
@@ -79,6 +79,13 @@ internal object StoreCalleeReference : FirTransformer<FirResolvedCallableReferen
return element.compose()
}
override fun transformNamedReference(
namedReference: FirNamedReference,
data: FirResolvedCallableReference
): CompositeTransformResult<FirNamedReference> {
return data.compose()
}
override fun transformResolvedCallableReference(
resolvedCallableReference: FirResolvedCallableReference,
data: FirResolvedCallableReference
@@ -0,0 +1,11 @@
class Foo(name: () -> String) {
val result = run { name() }
val name = result.length
}
fun bar(name: () -> String) {
val result = run { name() }
val name = result.length
}
@@ -0,0 +1,23 @@
FILE: recursiveBug.kt
public final class Foo : R|kotlin/Any| {
public constructor(name: R|kotlin/Function0<kotlin/String>|): R|Foo| {
super<R|kotlin/Any|>()
}
public final val result: R|kotlin/String| = R|kotlin/run|<R|kotlin/String|>(<L> = run@fun <anonymous>(): R|kotlin/String| {
R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
}
)
public get(): R|kotlin/String|
public final val name: R|kotlin/Int| = R|/Foo.result|.R|kotlin/String.length|
public get(): R|kotlin/Int|
}
public final fun bar(name: R|kotlin/Function0<kotlin/String>|): R|kotlin/Unit| {
lval result: R|kotlin/String| = R|kotlin/run|<R|kotlin/String|>(<L> = run@fun <anonymous>(): R|kotlin/String| {
R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
}
)
lval name: R|kotlin/Int| = R|<local>/result|.R|kotlin/String.length|
}
@@ -13,7 +13,7 @@ FILE: topLevelResolve.kt
lval setAndList: R|kotlin/collections/Set<kotlin/Int>| = R|kotlin/collections/setOf|<R|kotlin/Int|>(Int(0)).R|kotlin/collections/plus|<R|kotlin/Int|>(R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(1), Int(2)))
lval stringAndList: R|kotlin/String| = String().R|kotlin/String.plus|(R|kotlin/collections/emptyList|<R|kotlin/Boolean|>())
lval map: R|kotlin/collections/Map<kotlin/String, kotlin/Int>| = R|kotlin/collections/mapOf|<R|kotlin/String|, R|kotlin/Int|>(String().R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(1)), String(.).R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(2))).R|kotlin/collections/plus|<R|kotlin/String|, R|kotlin/Int|>(String(..).R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(3)))
lval mapAndMap: <ERROR TYPE REF: Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]> = <Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#(String(-).R|kotlin/to|(Int(4))).<Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]>#(<Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#(String(_).R|kotlin/to|(Int(5))))
lval mapAndMap: <ERROR TYPE REF: Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]> = <Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#(String(-).R?C|kotlin/to|(Int(4))).<Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]>#(<Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#(String(_).R?C|kotlin/to|(Int(5))))
}
public final fun <T> id(arg: R|T|): R|T| {
^id R|<local>/arg|
@@ -84,6 +84,11 @@ public class FirResolveTestCaseWithStdlibGenerated extends AbstractFirResolveTes
runTest("compiler/fir/resolve/testData/resolve/stdlib/mapList.kt");
}
@TestMetadata("recursiveBug.kt")
public void testRecursiveBug() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/recursiveBug.kt");
}
@TestMetadata("reflectionClass.kt")
public void testReflectionClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/reflectionClass.kt");
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.Name
@@ -12,6 +13,8 @@ import org.jetbrains.kotlin.name.Name
interface FirNamedReference : FirReference {
val name: Name
val candidateSymbol: ConeSymbol? get() = null
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitNamedReference(this, data)
}
@@ -783,10 +783,18 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
}
override fun visitNamedReference(namedReference: FirNamedReference) {
if (namedReference is FirErrorNamedReference) {
print("<${namedReference.errorReason}>#")
} else {
print("${namedReference.name}#")
val symbol = namedReference.candidateSymbol
when {
symbol != null -> {
print("R?C|")
if (symbol is ConeCallableSymbol)
print(symbol.callableId)
else if (symbol is ConeClassLikeSymbol)
print(symbol.classId)
print("|")
}
namedReference is FirErrorNamedReference -> print("<${namedReference.errorReason}>#")
else -> print("${namedReference.name}#")
}
}
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.name.Name
open class FirResolvedCallableReferenceImpl(
class FirResolvedCallableReferenceImpl(
session: FirSession,
psi: PsiElement?,
override val name: Name,
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.FirNamedReference
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.name.Name
class FirSimpleNamedReference(
open class FirSimpleNamedReference(
session: FirSession,
psi: PsiElement?,
override val name: Name
@@ -8,7 +8,7 @@ FILE fqName:<root> fileName:/genericPropertyCall.kt
PROPERTY name:test visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test type:IrErrorType visibility:public [final,static]
EXPRESSION_BODY
CALL 'public final fun <get-id> (): IrErrorType declared in <root>' type=IrErrorType origin=null
ERROR_CALL 'Unresolved reference: R?C|/id|' type=IrErrorType
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test> visibility:public modality:FINAL <> () returnType:IrErrorType
correspondingProperty: PROPERTY name:test visibility:public modality:FINAL [val]
BLOCK_BODY
@@ -14,7 +14,7 @@ FILE fqName:<root> fileName:/variableAsFunctionCallWithGenerics.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testGeneric1 (x: kotlin.String): T of <uninitialized parent> declared in <root>'
CALL 'public abstract fun invoke (): T of <uninitialized parent> declared in kotlin.Function0' type=T of <uninitialized parent> origin=null
$this: CALL 'public final fun <get-gk> (): kotlin.Function0<T of <uninitialized parent>> declared in <root>' type=kotlin.Function0<T of <uninitialized parent>> origin=null
$this: ERROR_CALL 'Unresolved reference: R?C|/gk|' type=kotlin.Function0<T of <uninitialized parent>>
PROPERTY name:kt26531Val visibility:public modality:FINAL [val]
FUN name:<get-kt26531Val> visibility:public modality:FINAL <> () returnType:kotlin.Function0<T of <uninitialized parent>>
correspondingProperty: PROPERTY name:kt26531Val visibility:public modality:FINAL [val]
@@ -30,4 +30,4 @@ FILE fqName:<root> fileName:/variableAsFunctionCallWithGenerics.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun kt26531 (): T of <uninitialized parent> declared in <root>'
CALL 'public abstract fun invoke (): T of <uninitialized parent> declared in kotlin.Function0' type=T of <uninitialized parent> origin=null
$this: CALL 'public final fun <get-kt26531Val> (): kotlin.Function0<T of <uninitialized parent>> declared in <root>' type=kotlin.Function0<T of <uninitialized parent>> origin=null
$this: ERROR_CALL 'Unresolved reference: R?C|/kt26531Val|' type=kotlin.Function0<T of <uninitialized parent>>