Skip to content

Commit

Permalink
Use proper applicability for constraint warnings
Browse files Browse the repository at this point in the history
^KT-47316 Fixed
  • Loading branch information
petukhovv authored and Space committed Jun 21, 2021
1 parent dc8fa06 commit eec6efb
Show file tree
Hide file tree
Showing 17 changed files with 426 additions and 20 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -345,8 +345,8 @@ class DiagnosticReporterByTrackingStrategy(

override fun constraintError(error: ConstraintSystemError) {
when (error.javaClass) {
NewConstraintError::class.java -> {
error as NewConstraintError
NewConstraintError::class.java, NewConstraintWarning::class.java -> {
error as NewConstraintMismatch
val position = error.position.from
val argument =
when (position) {
Expand All @@ -356,16 +356,17 @@ class DiagnosticReporterByTrackingStrategy(
is LambdaArgumentConstraintPositionImpl -> position.lambda.atom
else -> null
}
val typeMismatchDiagnostic = if (error.isWarning) TYPE_MISMATCH_WARNING else TYPE_MISMATCH
val report = if (error.isWarning) trace::reportDiagnosticOnce else trace::report
val isWarning = error is NewConstraintWarning
val typeMismatchDiagnostic = if (isWarning) TYPE_MISMATCH_WARNING else TYPE_MISMATCH
val report = if (isWarning) trace::reportDiagnosticOnce else trace::report
argument?.let {
it.safeAs<LambdaKotlinCallArgument>()?.let lambda@{ lambda ->
val parameterTypes = lambda.parametersTypes?.toList() ?: return@lambda
val index = parameterTypes.indexOf(error.upperKotlinType.unwrap())
val lambdaExpression = lambda.psiExpression as? KtLambdaExpression ?: return@lambda
val parameter = lambdaExpression.valueParameters.getOrNull(index) ?: return@lambda
val diagnosticFactory =
if (error.isWarning) EXPECTED_PARAMETER_TYPE_MISMATCH_WARNING else EXPECTED_PARAMETER_TYPE_MISMATCH
if (isWarning) EXPECTED_PARAMETER_TYPE_MISMATCH_WARNING else EXPECTED_PARAMETER_TYPE_MISMATCH
report(diagnosticFactory.on(parameter, error.upperKotlinType))
return
}
Expand Down Expand Up @@ -398,7 +399,7 @@ class DiagnosticReporterByTrackingStrategy(

(position as? ExplicitTypeParameterConstraintPositionImpl)?.let {
val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference
val diagnosticFactory = if (error.isWarning) UPPER_BOUND_VIOLATED_WARNING else UPPER_BOUND_VIOLATED
val diagnosticFactory = if (isWarning) UPPER_BOUND_VIOLATED_WARNING else UPPER_BOUND_VIOLATED
report(diagnosticFactory.on(typeArgumentReference, error.upperKotlinType, error.lowerKotlinType))
}

Expand Down Expand Up @@ -570,7 +571,7 @@ class DiagnosticReporterByTrackingStrategy(
}
}

private fun reportConstantTypeMismatch(constraintError: NewConstraintError, expression: KtExpression): Boolean {
private fun reportConstantTypeMismatch(constraintError: NewConstraintMismatch, expression: KtExpression): Boolean {
if (expression is KtConstantExpression) {
val module = context.scope.ownerDescriptor.module
val constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, trace, context.expectedType)
Expand All @@ -583,5 +584,5 @@ class DiagnosticReporterByTrackingStrategy(

}

val NewConstraintError.upperKotlinType get() = upperType as KotlinType
val NewConstraintError.lowerKotlinType get() = lowerType as KotlinType
val NewConstraintMismatch.upperKotlinType get() = upperType as KotlinType
val NewConstraintMismatch.lowerKotlinType get() = lowerType as KotlinType
Expand Up @@ -80,12 +80,24 @@ object SimpleConstraintSystemConstraintPosition : ConstraintPosition()

sealed class ConstraintSystemError(val applicability: CandidateApplicability)

sealed interface NewConstraintMismatch {
val lowerType: KotlinTypeMarker
val upperType: KotlinTypeMarker
val position: IncorporationConstraintPosition
}

class NewConstraintError(
val lowerType: KotlinTypeMarker,
val upperType: KotlinTypeMarker,
val position: IncorporationConstraintPosition,
val isWarning: Boolean = false
) : ConstraintSystemError(if (position.from is ReceiverConstraintPosition<*>) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE)
override val lowerType: KotlinTypeMarker,
override val upperType: KotlinTypeMarker,
override val position: IncorporationConstraintPosition,
) : ConstraintSystemError(if (position.from is ReceiverConstraintPosition<*>) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE),
NewConstraintMismatch

class NewConstraintWarning(
override val lowerType: KotlinTypeMarker,
override val upperType: KotlinTypeMarker,
override val position: IncorporationConstraintPosition,
) : ConstraintSystemError(RESOLVED), NewConstraintMismatch

class CapturedTypeFromSubtyping(
val typeVariable: TypeVariableMarker,
Expand All @@ -111,4 +123,4 @@ object LowerPriorityToPreserveCompatibility : ConstraintSystemError(RESOLVED_NEE
fun Constraint.isExpectedTypePosition() =
position.from is ExpectedTypeConstraintPosition<*> || position.from is DelegatedPropertyConstraintPosition<*>

fun NewConstraintError.transformToWarning() = NewConstraintError(lowerType, upperType, position, isWarning = true)
fun NewConstraintError.transformToWarning() = NewConstraintWarning(lowerType, upperType, position)
Expand Up @@ -386,7 +386,7 @@ class NewConstraintSystemImpl(
}
val constraintErrors = constraintSystem.errors.filterIsInstance<NewConstraintError>()
// Don't report warning if an error on the same call has already been reported
if (constraintErrors.isEmpty() || constraintErrors.all { it.isWarning }) {
if (constraintErrors.isEmpty()) {
errorsByMissedConstraints.forEach {
constraintSystem.addError(it.transformToWarning())
}
Expand Down
Expand Up @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceCandidate
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintError
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintWarning
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability.*
import org.jetbrains.kotlin.types.TypeConstructor
Expand Down Expand Up @@ -282,4 +282,4 @@ fun ConstraintSystemError.asDiagnostic(): KotlinConstraintSystemDiagnostic = Kot
fun Collection<ConstraintSystemError>.asDiagnostics(): List<KotlinConstraintSystemDiagnostic> = map(ConstraintSystemError::asDiagnostic)

fun List<KotlinCallDiagnostic>.filterErrorDiagnostics() =
filter { it !is KotlinConstraintSystemDiagnostic || (it.error as? NewConstraintError)?.isWarning != true }
filter { it !is KotlinConstraintSystemDiagnostic || it.error !is NewConstraintWarning }
Expand Up @@ -248,10 +248,13 @@ sealed class CallResolutionResult(
fun completedDiagnostic(substitutor: NewTypeSubstitutor): List<KotlinCallDiagnostic> {
return diagnostics.map {
val error = it.constraintSystemError ?: return@map it
if (error !is NewConstraintError) return@map it
if (error !is NewConstraintMismatch) return@map it
val lowerType = error.lowerType.safeAs<KotlinType>()?.unwrap() ?: return@map it
val newLowerType = substitutor.safeSubstitute(lowerType.unCapture())
NewConstraintError(newLowerType, error.upperType, error.position, error.isWarning).asDiagnostic()
when (error) {
is NewConstraintError -> NewConstraintError(newLowerType, error.upperType, error.position).asDiagnostic()
is NewConstraintWarning -> NewConstraintWarning(newLowerType, error.upperType, error.position).asDiagnostic()
}
}
}

Expand Down
39 changes: 39 additions & 0 deletions compiler/testData/codegen/box/inference/kt47316.kt
@@ -0,0 +1,39 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR

// FILE: GoBuildingRunningState.java
public abstract class GoBuildingRunningState<T extends GoBuildingRunConfiguration<? extends GoBuildingRunningState<T>>> implements RunProfileState {
public String getBuildingWorkingDirectory() {
return "";
}
}

// FILE: GoBuildingRunConfiguration.java
public abstract class GoBuildingRunConfiguration<RunningState extends GoBuildingRunningState<? extends GoBuildingRunConfiguration<RunningState>>> { }

// FILE: RunProfileState.java
public interface RunProfileState {
}

// FILE: Test.java
import org.jetbrains.annotations.Nullable;

public class Test {
@Nullable
public RunProfileState getState() {
return null;
}
}

// FILE: main.kt
fun String.asFsdAddress(): String {
return ""
}

fun box(): String {
val state = Test().state
if (state is GoBuildingRunningState<*>) {
state.buildingWorkingDirectory.asFsdAddress()
}
return "OK"
}

0 comments on commit eec6efb

Please sign in to comment.