Don't clean type info for containment operator if the resolution was unsuccessful, but all diagnostics were about only input types and non-strict only input types check was enabled

This commit is contained in:
Victor Petukhov
2020-12-23 15:03:40 +03:00
parent 954c9cecca
commit b4d8adeeb4
7 changed files with 144 additions and 6 deletions
@@ -566,6 +566,8 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D>
private var nonTrivialUpdatedResultInfo: DataFlowInfo? = null
abstract fun containsOnlyOnlyInputTypesErrors(): Boolean
override fun getCall(): Call = kotlinCall.psiKotlinCall.psiCall
override fun getValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> {
@@ -710,6 +712,9 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
return typeParameters.zip(typeArguments).toMap()
}
override fun containsOnlyOnlyInputTypesErrors() =
diagnostics.all { it is KotlinConstraintSystemDiagnostic && it.error is OnlyInputTypesDiagnostic }
override fun getSmartCastDispatchReceiverType(): KotlinType? = smartCastDispatchReceiverType
fun updateExtensionReceiverWithSmartCastIfNeeded(smartCastExtensionReceiverType: KotlinType) {
@@ -60,6 +60,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability;
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
import org.jetbrains.kotlin.resolve.calls.tower.NewAbstractResolvedCall;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker;
import org.jetbrains.kotlin.resolve.constants.*;
@@ -1394,14 +1395,26 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
rightTypeInfo = rightTypeInfo.replaceDataFlowInfo(dataFlowInfo);
}
if (resolutionResult.isSuccess()) {
if (resolutionResult.isSuccess() || isResolutionSuccessfulWithOnlyInputTypesWarnings(resolutionResult.getResultingCalls(), context)) {
return rightTypeInfo.replaceType(components.builtIns.getBooleanType());
}
else {
} else {
return rightTypeInfo.clearType();
}
}
private static boolean isResolutionSuccessfulWithOnlyInputTypesWarnings(
@Nullable Collection<? extends ResolvedCall<FunctionDescriptor>> allCandidates,
@NotNull ExpressionTypingContext context
) {
if (allCandidates == null || allCandidates.isEmpty()) return false;
boolean areAllCandidatesFailedWithOnlyInputTypesError = allCandidates.stream().allMatch((resolvedCall) ->
resolvedCall instanceof NewAbstractResolvedCall<?> && ((NewAbstractResolvedCall<?>) resolvedCall).containsOnlyOnlyInputTypesErrors()
);
boolean isNonStrictOnlyInputTypesCheckEnabled = context.languageVersionSettings.supportsFeature(LanguageFeature.NonStrictOnlyInputTypesChecks);
return areAllCandidatesFailedWithOnlyInputTypesError && isNonStrictOnlyInputTypesCheckEnabled;
}
private boolean ensureBooleanResult(KtExpression operationSign, Name name, KotlinType resultType, ExpressionTypingContext context) {
return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'", context);
@@ -0,0 +1,45 @@
// WITH_RUNTIME
import kotlin.experimental.ExperimentalTypeInference
fun <K> FlowCollector<K>.bar(): K = null as K
fun <K> FlowCollector<K>.foo(): K = null as K
fun bar2(): Int = 1
fun foo2(): Float = 1f
val bar4: Int
get() = 1
var foo4: Float
get() = 1f
set(value) {}
fun <T> materialize() = null as T
interface FlowCollector<in T> {}
@Suppress("EXPERIMENTAL_API_USAGE_ERROR")
fun <L> flow(@BuilderInference block: suspend FlowCollector<L>.() -> Unit) = Flow(block)
class Flow<out R>(private val block: suspend FlowCollector<R>.() -> Unit)
fun poll81(): Flow<String> {
return flow {
val inv = ::bar2 in setOf(::foo2)
inv
}
}
fun poll83(): Flow<String> {
return flow {
val inv = ::bar4 in setOf(::foo4)
inv
}
}
fun box(): String {
poll81()
poll83()
return "OK"
}
@@ -0,0 +1,35 @@
// WITH_RUNTIME
// SKIP_TXT
// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_API_USAGE_ERROR -UNUSED_EXPRESSION
import kotlin.experimental.ExperimentalTypeInference
fun bar2(): Int = 1
fun foo2(): Float = 1f
val bar4: Int
get() = 1
var foo4: Float
get() = 1f
set(value) {}
interface FlowCollector<in T> {}
fun <L> flow(@BuilderInference block: suspend FlowCollector<L>.() -> Unit) = Flow(block)
class Flow<out R>(private val block: suspend FlowCollector<R>.() -> Unit)
fun poll81(): Flow<String> {
return flow {
val inv = ::bar2 in setOf(::foo2)
<!UNRESOLVED_REFERENCE!>inv<!>()
}
}
fun poll83(): Flow<String> {
return flow {
val inv = ::bar4 in setOf(::foo4)
inv
}
}
@@ -0,0 +1,35 @@
// WITH_RUNTIME
// SKIP_TXT
// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_API_USAGE_ERROR -UNUSED_EXPRESSION
import kotlin.experimental.ExperimentalTypeInference
fun bar2(): Int = 1
fun foo2(): Float = 1f
val bar4: Int
get() = 1
var foo4: Float
get() = 1f
set(value) {}
interface FlowCollector<in T> {}
fun <L> flow(@BuilderInference block: suspend FlowCollector<L>.() -> Unit) = Flow(block)
class Flow<out R>(private val block: suspend FlowCollector<R>.() -> Unit)
fun poll81(): Flow<String> {
return flow {
val inv = ::bar2 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_WARNING!>in<!> setOf(::foo2)
<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inv<!>()
}
}
fun poll83(): Flow<String> {
return flow {
val inv = ::bar4 <!TYPE_INFERENCE_ONLY_INPUT_TYPES_WARNING!>in<!> setOf(::foo4)
inv
}
}
@@ -13506,6 +13506,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesErrorType.kt");
}
@TestMetadata("specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt")
public void testSpecialCallsWithCallableReferencesNonStrictOnlyInputTypes() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt");
}
@TestMetadata("substituteStubTypeIntoCR.kt")
public void testSubstituteStubTypeIntoCR() throws Exception {
runTest("compiler/testData/codegen/box/inference/builderInference/substituteStubTypeIntoCR.kt");
@@ -29,8 +29,8 @@ fun case_1(value_1: Int, value_2: EmptyClass, value_3: Int, value_4: Any): Strin
*/
fun case_2(value_1: Int, value_3: Nothing) {
when (value_1) {
<!OVERLOAD_RESOLUTION_AMBIGUITY, TYPE_MISMATCH_IN_RANGE, UNREACHABLE_CODE!>in<!> value_3 -> <!UNREACHABLE_CODE!>{}<!>
<!UNREACHABLE_CODE!><!OVERLOAD_RESOLUTION_AMBIGUITY, TYPE_MISMATCH_IN_RANGE!>in<!> throw Exception() -> {}<!>
<!UNREACHABLE_CODE!><!OVERLOAD_RESOLUTION_AMBIGUITY, TYPE_MISMATCH_IN_RANGE!>in<!> return -> {}<!>
<!OVERLOAD_RESOLUTION_AMBIGUITY, UNREACHABLE_CODE!>in<!> value_3 -> <!UNREACHABLE_CODE!>{}<!>
<!UNREACHABLE_CODE!><!OVERLOAD_RESOLUTION_AMBIGUITY!>in<!> throw Exception() -> {}<!>
<!UNREACHABLE_CODE!><!OVERLOAD_RESOLUTION_AMBIGUITY!>in<!> return -> {}<!>
}
}