FIR: Avoid reporting redundant TYPE_MISMATCH (for assignments)

This commit is contained in:
Denis.Zharkov
2021-05-19 18:23:03 +03:00
committed by teamcityserver
parent 36c9418d55
commit db500fab94
5 changed files with 70 additions and 16 deletions
@@ -15,8 +15,13 @@ sealed class ResolutionMode {
object ContextDependent : ResolutionMode()
object ContextDependentDelegate : ResolutionMode()
object ContextIndependent : ResolutionMode()
// TODO: it's better not to use WithExpectedType(FirImplicitTypeRef)
class WithExpectedType(val expectedTypeRef: FirTypeRef, val mayBeCoercionToUnitApplied: Boolean = false) : ResolutionMode()
class WithExpectedType(
val expectedTypeRef: FirTypeRef,
val mayBeCoercionToUnitApplied: Boolean = false,
val expectedTypeMismatchIsReportedInChecker: Boolean = false,
) : ResolutionMode()
class WithStatus(val status: FirDeclarationStatus) : ResolutionMode()
@@ -29,8 +34,13 @@ fun ResolutionMode.expectedType(components: BodyResolveComponents): FirTypeRef?
else -> null
}
fun withExpectedType(expectedTypeRef: FirTypeRef?): ResolutionMode =
expectedTypeRef?.let { ResolutionMode.WithExpectedType(it) } ?: ResolutionMode.ContextDependent
fun withExpectedType(expectedTypeRef: FirTypeRef?, expectedTypeMismatchIsReportedInChecker: Boolean = false): ResolutionMode =
expectedTypeRef?.let {
ResolutionMode.WithExpectedType(
it,
expectedTypeMismatchIsReportedInChecker = expectedTypeMismatchIsReportedInChecker
)
} ?: ResolutionMode.ContextDependent
@JvmName("withExpectedTypeNullable")
fun withExpectedType(coneType: ConeKotlinType?, mayBeCoercionToUnitApplied: Boolean = false): ResolutionMode {
@@ -31,8 +31,6 @@ 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
import org.jetbrains.kotlin.name.Name
@@ -56,13 +54,26 @@ class FirCallCompleter(
data class CompletionResult<T>(val result: T, val callCompleted: Boolean)
fun <T> completeCall(call: T, expectedTypeRef: FirTypeRef?): CompletionResult<T> where T : FirResolvable, T : FirStatement =
completeCall(call, expectedTypeRef, mayBeCoercionToUnitApplied = false)
fun <T> completeCall(
call: T,
expectedTypeRef: FirTypeRef?,
expectedTypeMismatchIsReportedInChecker: Boolean = false,
): CompletionResult<T> where T : FirResolvable, T : FirStatement =
completeCall(call, expectedTypeRef, mayBeCoercionToUnitApplied = false, expectedTypeMismatchIsReportedInChecker)
fun <T> completeCall(call: T, data: ResolutionMode): CompletionResult<T> where T : FirResolvable, T : FirStatement =
completeCall(call, data.expectedType(components), (data as? ResolutionMode.WithExpectedType)?.mayBeCoercionToUnitApplied == true)
completeCall(
call,
data.expectedType(components),
(data as? ResolutionMode.WithExpectedType)?.mayBeCoercionToUnitApplied == true,
(data as? ResolutionMode.WithExpectedType)?.expectedTypeMismatchIsReportedInChecker == true,
)
fun <T> completeCall(call: T, expectedTypeRef: FirTypeRef?, mayBeCoercionToUnitApplied: Boolean): CompletionResult<T>
private fun <T> completeCall(
call: T, expectedTypeRef: FirTypeRef?,
mayBeCoercionToUnitApplied: Boolean,
expectedTypeMismatchIsReportedInChecker: Boolean,
): CompletionResult<T>
where T : FirResolvable, T : FirStatement {
val typeRef = components.typeFromCallee(call)
@@ -82,14 +93,15 @@ class FirCallCompleter(
}
if (expectedTypeRef is FirResolvedTypeRef) {
val expectedTypeConstraintPosition = ConeExpectedTypeConstraintPosition(expectedTypeMismatchIsReportedInChecker)
if (expectedTypeRef.coneType.isUnitOrFlexibleUnit && mayBeCoercionToUnitApplied) {
if (candidate.system.notFixedTypeVariables.isNotEmpty()) {
candidate.system.addSubtypeConstraintIfCompatible(
initialType, expectedTypeRef.type, ConeExpectedTypeConstraintPosition()
initialType, expectedTypeRef.type, expectedTypeConstraintPosition
)
}
} else {
candidate.system.addSubtypeConstraint(initialType, expectedTypeRef.type, ConeExpectedTypeConstraintPosition())
candidate.system.addSubtypeConstraint(initialType, expectedTypeRef.type, expectedTypeConstraintPosition)
}
}
@@ -17,7 +17,9 @@ class ConeFixVariableConstraintPosition(variable: TypeVariableMarker) : FixVaria
class ConeArgumentConstraintPosition(argument: FirElement) : ArgumentConstraintPosition<FirElement>(argument)
class ConeExpectedTypeConstraintPosition : ExpectedTypeConstraintPosition<Nothing?>(null)
class ConeExpectedTypeConstraintPosition(
val expectedTypeMismatchIsReportedInChecker: Boolean
) : ExpectedTypeConstraintPosition<Nothing?>(null)
class ConeExplicitTypeParameterConstraintPosition(
typeArgument: FirTypeProjection,
@@ -423,7 +423,11 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
}
fun chooseOperator(): FirStatement {
callCompleter.completeCall(resolvedOperatorCall, lhsVariable?.returnTypeRef ?: noExpectedType)
callCompleter.completeCall(
resolvedOperatorCall,
lhsVariable?.returnTypeRef ?: noExpectedType,
expectedTypeMismatchIsReportedInChecker = true
)
dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true)
val assignment =
buildVariableAssignment {
@@ -684,7 +688,10 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
val resolvedAssignment = callResolver.resolveVariableAccessAndSelectCandidate(variableAssignment)
val result = if (resolvedAssignment is FirVariableAssignment) {
val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType).result // TODO: check
completeAssignment.transformRValue(transformer, withExpectedType(variableAssignment.lValueTypeRef))
completeAssignment.transformRValue(
transformer,
withExpectedType(variableAssignment.lValueTypeRef, expectedTypeMismatchIsReportedInChecker = true),
)
} else {
// This can happen in erroneous code only
resolvedAssignment