FIR: Fix false positive INAPPLICABLE_INFIX_MODIFIER
This commit is contained in:
+12
-1
@@ -10,4 +10,15 @@ infix class A
|
||||
|
||||
infix typealias B = A
|
||||
|
||||
infix val x = 1
|
||||
infix val x = 1
|
||||
|
||||
class C {
|
||||
infix fun good(x: Int) {}
|
||||
infix fun Int.goodAsWell(x: Int) {}
|
||||
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun Int.foo(x: Int, y: Int) {}<!>
|
||||
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun Int.bar() {}<!>
|
||||
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun baz(x: Int, y: Int) {}<!>
|
||||
}
|
||||
|
||||
@@ -16,3 +16,24 @@ FILE: infixFunctions.kt
|
||||
public final typealias B = R|A|
|
||||
public final val x: R|kotlin/Int| = Int(1)
|
||||
public get(): R|kotlin/Int|
|
||||
public final class C : R|kotlin/Any| {
|
||||
public constructor(): R|C| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final infix fun good(x: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public final infix fun R|kotlin/Int|.goodAsWell(x: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public final infix fun R|kotlin/Int|.foo(x: R|kotlin/Int|, y: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public final infix fun R|kotlin/Int|.bar(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public final infix fun baz(x: R|kotlin/Int|, y: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
interface List<out T : Any> {
|
||||
operator fun get(index: Int): T
|
||||
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun concat(other: List<T>): List<T><!>
|
||||
infix fun concat(other: List<T>): List<T>
|
||||
}
|
||||
|
||||
typealias StringList = List<out String>
|
||||
|
||||
+11
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
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.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.isInfix
|
||||
@@ -16,7 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.isInfix
|
||||
object FirInfixFunctionDeclarationChecker : FirDeclarationChecker<FirMemberDeclaration>() {
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration is FirSimpleFunction && declaration.isInfix) {
|
||||
if (declaration.valueParameters.size != 1 || declaration.receiverTypeRef == null) {
|
||||
if (declaration.valueParameters.size != 1 || !hasExtensionOrDispatchReceiver(declaration, context)) {
|
||||
reporter.report(declaration.source)
|
||||
}
|
||||
return
|
||||
@@ -26,7 +27,15 @@ object FirInfixFunctionDeclarationChecker : FirDeclarationChecker<FirMemberDecla
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasExtensionOrDispatchReceiver(
|
||||
function: FirSimpleFunction,
|
||||
context: CheckerContext
|
||||
): Boolean {
|
||||
if (function.receiverTypeRef != null) return true
|
||||
return context.containingDeclarations.lastOrNull() is FirClass<*>
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
||||
source?.let { report(FirErrors.INAPPLICABLE_INFIX_MODIFIER.on(it, "Inapplicable infix modifier")) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,5 @@ infix fun String.on(predicate : (s : URI) -> Boolean) : URI {
|
||||
}
|
||||
|
||||
class URI(val body : Any) {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun to(dest : String) {}<!>
|
||||
infix fun to(dest : String) {}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
class Pair<out A, out B>(val first: A, val second: B)
|
||||
|
||||
class Example {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun to(other: Example) = Pair(this, other)<!>
|
||||
infix fun to(other: Example) = Pair(this, other)
|
||||
fun toNonInfix(other: Example) = Pair(this, other)
|
||||
}
|
||||
|
||||
@@ -35,4 +35,4 @@ fun test() {
|
||||
a toExtNonInfixDefaultValues b
|
||||
|
||||
a withLambda { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
|
||||
// OK
|
||||
infix fun String.ok1(o: String) {}
|
||||
class OkTest {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun ok2(o: String) {}<!>
|
||||
infix fun ok2(o: String) {}
|
||||
infix fun String.ok3(o: String) {}
|
||||
}
|
||||
|
||||
@@ -24,4 +24,4 @@ class Example {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun e8(s: String, a: Int = 0) {}<!>
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun e9(s: String, a: Int) {}<!>
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun e10() {}<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,9 +59,9 @@ interface Example {
|
||||
operator fun hasNext(): Boolean
|
||||
operator fun hasNext(n: Int): String
|
||||
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun i1(n: Int)<!>
|
||||
infix fun i1(n: Int)
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun i1(n: Int, n2: Int)<!>
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun i1(vararg n: Int)<!>
|
||||
infix fun i1(vararg n: Int)
|
||||
}
|
||||
|
||||
class OkDelegates {
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
//KT-4529 Lambdas are analyzed improperly in an infix call nested inside a println
|
||||
|
||||
class G {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun foo(bar: (Int) -> Int) = bar<!>
|
||||
}
|
||||
|
||||
fun main() {
|
||||
use(
|
||||
G().foo {it + 11} // no error
|
||||
)
|
||||
use(
|
||||
G() foo {it + 11} // ERROR
|
||||
)
|
||||
use(
|
||||
G() foo ({it + 1}) // 2 ERRORs
|
||||
)
|
||||
}
|
||||
|
||||
fun use(a: Any?) = a
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
//KT-4529 Lambdas are analyzed improperly in an infix call nested inside a println
|
||||
|
||||
class G {
|
||||
|
||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ interface Foo
|
||||
fun (Foo.() -> Unit).invoke(b : Foo.() -> Unit) {}
|
||||
|
||||
object Z {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun add(b : Foo.() -> Unit) : Z = Z<!>
|
||||
infix fun add(b : Foo.() -> Unit) : Z = Z
|
||||
}
|
||||
|
||||
val t2 = Z <!INAPPLICABLE_CANDIDATE!>add<!> { } { }
|
||||
|
||||
Vendored
+2
-2
@@ -1,9 +1,9 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE
|
||||
|
||||
class Z {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>inline infix fun <R> inlineFun(crossinline p: () -> R) {
|
||||
inline infix fun <R> inlineFun(crossinline p: () -> R) {
|
||||
p()
|
||||
}<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun <R> fun1(p: () -> R) {
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER, -EXTENSION_SHADOWED_BY_MEMBER
|
||||
|
||||
class Example {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>operator infix fun plus(other: Example) = 0<!>
|
||||
operator infix fun plus(other: Example) = 0
|
||||
fun minus(other: Example) = 0
|
||||
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>operator infix fun times(other: Example) = 0<!>
|
||||
operator infix fun times(other: Example) = 0
|
||||
fun div(other: Example) = 0
|
||||
}
|
||||
|
||||
@@ -42,4 +42,4 @@ fun a() {
|
||||
}
|
||||
|
||||
fun consumeInt(i: Int) {}
|
||||
fun consumeString(s: String) {}
|
||||
fun consumeString(s: String) {}
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
class A() {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>operator infix fun plus(i : Int) {}<!>
|
||||
operator infix fun plus(i : Int) {}
|
||||
operator fun unaryMinus() {}
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>operator infix fun contains(a : Any?) : Boolean = true<!>
|
||||
operator infix fun contains(a : Any?) : Boolean = true
|
||||
}
|
||||
|
||||
operator infix fun A.div(i : Int) {}
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
interface IFoo {
|
||||
fun foo(i: Int): Int
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun bar(i: Int): Int<!>
|
||||
infix fun bar(i: Int): Int
|
||||
}
|
||||
|
||||
infix fun IFoo.foo(i: Int) = i
|
||||
infix fun IFoo.bar(i: Int) = i
|
||||
infix fun IFoo.bar(i: Int) = i
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package o
|
||||
|
||||
class A {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun foo(b: B) = b<!>
|
||||
infix fun foo(b: B) = b
|
||||
}
|
||||
|
||||
class B {
|
||||
@@ -11,4 +11,4 @@ class B {
|
||||
fun test(a: A, b: B?) {
|
||||
a foo b!!
|
||||
b.bar()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user