From 4aa808b25035769f2cc7865c4f11a2103402ea91 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Fri, 31 Mar 2017 17:15:07 +0300 Subject: [PATCH] Fix warning about useless elvis when generics are involved #KT-13648 Fixed --- .../BasicExpressionTypingVisitor.java | 4 +-- .../tests/nullableTypes/uselessElvis.kt | 31 +++++++++++++++++-- .../tests/nullableTypes/uselessElvis.txt | 7 +++++ .../nullabilityWarnings/elvis.kt | 26 +++++++++++++++- .../nullabilityWarnings/elvis.txt | 4 +++ 5 files changed, 67 insertions(+), 5 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 12173063736..22d04b2ac66 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -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)) { diff --git a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt index 12e6a1af108..3898b6e6d18 100644 --- a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt +++ b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt @@ -1,4 +1,4 @@ -// For KT-3491 +// !DIAGNOSTICS: -UNUSED_PARAMETER, -SENSELESS_COMPARISON, -DEBUG_INFO_SMARTCAST fun test1(t: Any?): Any { return t as T ?: "" @@ -10,8 +10,35 @@ fun test2(t: Any?): Any { fun test3(t: Any?): Any { if (t != null) { - return t ?: "" + return t ?: "" } return 1 +} + +fun takeNotNull(s: String) {} +fun notNull(): T = TODO() +fun nullable(): T? = null +fun dependOn(x: T) = x + +fun test() { + takeNotNull(notNull() ?: "") + takeNotNull(nullable() ?: "") + + val x: String? = null + takeNotNull(dependOn(x) ?: "") + takeNotNull(dependOn(dependOn(x)) ?: "") + takeNotNull(dependOn(dependOn(x as String)) ?: "") + + if (x != null) { + takeNotNull(dependOn(x) ?: "") + takeNotNull(dependOn(dependOn(x)) ?: "") + takeNotNull(dependOn(dependOn(x) as? String) ?: "") + } +} + +inline fun reifiedNull(): T? = null + +fun testFrom13648() { + takeNotNull(reifiedNull() ?: "") } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.txt b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.txt index 54f7693e792..b1c1fd4f2d6 100644 --- a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.txt +++ b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.txt @@ -1,5 +1,12 @@ package +public fun dependOn(/*0*/ x: T): T +public fun notNull(): T +public fun nullable(): T? +public inline fun reifiedNull(): T? +public fun takeNotNull(/*0*/ s: kotlin.String): kotlin.Unit +public fun test(): kotlin.Unit public fun test1(/*0*/ t: kotlin.Any?): kotlin.Any public fun test2(/*0*/ t: kotlin.Any?): kotlin.Any public fun test3(/*0*/ t: kotlin.Any?): kotlin.Any +public fun testFrom13648(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.kt index 6dcd4b4aeaa..468a36456a8 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.kt @@ -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 getAny() { + return null; + } + + @NotNull + public static T getNNAny() { + return (T) null; + } + + @Nullable + public static T getNAny() { + return null; + } } // FILE: k.kt @@ -38,5 +52,15 @@ fun test() { if (platformJ != null) { platformJ ?: J() } + + takeNotNull(J.staticNN ?: J()) + takeNotNull(J.staticN ?: J()) + takeNotNull(J.staticJ ?: J()) + takeNotNull(J.getAny() ?: J()) + takeNotNull(J.getNNAny() ?: J()) + takeNotNull(J.getNAny() ?: J()) + + val x = unresolved ?: null } +fun takeNotNull(s: J) {} diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.txt index c33963afb31..0536635b974 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.txt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.txt @@ -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 getAny(): T! + @org.jetbrains.annotations.Nullable public open fun getNAny(): T? + @org.jetbrains.annotations.NotNull public open fun getNNAny(): T }