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 3060c40d25a..a81f9e77a64 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -892,7 +892,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return baseTypeInfo; } DataFlowInfo dataFlowInfo = baseTypeInfo.getDataFlowInfo(); - if (isKnownToBeNotNull(baseExpression, baseType, context) && (!baseType.isError() || ErrorUtils.isUninferredParameter(baseType))) { + if (isKnownToBeNotNull(baseExpression, baseType, context)) { context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, TypeUtils.makeNotNullable(baseType))); } else { @@ -935,12 +935,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return facade.getTypeInfo(baseExpression, context, isStatement); } + // Returns `true` if warnings should be reported for left-hand side of elvis and not-null (!!) assertion private static boolean isKnownToBeNotNull( @NotNull KtExpression expression, @Nullable KotlinType ktType, @NotNull ExpressionTypingContext context ) { if (ktType == null) return false; + + if (ktType.isError() && !ErrorUtils.isUninferredParameter(ktType)) return false; + if (!TypeUtils.isNullableType(ktType)) return true; DataFlowValue dataFlowValue = createDataFlowValue(expression, ktType, context); diff --git a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt index 3898b6e6d18..28985842fc9 100644 --- a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt +++ b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt @@ -35,10 +35,14 @@ fun test() { takeNotNull(dependOn(dependOn(x)) ?: "") takeNotNull(dependOn(dependOn(x) as? String) ?: "") } + + takeNotNull(bar()!!) } inline fun reifiedNull(): T? = null fun testFrom13648() { takeNotNull(reifiedNull() ?: "") -} \ No newline at end of file +} + +fun bar() = unresolved \ 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 b1c1fd4f2d6..276a19a21b0 100644 --- a/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.txt +++ b/compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.txt @@ -1,5 +1,6 @@ package +public fun bar(): [ERROR : Error function type] public fun dependOn(/*0*/ x: T): T public fun notNull(): T public fun nullable(): T? diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.kt index 468a36456a8..3a0ed4efc32 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/elvis.kt @@ -61,6 +61,7 @@ fun test() { takeNotNull(J.getNAny() ?: J()) val x = unresolved ?: null + val y = unresolved.foo ?: return } fun takeNotNull(s: J) {}