[FIR] Implement checker for value parameter default value type mismatch
#KT-58901 Fixed
This commit is contained in:
committed by
Space Team
parent
cfc824f9f2
commit
028921ade1
+3
-1
@@ -174,5 +174,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
)
|
||||
|
||||
override val valueParameterCheckers: Set<FirValueParameterChecker>
|
||||
get() = setOf()
|
||||
get() = setOf(
|
||||
FirValueParameterDefaultValueTypeMismatchChecker,
|
||||
)
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.declaration
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkTypeMismatch
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
|
||||
object FirValueParameterDefaultValueTypeMismatchChecker : FirValueParameterChecker() {
|
||||
override fun check(declaration: FirValueParameter, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val defaultValue = declaration.defaultValue ?: return
|
||||
val source = requireNotNull(declaration.source)
|
||||
val parameterType = declaration.returnTypeRef.coneType
|
||||
|
||||
checkTypeMismatch(parameterType, null, defaultValue, context, source, reporter, true)
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -945,11 +945,14 @@ object PositioningStrategies {
|
||||
|
||||
val PROPERTY_INITIALIZER: PositioningStrategy<KtNamedDeclaration> = object : PositioningStrategy<KtNamedDeclaration>() {
|
||||
override fun mark(element: KtNamedDeclaration): List<TextRange> {
|
||||
return markElement(when (element) {
|
||||
is KtProperty -> element.initializer ?: element
|
||||
is KtParameter -> element.typeReference ?: element
|
||||
else -> element
|
||||
})
|
||||
return markElement(
|
||||
when (element) {
|
||||
is KtProperty -> element.initializer ?: element
|
||||
// Type reference is used as a target for loop variable type mismatches
|
||||
is KtParameter -> element.defaultValue ?: element.typeReference ?: element
|
||||
else -> element
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -19,6 +19,7 @@ annotation class Foo(
|
||||
val a: IntArray = [],
|
||||
val b: IntArray = [1, 2, 3],
|
||||
val c: Array<String> = ["/"],
|
||||
@Suppress("INITIALIZER_TYPE_MISMATCH") // Remove after KT-59581 is fixed
|
||||
val d: Array<KClass<*>> = [Int::class, Array<Int>::class],
|
||||
val e: DoubleArray = [1.0]
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
val x = ""
|
||||
|
||||
fun bar(x : Int = "", y : Int = x, z : String = y) {
|
||||
fun bar(x : Int = <!INITIALIZER_TYPE_MISMATCH!>""<!>, y : Int = x, z : String = <!INITIALIZER_TYPE_MISMATCH!>y<!>) {
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ fun bar(x : Int = "", y : Int = x, z : String = y) {
|
||||
|
||||
class A(x : Int = <!UNINITIALIZED_PARAMETER!>y<!>, y : Int = x) { // None of the references is resolved, no types checked
|
||||
constructor(x : Int = <!UNINITIALIZED_PARAMETER!>x<!>) : this(x, x)
|
||||
fun foo(bool: Boolean, a: Int = <!UNINITIALIZED_PARAMETER!>b<!>, b: String = a) {}
|
||||
fun foo(bool: Boolean, a: Int = <!INITIALIZER_TYPE_MISMATCH, UNINITIALIZED_PARAMETER!>b<!>, b: String = <!INITIALIZER_TYPE_MISMATCH!>a<!>) {}
|
||||
}
|
||||
|
||||
val z = 3
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
object A1<!CONSTRUCTOR_IN_OBJECT!>()<!> {
|
||||
<!CONSTRUCTOR_IN_OBJECT!>constructor(x: Int = "", y: Int)<!> : <!UNRESOLVED_REFERENCE!>this<!>() {
|
||||
<!CONSTRUCTOR_IN_OBJECT!>constructor(x: Int = <!INITIALIZER_TYPE_MISMATCH!>""<!>, y: Int)<!> : <!UNRESOLVED_REFERENCE!>this<!>() {
|
||||
x + y
|
||||
}
|
||||
}
|
||||
|
||||
object A2 public <!CONSTRUCTOR_IN_OBJECT!>constructor(private val prop: Int)<!> {
|
||||
<!CONSTRUCTOR_IN_OBJECT!>constructor(x: Int = "", y: Int)<!> : <!NONE_APPLICABLE!>this<!>(x * y) {
|
||||
<!CONSTRUCTOR_IN_OBJECT!>constructor(x: Int = <!INITIALIZER_TYPE_MISMATCH!>""<!>, y: Int)<!> : <!NONE_APPLICABLE!>this<!>(x * y) {
|
||||
x + y
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ annotation class Ann4(vararg val a: String = ["/"])
|
||||
annotation class Ann5(vararg val a: Ann4 = [])
|
||||
annotation class Ann6(vararg val a: Ann4 = [Ann4(*["a", "b"])])
|
||||
|
||||
annotation class Ann7(vararg val a: Long = [1L, null, ""])
|
||||
annotation class Ann7(vararg val a: Long = <!INITIALIZER_TYPE_MISMATCH!>[1L, null, ""]<!>)
|
||||
|
||||
@Ann1(*[])
|
||||
fun test1_0() {}
|
||||
|
||||
+4
-4
@@ -5,9 +5,9 @@ annotation class Foo(
|
||||
)
|
||||
|
||||
annotation class Bar(
|
||||
val a: Array<String> = [' '],
|
||||
val a: Array<String> = <!INITIALIZER_TYPE_MISMATCH!>[' ']<!>,
|
||||
val b: Array<String> = ["", <!EMPTY_CHARACTER_LITERAL!>''<!>],
|
||||
val c: Array<String> = [1]
|
||||
val c: Array<String> = <!INITIALIZER_TYPE_MISMATCH!>[1]<!>
|
||||
)
|
||||
|
||||
annotation class Base(
|
||||
@@ -18,6 +18,6 @@ annotation class Base(
|
||||
)
|
||||
|
||||
annotation class Err(
|
||||
val a: IntArray = [1L],
|
||||
val b: Array<String> = [1]
|
||||
val a: IntArray = <!INITIALIZER_TYPE_MISMATCH!>[1L]<!>,
|
||||
val b: Array<String> = <!INITIALIZER_TYPE_MISMATCH!>[1]<!>
|
||||
)
|
||||
|
||||
compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesWithConstantsInAnnotation.fir.kt
Vendored
+3
-3
@@ -17,7 +17,7 @@ annotation class Bar(
|
||||
)
|
||||
|
||||
annotation class Baz(
|
||||
val a: IntArray = [null],
|
||||
val b: IntArray = [1, null, 2],
|
||||
val c: IntArray = [<!NO_THIS!>this<!>]
|
||||
val a: IntArray = <!INITIALIZER_TYPE_MISMATCH!>[null]<!>,
|
||||
val b: IntArray = <!INITIALIZER_TYPE_MISMATCH!>[1, null, 2]<!>,
|
||||
val c: IntArray = <!INITIALIZER_TYPE_MISMATCH!>[<!NO_THIS!>this<!>]<!>
|
||||
)
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
annotation class A(val a: IntArray = <!TYPE_MISMATCH!>arrayOf(1)<!>)
|
||||
annotation class A(val a: IntArray = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>arrayOf(1)<!>)
|
||||
annotation class B(val a: IntArray = intArrayOf(1))
|
||||
|
||||
compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationArgumentEquality.fir.kt
Vendored
+88
@@ -0,0 +1,88 @@
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
expect annotation class Primitives(
|
||||
val z: Boolean = true,
|
||||
val c: Char = 'c',
|
||||
val b: Byte = 42.toByte(),
|
||||
val s: Short = (-1).toShort(),
|
||||
val i: Int = -42,
|
||||
val f: Float = 2.72f,
|
||||
val j: Long = 123456789123456789L,
|
||||
val d: Double = 3.14159265358979
|
||||
)
|
||||
|
||||
expect annotation class PrimitiveArrays(
|
||||
val z: BooleanArray = [true],
|
||||
val c: CharArray = ['c'],
|
||||
val b: ByteArray = [42.toByte()],
|
||||
val s: ShortArray = [(-1).toShort()],
|
||||
val i: IntArray = [-42],
|
||||
val f: FloatArray = [2.72f],
|
||||
val j: LongArray = [123456789123456789L],
|
||||
val d: DoubleArray = [3.14159265358979]
|
||||
)
|
||||
|
||||
enum class En { A, B }
|
||||
|
||||
annotation class Anno(val value: String = "Anno")
|
||||
|
||||
expect annotation class Classes(
|
||||
val s: String = "OK",
|
||||
val e: En = En.B,
|
||||
// TODO: this does not work at the moment because AnnotationDescriptor subclasses do not implement equals correctly
|
||||
// val a: Anno = Anno(),
|
||||
val k: KClass<*> = List::class
|
||||
)
|
||||
|
||||
expect annotation class ClassArrays(
|
||||
val s: Array<String> = ["OK"],
|
||||
val e: Array<En> = [En.B],
|
||||
// val a: Array<Anno> = [Anno()],
|
||||
val k: Array<KClass<*>> = <!INITIALIZER_TYPE_MISMATCH!>[List::class]<!>, // KT-59581
|
||||
vararg val v: Int = [42]
|
||||
)
|
||||
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
actual annotation class Primitives(
|
||||
actual val z: Boolean = true,
|
||||
actual val c: Char = 'c',
|
||||
actual val b: Byte = 42.toByte(),
|
||||
actual val s: Short = (-1).toShort(),
|
||||
actual val i: Int = -42,
|
||||
actual val f: Float = 2.72f,
|
||||
actual val j: Long = 123456789123456789L,
|
||||
actual val d: Double = 3.14159265358979
|
||||
)
|
||||
|
||||
actual annotation class PrimitiveArrays(
|
||||
actual val z: BooleanArray = [true],
|
||||
actual val c: CharArray = ['c'],
|
||||
actual val b: ByteArray = [42.toByte()],
|
||||
actual val s: ShortArray = [(-1).toShort()],
|
||||
actual val i: IntArray = [-42],
|
||||
actual val f: FloatArray = [2.72f],
|
||||
actual val j: LongArray = [123456789123456789L],
|
||||
actual val d: DoubleArray = [3.14159265358979]
|
||||
)
|
||||
|
||||
actual annotation class Classes(
|
||||
actual val s: String = "OK",
|
||||
actual val e: En = En.B,
|
||||
// actual val a: Anno = Anno(),
|
||||
actual val k: KClass<*> = List::class
|
||||
)
|
||||
|
||||
actual annotation class ClassArrays(
|
||||
actual val s: Array<String> = ["OK"],
|
||||
actual val e: Array<En> = [En.B],
|
||||
// actual val a: Array<Anno> = [Anno()],
|
||||
actual val k: Array<KClass<*>> = <!INITIALIZER_TYPE_MISMATCH!>[List::class]<!>,
|
||||
actual vararg val v: Int = [42]
|
||||
)
|
||||
Vendored
+1
-2
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
@@ -42,7 +41,7 @@ expect annotation class ClassArrays(
|
||||
val s: Array<String> = ["OK"],
|
||||
val e: Array<En> = [En.B],
|
||||
// val a: Array<Anno> = [Anno()],
|
||||
val k: Array<KClass<*>> = [List::class],
|
||||
val k: Array<KClass<*>> = [List::class], // KT-59581
|
||||
vararg val v: Int = [42]
|
||||
)
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -21,7 +21,7 @@ fun test() {
|
||||
// platform type with no annotation
|
||||
val platformJ = J.staticJ
|
||||
|
||||
fun foo(p: J = platformNN, p1: J = platformN, p2: J = platformJ) {}
|
||||
fun foo(p: J = platformNN, p1: J = <!INITIALIZER_TYPE_MISMATCH!>platformN<!>, p2: J = platformJ) {}
|
||||
|
||||
fun foo1(p: J? = platformNN, p1: J? = platformN, p2: J? = platformJ) {}
|
||||
}
|
||||
Vendored
+1
-1
@@ -3,6 +3,6 @@ open class B(x: Int) {
|
||||
fun foo() = 1
|
||||
}
|
||||
class A : B {
|
||||
constructor(x: Int, y: Int = <!TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>foo<!>() <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.foo() + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.foo()<!>) :
|
||||
constructor(x: Int, y: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>foo<!>() <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.foo() + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.foo()<!>) :
|
||||
super(<!ARGUMENT_TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>foo<!>() <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.foo() + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.foo()<!>)
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,6 +4,6 @@ open class B(x: Int) {
|
||||
}
|
||||
class A : B {
|
||||
override fun foo() = 2
|
||||
constructor(x: Int, y: Int = <!TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>foo<!>() <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.foo() + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.foo()<!>) :
|
||||
constructor(x: Int, y: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>foo<!>() <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.foo() + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.foo()<!>) :
|
||||
super(<!ARGUMENT_TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>foo<!>() <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.foo() + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.foo()<!>)
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
open class B(val prop: Int)
|
||||
class A : B {
|
||||
constructor(x: Int, y: Int = <!TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>prop<!> <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.prop + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.prop<!>) :
|
||||
constructor(x: Int, y: Int = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>prop<!> <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.prop + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.prop<!>) :
|
||||
super(<!ARGUMENT_TYPE_MISMATCH!>x + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>prop<!> <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.prop + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>super<!>.prop<!>)
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -65,4 +65,4 @@ fun case_10(x: Int?) {
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 11
|
||||
fun case_11(x: Int?, y: Int = x) = null
|
||||
fun case_11(x: Int?, y: Int = <!INITIALIZER_TYPE_MISMATCH!>x<!>) = null
|
||||
|
||||
Vendored
+6
-6
@@ -11,29 +11,29 @@
|
||||
*/
|
||||
|
||||
// TESTCASE NUMBER: 1
|
||||
fun case_1(x: Int = null) {
|
||||
fun case_1(x: Int = <!NULL_FOR_NONNULL_TYPE!>null<!>) {
|
||||
println(x)
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun case_2(x: Any = null) {
|
||||
fun case_2(x: Any = <!NULL_FOR_NONNULL_TYPE!>null<!>) {
|
||||
println(x)
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun case_3(x: Nothing = null) {
|
||||
fun case_3(x: Nothing = <!NULL_FOR_NONNULL_TYPE!>null<!>) {
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(x)
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 4
|
||||
class Case4(x: Int = null)
|
||||
class Case4(x: Int = <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
|
||||
// TESTCASE NUMBER: 5
|
||||
class Case5 constructor(x: Any = null)
|
||||
class Case5 constructor(x: Any = <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
|
||||
// TESTCASE NUMBER: 6
|
||||
class Case6 {
|
||||
fun foo(x: Nothing = null) {}
|
||||
fun foo(x: Nothing = <!NULL_FOR_NONNULL_TYPE!>null<!>) {}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 7
|
||||
|
||||
Vendored
+5
-5
@@ -11,28 +11,28 @@
|
||||
*/
|
||||
|
||||
// TESTCASE NUMBER: 1
|
||||
fun <T: Any> case_1(x: T = null) {
|
||||
fun <T: Any> case_1(x: T = <!NULL_FOR_NONNULL_TYPE!>null<!>) {
|
||||
println(x)
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun <T: K, K: Number> case_2(x: T = null) {
|
||||
fun <T: K, K: Number> case_2(x: T = <!NULL_FOR_NONNULL_TYPE!>null<!>) {
|
||||
println(x)
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun <K: Number> case_3() {
|
||||
class Case4<T: K> (x: T = null)
|
||||
class Case4<T: K> (x: T = <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 4
|
||||
fun <T> case_4() {
|
||||
class Case4(x: T = null)
|
||||
class Case4(x: T = <!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 5
|
||||
fun <T, K> case_5(x: T) where T: Number?, K: Number {
|
||||
if (x == null) {
|
||||
class Case5 constructor(y: K = x)
|
||||
class Case5 constructor(y: K = <!INITIALIZER_TYPE_MISMATCH!>x<!>)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user