Fix warning about useless elvis when generics are involved

#KT-13648 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2017-03-31 17:15:07 +03:00
parent 0badc686ca
commit 4aa808b250
5 changed files with 67 additions and 5 deletions
@@ -943,7 +943,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.getStableNullability(dataFlowValue).canBeNull();
return context.dataFlowInfo.getStableNullability(dataFlowValue) == Nullability.NOT_NULL;
}
/**
@@ -1272,7 +1272,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
assert leftTypeInfo != null : "Left expression was not processed: " + expression;
KotlinType leftType = leftTypeInfo.getType();
if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
if (leftType != null && (!TypeUtils.isNullableType(leftType) || isKnownToBeNotNull(left, leftType, context))) {
context.trace.report(USELESS_ELVIS.on(expression, leftType));
}
else if (KtPsiUtil.isNullConstant(right) && leftType != null && !FlexibleTypesKt.isNullabilityFlexible(leftType)) {
@@ -1,4 +1,4 @@
// For KT-3491
// !DIAGNOSTICS: -UNUSED_PARAMETER, -SENSELESS_COMPARISON, -DEBUG_INFO_SMARTCAST
fun <T: Any?> test1(t: Any?): Any {
return <!UNCHECKED_CAST!>t as T<!> ?: ""
@@ -10,8 +10,35 @@ fun <T: Any> test2(t: Any?): Any {
fun <T: Any?> test3(t: Any?): Any {
if (t != null) {
return t <!USELESS_ELVIS!>?: ""<!>
return t <!USELESS_ELVIS!>?: ""<!>
}
return 1
}
fun takeNotNull(s: String) {}
fun <T> notNull(): T = TODO()
fun <T> nullable(): T? = null
fun <T> dependOn(x: T) = x
fun test() {
takeNotNull(notNull() <!USELESS_ELVIS!>?: ""<!>)
takeNotNull(nullable() ?: "")
val x: String? = null
takeNotNull(dependOn(x) ?: "")
takeNotNull(dependOn(dependOn(x)) ?: "")
takeNotNull(dependOn(dependOn(x as String)) <!USELESS_ELVIS!>?: ""<!>)
if (x != null) {
takeNotNull(dependOn(x) <!USELESS_ELVIS!>?: ""<!>)
takeNotNull(dependOn(dependOn(x)) <!USELESS_ELVIS!>?: ""<!>)
takeNotNull(dependOn(dependOn(x) <!USELESS_CAST!>as? String<!>) ?: "")
}
}
inline fun <reified T : Any> reifiedNull(): T? = null
fun testFrom13648() {
takeNotNull(reifiedNull() ?: "")
}
@@ -1,5 +1,12 @@
package
public fun </*0*/ T> dependOn(/*0*/ x: T): T
public fun </*0*/ T> notNull(): T
public fun </*0*/ T> nullable(): T?
public inline fun </*0*/ reified T : kotlin.Any> reifiedNull(): T?
public fun takeNotNull(/*0*/ s: kotlin.String): kotlin.Unit
public fun test(): kotlin.Unit
public fun </*0*/ T> test1(/*0*/ t: kotlin.Any?): kotlin.Any
public fun </*0*/ T : kotlin.Any> test2(/*0*/ t: kotlin.Any?): kotlin.Any
public fun </*0*/ T> test3(/*0*/ t: kotlin.Any?): kotlin.Any
public fun testFrom13648(): kotlin.Unit
@@ -1,4 +1,4 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -SENSELESS_COMPARISON
// !DIAGNOSTICS: -UNUSED_VARIABLE -SENSELESS_COMPARISON, -UNUSED_PARAMETER
// FILE: J.java
@@ -10,6 +10,20 @@ public class J {
@Nullable
public static J staticN;
public static J staticJ;
public static <T> T getAny() {
return null;
}
@NotNull
public static <T> T getNNAny() {
return (T) null;
}
@Nullable
public static <T> T getNAny() {
return null;
}
}
// FILE: k.kt
@@ -38,5 +52,15 @@ fun test() {
if (platformJ != null) {
platformJ <!USELESS_ELVIS!>?: J()<!>
}
takeNotNull(J.staticNN <!USELESS_ELVIS!>?: J()<!>)
takeNotNull(J.staticN ?: J())
takeNotNull(J.staticJ ?: J())
takeNotNull(J.getAny() ?: J())
takeNotNull(J.getNNAny() <!USELESS_ELVIS!>?: J()<!>)
takeNotNull(J.getNAny() ?: J())
val x = <!UNRESOLVED_REFERENCE!>unresolved<!> ?: null
}
fun takeNotNull(s: J) {}
@@ -1,5 +1,6 @@
package
public fun takeNotNull(/*0*/ s: J): kotlin.Unit
public fun test(): kotlin.Unit
public open class J {
@@ -12,4 +13,7 @@ public open class J {
public final var staticJ: J!
@org.jetbrains.annotations.Nullable public final var staticN: J?
@org.jetbrains.annotations.NotNull public final var staticNN: J
public open fun </*0*/ T : kotlin.Any!> getAny(): T!
@org.jetbrains.annotations.Nullable public open fun </*0*/ T : kotlin.Any!> getNAny(): T?
@org.jetbrains.annotations.NotNull public open fun </*0*/ T : kotlin.Any!> getNNAny(): T
}