More precise diagnostics of smart cast impossible #KT-7240 Fixed
This commit is contained in:
@@ -475,7 +475,7 @@ public class CandidateResolver(
|
||||
|
||||
val bindingContext = trace.bindingContext
|
||||
val receiverValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, bindingContext, scope.ownerDescriptor)
|
||||
if (safeAccess && !dataFlowInfo.getNullability(receiverValue).canBeNull()) {
|
||||
if (safeAccess && !dataFlowInfo.getPredictableNullability(receiverValue).canBeNull()) {
|
||||
tracing.unnecessarySafeCall(trace, receiverArgument.type)
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,19 @@ public interface DataFlowInfo {
|
||||
@NotNull
|
||||
SetMultimap<DataFlowValue, KotlinType> getCompleteTypeInfo();
|
||||
|
||||
/**
|
||||
* Returns collected nullability for the given value, NOT taking its predictability into account.
|
||||
*/
|
||||
@NotNull
|
||||
Nullability getNullability(@NotNull DataFlowValue key);
|
||||
|
||||
/**
|
||||
* Returns collected nullability for the given value if it's predictable.
|
||||
* Otherwise basic value nullability is returned
|
||||
*/
|
||||
@NotNull
|
||||
Nullability getPredictableNullability(@NotNull DataFlowValue key);
|
||||
|
||||
/**
|
||||
* IMPORTANT: by default, the original (native) type for this value
|
||||
* are NOT included. So it's quite possible to get an empty set here.
|
||||
|
||||
+12
-2
@@ -111,7 +111,18 @@ import static org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
||||
@Override
|
||||
@NotNull
|
||||
public Nullability getNullability(@NotNull DataFlowValue key) {
|
||||
if (!key.isPredictable()) return key.getImmanentNullability();
|
||||
return getNullability(key, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Nullability getPredictableNullability(@NotNull DataFlowValue key) {
|
||||
return getNullability(key, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Nullability getNullability(@NotNull DataFlowValue key, boolean predictableOnly) {
|
||||
if (predictableOnly && !key.isPredictable()) return key.getImmanentNullability();
|
||||
Nullability nullability = nullabilityInfo.get(key);
|
||||
return nullability != null ? nullability :
|
||||
parent != null ? parent.getNullability(key) :
|
||||
@@ -123,7 +134,6 @@ import static org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
||||
@NotNull DataFlowValue value,
|
||||
@NotNull Nullability nullability
|
||||
) {
|
||||
if (!value.isPredictable()) return false;
|
||||
map.put(value, nullability);
|
||||
return nullability != getNullability(value);
|
||||
}
|
||||
|
||||
+3
-3
@@ -892,7 +892,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
private static boolean isKnownToBeNotNull(KtExpression expression, KotlinType jetType, ExpressionTypingContext context) {
|
||||
DataFlowValue dataFlowValue = createDataFlowValue(expression, jetType, context);
|
||||
return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
|
||||
return !context.dataFlowInfo.getPredictableNullability(dataFlowValue).canBeNull();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1191,7 +1191,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
DataFlowInfo rightDataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
|
||||
// left argument is considered not-null if it's not-null also in right part or if we have jump in right part
|
||||
if ((rightType != null && KotlinBuiltIns.isNothingOrNullableNothing(rightType) && !rightType.isMarkedNullable())
|
||||
|| !rightDataFlowInfo.getNullability(leftValue).canBeNull()) {
|
||||
|| !rightDataFlowInfo.getPredictableNullability(leftValue).canBeNull()) {
|
||||
dataFlowInfo = dataFlowInfo.disequate(leftValue, DataFlowValue.nullValue(components.builtIns));
|
||||
}
|
||||
}
|
||||
@@ -1298,7 +1298,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
new Function1<DataFlowValue, Nullability>() {
|
||||
@Override
|
||||
public Nullability invoke(DataFlowValue value) {
|
||||
return context.dataFlowInfo.getNullability(value);
|
||||
return context.dataFlowInfo.getPredictableNullability(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user