[FIR] Implement NULL_FOR_NONNULL_TYPE diagnostics, fix tests

This commit is contained in:
Ivan Kochurkin
2021-04-13 20:17:48 +03:00
parent 9336e4b09b
commit 4353365968
54 changed files with 130 additions and 251 deletions
+1 -1
View File
@@ -26,6 +26,6 @@ open class B<V> : A<Any, V>() {
fun test_1(b: B<Int>, x: Int, inv: Inv<Int>) {
b.take(x)
b.take(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
b.take(<!NULL_FOR_NONNULL_TYPE!>null<!>)
b.takeInv(inv)
}
@@ -222,6 +222,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
parameter<ConeKotlinType>("actualType")
}
val NULL_FOR_NONNULL_TYPE by error<PsiElement> { }
val INAPPLICABLE_LATEINIT_MODIFIER by error<KtModifierListOwner>(PositioningStrategy.LATEINIT_MODIFIER) {
parameter<String>("reason")
}
@@ -336,7 +338,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error<KtTypeParameterList>()
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning<KtTypeParameter>()
val DYNAMIC_UPPER_BOUND by error<KtTypeReference>()
}
@@ -193,6 +193,7 @@ object FirErrors {
val NONE_APPLICABLE by error1<PsiElement, Collection<AbstractFirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val INAPPLICABLE_CANDIDATE by error1<PsiElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val ARGUMENT_TYPE_MISMATCH by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
val NULL_FOR_NONNULL_TYPE by error0<PsiElement>()
val INAPPLICABLE_LATEINIT_MODIFIER by error1<KtModifierListOwner, String>(SourceElementPositioningStrategies.LATEINIT_MODIFIER)
val VARARG_OUTSIDE_PARENTHESES by error0<KtExpression>()
val NAMED_ARGUMENTS_NOT_ALLOWED by error1<KtValueArgument, ForbiddenNamedArgumentsTarget>(SourceElementPositioningStrategies.NAME_OF_NAMED_ARGUMENT)
@@ -11,7 +11,9 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isComponentCall
import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.typeContext
@@ -43,7 +45,11 @@ object FirInitializerTypeMismatchChecker : FirPropertyChecker() {
// TODO: remove after fix of KT-45989
return
}
reporter.report(INITIALIZER_TYPE_MISMATCH.on(source, propertyType, expressionType), context)
if (initializer.isNullLiteral && propertyType.nullability == ConeNullability.NOT_NULL) {
reporter.reportOn(initializer.source, FirErrors.NULL_FOR_NONNULL_TYPE, context)
} else {
reporter.report(INITIALIZER_TYPE_MISMATCH.on(source, propertyType, expressionType), context)
}
}
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.ConeNullability
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isNullLiteral
object FirAssignmentTypeMismatchChecker : FirVariableAssignmentChecker() {
override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) {
val rValue = expression.rValue
if (rValue.isNullLiteral) {
val leftType = ((expression.lValue as? FirResolvedNamedReference)?.resolvedSymbol as? FirPropertySymbol)?.fir?.returnTypeRef
if (leftType?.coneType?.nullability == ConeNullability.NOT_NULL) {
reporter.reportOn(rValue.source, FirErrors.NULL_FOR_NONNULL_TYPE, context)
}
}
}
}
@@ -8,15 +8,15 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULL_FOR_NONNULL_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.isExhaustive
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.*
object FirFunctionReturnTypeMismatchChecker : FirReturnExpressionChecker() {
override fun check(expression: FirReturnExpression, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -33,7 +33,11 @@ object FirFunctionReturnTypeMismatchChecker : FirReturnExpressionChecker() {
if (!isSubtypeForTypeMismatch(typeContext, subtype = returnExpressionType, supertype = functionReturnType)) {
val returnExpressionSource = resultExpression.source ?: return
reporter.report(RETURN_TYPE_MISMATCH.on(returnExpressionSource, functionReturnType, returnExpressionType), context)
if (resultExpression.isNullLiteral && functionReturnType.nullability == ConeNullability.NOT_NULL) {
reporter.reportOn(resultExpression.source, NULL_FOR_NONNULL_TYPE, context)
} else {
reporter.report(RETURN_TYPE_MISMATCH.on(returnExpressionSource, functionReturnType, returnExpressionType), context)
}
}
}
}
@@ -142,6 +142,9 @@ private fun mapInapplicableCandidateError(
rootCause.expectedType,
rootCause.actualType
)
is NullForNotNullType -> FirErrors.NULL_FOR_NONNULL_TYPE.on(
rootCause.argument.source ?: source
)
is NonVarargSpread -> FirErrors.NON_VARARG_SPREAD.on(rootCause.argument.source?.getChild(KtTokens.MUL, depth = 1)!!)
is ArgumentPassedTwice -> FirErrors.ARGUMENT_PASSED_TWICE.on(rootCause.argument.source)
is TooManyArguments -> FirErrors.TOO_MANY_ARGUMENTS.on(rootCause.argument.source ?: source, rootCause.function)
@@ -30,7 +30,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirTypeParameterInQualifiedAccessChecker,
FirSealedClassConstructorCallChecker,
FirUninitializedEnumChecker,
FirFunInterfaceConstructorReferenceChecker,
FirFunInterfaceConstructorReferenceChecker,
)
override val functionCallCheckers: Set<FirFunctionCallChecker>
@@ -46,7 +46,8 @@ object CommonExpressionCheckers : ExpressionCheckers() {
override val variableAssignmentCheckers: Set<FirVariableAssignmentChecker>
get() = setOf(
FirValReassignmentViaBackingFieldChecker
FirValReassignmentViaBackingFieldChecker,
FirAssignmentTypeMismatchChecker
)
override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
@@ -353,6 +353,10 @@ private fun checkApplicabilityForArgumentType(
}
}
if (argument.isNullLiteral && actualExpectedType.nullability == ConeNullability.NOT_NULL) {
return NullForNotNullType(argument)
}
fun tryGetConeTypeThatCompatibleWithKtType(type: ConeKotlinType): ConeKotlinType {
if (type is ConeTypeVariableType) {
val originalTypeParameter =
@@ -374,7 +378,6 @@ private fun checkApplicabilityForArgumentType(
)
}
if (isReceiver && isDispatch) {
if (!expectedType.isNullable && argumentType.isMarkedNullable) {
sink.reportDiagnostic(InapplicableWrongReceiver(expectedType, argumentType))
@@ -92,3 +92,7 @@ class ArgumentTypeMismatch(
val actualType: ConeKotlinType,
val argument: FirExpression
) : ResolutionDiagnostic(INAPPLICABLE)
class NullForNotNullType(
val argument: FirExpression
) : ResolutionDiagnostic(INAPPLICABLE)
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.name.StandardClassIds
@@ -41,6 +43,7 @@ val FirTypeRef.isArrayType: Boolean
get() =
isBuiltinType(StandardClassIds.Array, false) ||
StandardClassIds.primitiveArrayTypeByElementType.values.any { isBuiltinType(it, false) }
val FirExpression.isNullLiteral: Boolean get() = this is FirConstExpression<*> && this.value == null && this.source != null
private val FirTypeRef.classLikeTypeOrNull: ConeClassLikeType?
get() = when (this) {
@@ -30,7 +30,7 @@ fun foo(expr: StringBuilder): Int {
fun unitShort() : Unit = Unit
fun unitShortConv() : Unit = <!RETURN_TYPE_MISMATCH!>1<!>
fun unitShortNull() : Unit = <!RETURN_TYPE_MISMATCH!>null<!>
fun unitShortNull() : Unit = <!NULL_FOR_NONNULL_TYPE!>null<!>
fun intEmpty() : Int {}
fun intShortInfer() = 1
@@ -23,8 +23,8 @@ fun <T> test(x: T) {
baz<Int?, String?>(null, null, ::foo)
baz<Int, String?>(<!ARGUMENT_TYPE_MISMATCH!>null<!>, null, ::foo)
baz<Int?, String>(null, <!ARGUMENT_TYPE_MISMATCH!>null<!>, ::foo)
baz<Int, String?>(<!NULL_FOR_NONNULL_TYPE!>null<!>, null, ::foo)
baz<Int?, String>(null, <!NULL_FOR_NONNULL_TYPE!>null<!>, ::foo)
baz(null, "", ::foo)
baz(1, null, ::foo)
baz(null, null, ::foo)
@@ -13,7 +13,7 @@ fun test2() = run {
inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> = null!!
fun test3(a: List<String>, b: List<Int>) = a.map {
if (it.length == 3) return <!RETURN_TYPE_MISMATCH!>null<!>
if (it.length == 3) return <!NULL_FOR_NONNULL_TYPE!>null<!>
if (it.length == 4) return <!RETURN_TYPE_MISMATCH!>""<!>
if (it.length == 4) return <!RETURN_TYPE_MISMATCH!>5<!>
if (it.length == 4) return b
@@ -4,7 +4,7 @@ fun <T> foo(x: T, y: T!!) = x!!
fun main() {
foo<String>("", "").length
foo<String>("", <!ARGUMENT_TYPE_MISMATCH!>null<!>).length
foo<String>("", <!NULL_FOR_NONNULL_TYPE!>null<!>).length
foo<String?>(null, "").length
foo<String?>(null, null).length
@@ -4,7 +4,7 @@ fun <T> foo(x: T, y: T!!): T!! = x ?: y
fun main() {
foo<String>("", "").length
foo<String>("", <!ARGUMENT_TYPE_MISMATCH!>null<!>).length
foo<String>("", <!NULL_FOR_NONNULL_TYPE!>null<!>).length
foo<String?>(null, "")<!UNSAFE_CALL!>.<!>length
foo<String?>(null, null)<!UNSAFE_CALL!>.<!>length
@@ -1,19 +0,0 @@
// !CHECK_TYPE
interface A {
val foo: Any?
}
interface C: A {
override val foo: String?
}
interface B: A {
override var foo: String
}
fun <T> test(a: T) where T : B, T : C {
a.foo = ""
a.foo = null
a.foo.checkType { _<String>() }
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !CHECK_TYPE
interface A {
@@ -1,35 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
fun <E> bar(x: E) {}
fun <T> foo(): T {
val x1: T = <!INITIALIZER_TYPE_MISMATCH!>null<!>
val x2: T? = null
bar<T>(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
bar<T?>(null)
return <!RETURN_TYPE_MISMATCH!>null<!>
}
fun <T> baz(): T? = null
fun <T> foobar(): T = <!RETURN_TYPE_MISMATCH!>null<!>
class A<F> {
fun xyz(x: F) {}
fun foo(): F {
val x1: F = <!INITIALIZER_TYPE_MISMATCH!>null<!>
val x2: F? = null
xyz(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
bar<F?>(null)
return <!RETURN_TYPE_MISMATCH!>null<!>
}
fun baz(): F? = null
fun foobar(): F = <!RETURN_TYPE_MISMATCH!>null<!>
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
fun <E> bar(x: E) {}
@@ -9,6 +9,6 @@ interface Tr<T> {
fun test(t: Tr<*>) {
t.v = null!!
t.v = ""
t.v = null
t.v = <!NULL_FOR_NONNULL_TYPE!>null<!>
t.v checkType { _<Any?>() }
}
@@ -8,7 +8,7 @@ fun <T> bar(a: T, b: Map<T, String>) = b.get(a)
fun test(a: Int) {
foo(a, null)
bar(a, <!ARGUMENT_TYPE_MISMATCH!>null<!>)
bar(a, <!NULL_FOR_NONNULL_TYPE!>null<!>)
}
fun test1(a: Int) {
foo(a, throw Exception())
@@ -1,23 +0,0 @@
// !CHECK_TYPE
// FILE: A.java
public class A {}
// FILE: X.java
import org.jetbrains.annotations.NotNull;
public class X<T> {
@NotNull T fooN() {return null;}
void barN(@NotNull T a) {}
}
// FILE: Y.java
public class Y extends X<String> {
}
// FILE: test.kt
fun main() {
checkSubtype<Any>(Y().fooN())
Y().barN(<!ARGUMENT_TYPE_MISMATCH!>null<!>);
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !CHECK_TYPE
// FILE: A.java
public class A {}
@@ -1,23 +0,0 @@
// !CHECK_TYPE
// FILE: A.java
public class A {}
// FILE: X.java
import org.jetbrains.annotations.NotNull;
public class X<T> {
@NotNull T fooN() {return null;}
void barN(@NotNull T a) {}
}
// FILE: Y.java
public class Y extends X<A> {
}
// FILE: test.kt
fun main() {
checkSubtype<Any>(Y().fooN())
Y().barN(<!ARGUMENT_TYPE_MISMATCH!>null<!>);
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !CHECK_TYPE
// FILE: A.java
public class A {}
@@ -100,7 +100,7 @@ public class SpecializedMap extends AbstractSpecializedMap {
// FILE: main.kt
fun foo(x: SpecializedMap) {
x.containsKey(1)
x.containsKey(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
x.containsKey(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.<!OVERLOAD_RESOLUTION_AMBIGUITY!>get<!>(2)
x.<!NONE_APPLICABLE!>get<!>(null)
@@ -20,5 +20,5 @@ class In<in F> {
fun test() {
A.foo().x() checkType { _<Any?>() }
A.bar().y(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
A.bar().y(<!NULL_FOR_NONNULL_TYPE!>null<!>)
}
@@ -1,16 +0,0 @@
// FILE: p/J.java
package p;
public class J {
public void _int(int s) {}
}
// FILE: k.kt
import p.*
fun test() {
J()._int(1)
J()._int(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: p/J.java
package p;
@@ -1,26 +0,0 @@
// FILE: A.java
import java.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class A<T> {
public static A<String> create() {
return null;
}
public void bar(@NotNull T x) {
}
}
// FILE: k.kt
fun test() {
A.create().bar(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
A.create().bar("")
A<String>().bar(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
A<String?>().bar(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
A<String?>().bar("")
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: A.java
import java.util.*;
@@ -33,9 +33,9 @@ class C2 : A<String?>() {
}
fun test() {
B1().bar(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
B2().bar(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
B1().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
B2().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
C1().bar(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
C1().bar(<!NULL_FOR_NONNULL_TYPE!>null<!>)
}
@@ -22,6 +22,6 @@ val doubleList: List<Double?> = null!!
fun main() {
Test.rawField.foo("", <!ARGUMENT_TYPE_MISMATCH!>doubleList<!>)
Test.rawField.foo(<!ARGUMENT_TYPE_MISMATCH!>null<!>, <!ARGUMENT_TYPE_MISMATCH!>doubleList<!>)
Test.DerivedRawA().foo(<!ARGUMENT_TYPE_MISMATCH!>null<!>, <!ARGUMENT_TYPE_MISMATCH!>doubleList<!>)
Test.rawField.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!ARGUMENT_TYPE_MISMATCH!>doubleList<!>)
Test.DerivedRawA().foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!ARGUMENT_TYPE_MISMATCH!>doubleList<!>)
}
@@ -14,7 +14,7 @@ interface B: A {
fun test(a: A) {
if (a is B && a is C) {
a.foo = ""
a.foo = null
a.foo = <!NULL_FOR_NONNULL_TYPE!>null<!>
a.foo.checkType { _<String>() }
}
@@ -23,8 +23,8 @@ fun foo(k: KotlinClass) {
k.setSomething4("")
k.something4 += ""
k.setSomething4(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
k.something4 = null
k.setSomething4(<!NULL_FOR_NONNULL_TYPE!>null<!>)
k.something4 = <!NULL_FOR_NONNULL_TYPE!>null<!>
useString(k.getSomething5())
useString(k.something5)
@@ -1,13 +0,0 @@
// !WITH_NEW_INFERENCE
// FILE: KotlinFile.kt
fun foo(javaInterface: JavaInterface) {
javaInterface.doIt(<!ARGUMENT_TYPE_MISMATCH!>null<!>) { }
javaInterface.doIt("", <!ARGUMENT_TYPE_MISMATCH!>null<!>)
}
// FILE: JavaInterface.java
import org.jetbrains.annotations.*;
public interface JavaInterface {
void doIt(@NotNull String s, @NotNull Runnable runnable);
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !WITH_NEW_INFERENCE
// FILE: KotlinFile.kt
fun foo(javaInterface: JavaInterface) {
@@ -32,7 +32,7 @@ abstract class MyIt7 : Iterator<String> {
fun foo(x: Iterator<String>, y: Iterator<String?>) {
x.forEachRemaining(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
x.forEachRemaining(<!NULL_FOR_NONNULL_TYPE!>null<!>)
x.forEachRemaining { it -> it.length }
x.forEachRemaining { it -> it?.length }
@@ -19,7 +19,7 @@ class KotlinMap2 : java.util.AbstractMap<String, Int>() {
fun foo(x: MutableMap<String, Int>, y: java.util.HashMap<String, Int>, z: java.util.AbstractMap<String, Int>) {
x.remove("", 1)
x.remove("", <!ARGUMENT_TYPE_MISMATCH!>""<!>)
x.remove("", <!ARGUMENT_TYPE_MISMATCH!>null<!>)
x.remove("", <!NULL_FOR_NONNULL_TYPE!>null<!>)
y.remove("", 1)
y.remove("", <!ARGUMENT_TYPE_MISMATCH!>""<!>)
@@ -21,7 +21,7 @@ class Pair<X, Y>(val x: X, val y: Y)
typealias PL<T> = Pair<T, List<T>>
typealias PN<T> = Pair<T, Num<T>>
val test5 = PL(1, <!ARGUMENT_TYPE_MISMATCH!>null<!>)
val test5 = PL(1, <!NULL_FOR_NONNULL_TYPE!>null<!>)
class Foo<T>(val p: Pair<T, T>)
@@ -1,24 +0,0 @@
// !WITH_NEW_INFERENCE
// NI_EXPECTED_FILE
object ObjectWithInvoke {
operator fun invoke() = this
}
class ClassWithCompanionObjectWithInvoke {
companion object {
operator fun invoke(x: Any) = x
}
}
typealias WI = ObjectWithInvoke
typealias CWI = ClassWithCompanionObjectWithInvoke
val test1 = WI()
val test2 = WI(<!TOO_MANY_ARGUMENTS!>null<!>)
val test3 = CWI()
val test4 = CWI("")
val test5 = CWI(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
val test5a = ClassWithCompanionObjectWithInvoke(<!ARGUMENT_TYPE_MISMATCH!>null<!>)
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !WITH_NEW_INFERENCE
// NI_EXPECTED_FILE
@@ -1,24 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !DIAGNOSTICS: -UNUSED_VARIABLE
import kotlin.experimental.ExperimentalTypeInference
@OptIn(ExperimentalTypeInference::class)
fun <E> myBuildList(@BuilderInference builderAction: MutableList<E>.() -> Unit) {
ArrayList<E>().builderAction()
}
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val newList1 = myBuildList {
addAll(
listOf(1).map { Foo(<!ARGUMENT_TYPE_MISMATCH!>null<!>) }
)
}
val newList2 = buildList {
addAll(listOf(1,2,3).map{ Foo(<!ARGUMENT_TYPE_MISMATCH!>null<!>) })
}
}
class Foo(val notNullProp: String)
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !DIAGNOSTICS: -UNUSED_VARIABLE
@@ -7,4 +7,4 @@ fun foo(c : Collection<String>) = {
}
fun bar() : String? = null
fun zoo(s : String) : Boolean = true
fun zoo(s : String) : Boolean = true
@@ -4,44 +4,44 @@
// TESTCASE NUMBER: 1
fun case_1() {
val x: Int = <!INITIALIZER_TYPE_MISMATCH!>null<!>
val x: Int = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
// TESTCASE NUMBER: 2
fun case_2() {
val x: Any = <!INITIALIZER_TYPE_MISMATCH!>null<!>
val x: Any = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
// TESTCASE NUMBER: 3
fun case_3() {
val x: Nothing = <!INITIALIZER_TYPE_MISMATCH!>null<!>
val x: Nothing = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
// TESTCASE NUMBER: 4
fun case_4() {
var x: Int = <!INITIALIZER_TYPE_MISMATCH!>null<!>
var x: Int = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
// TESTCASE NUMBER: 5
fun case_5() {
var x: Any = <!INITIALIZER_TYPE_MISMATCH!>null<!>
var x: Any = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
// TESTCASE NUMBER: 6
fun case_6() {
var x: Nothing = <!INITIALIZER_TYPE_MISMATCH!>null<!>
var x: Nothing = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
// TESTCASE NUMBER: 7
fun case_7() {
val x: Int
x = null
x = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
// TESTCASE NUMBER: 8
fun case_8() {
var x: Int = 10
x = null
x = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
// TESTCASE NUMBER: 9
@@ -43,7 +43,7 @@ class Case8 {
}
// TESTCASE NUMBER: 9
fun case_9(): Any = <!RETURN_TYPE_MISMATCH!>null<!>
fun case_9(): Any = <!NULL_FOR_NONNULL_TYPE!>null<!>
// TESTCASE NUMBER: 10
fun case_10(x: Int, y: Boolean): Any = <!RETURN_TYPE_MISMATCH!>if (y) x else null<!>
@@ -57,10 +57,10 @@ class Case12 {
var y: Any
var z: Any
init {
x = null
y = null
x = <!NULL_FOR_NONNULL_TYPE!>null<!>
y = <!NULL_FOR_NONNULL_TYPE!>null<!>
z = 10
z = null
z = <!NULL_FOR_NONNULL_TYPE!>null<!>
}
}
@@ -6,7 +6,7 @@ import kotlin.contracts.*
// TESTCASE NUMBER: 1
fun case_1(): Boolean? {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returnsNotNull() implies (<!ARGUMENT_TYPE_MISMATCH!>null<!>)<!> }
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returnsNotNull() implies (<!NULL_FOR_NONNULL_TYPE!>null<!>)<!> }
return true
}
@@ -739,6 +739,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.NULL_FOR_NONNULL_TYPE) { firDiagnostic ->
NullForNonnullTypeImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.INAPPLICABLE_LATEINIT_MODIFIER) { firDiagnostic ->
InapplicableLateinitModifierImpl(
firDiagnostic.a,
@@ -532,6 +532,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val actualType: KtType
}
abstract class NullForNonnullType : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = NullForNonnullType::class
}
abstract class InapplicableLateinitModifier : KtFirDiagnostic<KtModifierListOwner>() {
override val diagnosticClass get() = InapplicableLateinitModifier::class
abstract val reason: String
@@ -851,6 +851,13 @@ internal class ArgumentTypeMismatchImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class NullForNonnullTypeImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.NullForNonnullType(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class InapplicableLateinitModifierImpl(
override val reason: String,
firDiagnostic: FirPsiDiagnostic<*>,
+1 -1
View File
@@ -27,7 +27,7 @@ fun foo(expr: StringBuilder): Int {
fun unitShort() : Unit = Unit
fun unitShortConv() : Unit = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Unit, actual kotlin/Int">1</error>
fun unitShortNull() : Unit = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Unit, actual kotlin/Nothing?">null</error>
fun unitShortNull() : Unit = <error descr="[NULL_FOR_NONNULL_TYPE] ">null</error>
fun intEmpty() : Int {}
fun intShortInfer() = 1
+2 -2
View File
@@ -3,8 +3,8 @@ package test
annotation class A(val value: String)
@A(<error descr="[ARGUMENT_TYPE_MISMATCH] Argument type mismatch: actual type is kotlin/Nothing? but kotlin/String was expected">null</error>)
@A(<error descr="[NULL_FOR_NONNULL_TYPE] ">null</error>)
fun foo() {}
@A(<error descr="[ARGUMENT_TYPE_MISMATCH] Argument type mismatch: actual type is kotlin/Nothing? but kotlin/String was expected">null</error>)
@A(<error descr="[NULL_FOR_NONNULL_TYPE] ">null</error>)
class B