FIR: ensure the absence of FirResolvedTypeRef with erroneous type

This commit is contained in:
Jinseong Jeon
2021-05-02 11:39:11 -07:00
committed by Mikhail Glukhikh
parent cba21c68a3
commit 61e21ef6a2
6 changed files with 27 additions and 17 deletions
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
@@ -20,9 +19,10 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.render
class ErrorNodeDiagnosticCollectorComponent(
session: FirSession,
@@ -39,9 +39,9 @@ class ErrorNodeDiagnosticCollectorComponent(
}
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: CheckerContext) {
val errorType = resolvedTypeRef.type as? ConeClassErrorType ?: return
val source = resolvedTypeRef.source ?: return
reportFirDiagnostic(errorType.diagnostic, source, reporter, data)
assert(resolvedTypeRef.type !is ConeKotlinErrorType) {
"Instead use FirErrorTypeRef for ${resolvedTypeRef.type.render()}"
}
}
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) {
@@ -30,7 +30,7 @@ class ConeUnresolvedSymbolError(val classId: ClassId) : ConeDiagnostic() {
}
class ConeUnresolvedQualifierError(val qualifier: String) : ConeDiagnostic() {
override val reason: String get() = "Symbol not found for ${qualifier}"
override val reason: String get() = "Symbol not found for $qualifier"
}
class ConeUnresolvedNameError(val name: Name) : ConeDiagnostic() {
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.typeFromCallee
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.visitors.transformSingle
@@ -188,7 +189,7 @@ class FirCallCompleter(
source = lambdaAtom.atom.source?.fakeElement(FirFakeSourceElementKind.ItLambdaParameter)
declarationSiteSession = session
origin = FirDeclarationOrigin.Source
returnTypeRef = buildResolvedTypeRef { type = itType.approximateLambdaInputType() }
returnTypeRef = itType.approximateLambdaInputType().toFirResolvedTypeRef()
this.name = name
symbol = FirVariableSymbol(name)
defaultValue = null
@@ -212,10 +213,7 @@ class FirCallCompleter(
lambdaArgument.valueParameters.forEachIndexed { index, parameter ->
val newReturnType = parameters[index].approximateLambdaInputType()
val newReturnTypeRef = if (parameter.returnTypeRef is FirImplicitTypeRef) {
buildResolvedTypeRef {
source = parameter.source
type = newReturnType
}
newReturnType.toFirResolvedTypeRef(parameter.source)
} else parameter.returnTypeRef.resolvedTypeFromPrototype(newReturnType)
parameter.replaceReturnTypeRef(newReturnTypeRef)
lookupTracker?.recordTypeResolveAsLookup(newReturnTypeRef, parameter.source, null)
@@ -255,7 +255,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
return wrappedDelegateExpression.expression
.transformSingle(transformer, data)
.approximateIfIsIntegerConst()
} finally {
dataFlowAnalyzer.exitDelegateExpression()
}
@@ -658,7 +657,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
source = lambda.source?.fakeElement(FirFakeSourceElementKind.ItLambdaParameter)
declarationSiteSession = session
origin = FirDeclarationOrigin.Source
returnTypeRef = buildResolvedTypeRef { type = singleParameterType }
returnTypeRef = singleParameterType.toFirResolvedTypeRef()
this.name = name
symbol = FirVariableSymbol(name)
isCrossinline = false
@@ -185,10 +185,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
* DiagnosticsTestGenerated$Tests$ThisAndSuper.testQualifiedSuperOverridden
*/
val actualSuperTypeRef = actualSuperType?.let {
buildResolvedTypeRef {
source = superTypeRef.source
type = it
}
it.toFirResolvedTypeRef(superTypeRef.source)
} ?: buildErrorTypeRef {
source = superTypeRef.source
diagnostic = ConeSimpleDiagnostic("Not a super type", DiagnosticKind.Other)
@@ -174,6 +174,22 @@ fun ConeKotlinType.toSymbol(session: FirSession): AbstractFirBasedSymbol<*>? {
return (this as? ConeLookupTagBasedType)?.lookupTag?.toSymbol(session)
}
fun ConeKotlinType.toFirResolvedTypeRef(
source: FirSourceElement? = null,
): FirResolvedTypeRef {
return if (this is ConeKotlinErrorType) {
buildErrorTypeRef {
this.source = source
diagnostic = this@toFirResolvedTypeRef.diagnostic
}
} else {
buildResolvedTypeRef {
this.source = source
type = this@toFirResolvedTypeRef
}
}
}
fun FirTypeRef.isUnsafeVarianceType(session: FirSession): Boolean {
return coneTypeSafe<ConeKotlinType>()?.isUnsafeVarianceType(session) == true
}