[FIR] Disallow operators not on functions
Introduce `NOT_FUNCTION_AS_OPERATOR` and use it instead of `PROPERTY_AS_OPERATOR` ^KT-65881 Fixed Merge-request: KT-MR-14547
This commit is contained in:
committed by
Space Team
parent
df9d59851d
commit
2d4f4b9bb5
@@ -0,0 +1,130 @@
|
||||
// ISSUE: KT-65881, KT-65760
|
||||
|
||||
class I: Iterator<Int> {
|
||||
override fun hasNext(): Boolean = false
|
||||
override fun next(): Int = 0
|
||||
}
|
||||
|
||||
object A {
|
||||
object plusAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object minusAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object timesAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object divAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object remAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object unaryPlus {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object unaryMinus {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object not {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object plus {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object minus {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object times {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object div {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object rem {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object get {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object set {
|
||||
operator fun invoke(x: Int, y: Int): A = A
|
||||
}
|
||||
object contains {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object invoke {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object rangeTo {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object rangeUntil {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object compareTo {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object iterator {
|
||||
operator fun invoke(): I = I()
|
||||
}
|
||||
object component1 {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object component2 {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
}
|
||||
|
||||
fun usePlusAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 1 }
|
||||
fun useMinusAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>-=<!> 1 }
|
||||
fun useTimesAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>*=<!> 1 }
|
||||
fun useDivAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>/=<!> 1 }
|
||||
fun useRemAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>%=<!> 1 }
|
||||
val useUnaryPlus = <!NOT_FUNCTION_AS_OPERATOR!>+<!>A
|
||||
val useUnaryMinus = <!NOT_FUNCTION_AS_OPERATOR!>-<!>A
|
||||
val useNot = <!NOT_FUNCTION_AS_OPERATOR!>!<!>A
|
||||
val usePlus = A <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1
|
||||
val useMinus = A <!NOT_FUNCTION_AS_OPERATOR!>-<!> 1
|
||||
val useTimes = A <!NOT_FUNCTION_AS_OPERATOR!>*<!> 1
|
||||
val useDiv = A <!NOT_FUNCTION_AS_OPERATOR!>/<!> 1
|
||||
val useRem = A <!NOT_FUNCTION_AS_OPERATOR!>%<!> 1
|
||||
val useGet = <!NOT_FUNCTION_AS_OPERATOR!>A[1]<!>
|
||||
fun useSet() { <!NOT_FUNCTION_AS_OPERATOR!>A[1]<!> = 3 }
|
||||
val useContains = 1 <!NOT_FUNCTION_AS_OPERATOR!>in<!> A
|
||||
val useNotContains = 1 <!NOT_FUNCTION_AS_OPERATOR, UNRESOLVED_REFERENCE!>!in<!> A
|
||||
val useInvoke = <!UNRESOLVED_REFERENCE!>A<!>()
|
||||
val useRangeTo = A <!NOT_FUNCTION_AS_OPERATOR!>..<!> 3
|
||||
val useRangeUntil = A <!NOT_FUNCTION_AS_OPERATOR!>..<<!> 3
|
||||
val useCompareTo = A <!NOT_FUNCTION_AS_OPERATOR!>><!> 2
|
||||
fun useIterator() {
|
||||
for (x in <!ITERATOR_MISSING!>A<!>) { }
|
||||
}
|
||||
fun useComponentN() {
|
||||
val (x, y) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>A<!>
|
||||
}
|
||||
|
||||
object D {
|
||||
object getValue {
|
||||
operator fun invoke(thisRef: Any?, property: Any?): Int = 0
|
||||
}
|
||||
object setValue {
|
||||
operator fun invoke(thisRef: Any?, property: Any?, newValue: Int) { }
|
||||
}
|
||||
}
|
||||
|
||||
class X {
|
||||
val component1 = { "UwU" }
|
||||
}
|
||||
|
||||
operator fun X.component1(): String = "Not UwU"
|
||||
|
||||
fun useDelegate() {
|
||||
val m by <!DELEGATE_SPECIAL_FUNCTION_MISSING!>D<!>
|
||||
var n by <!DELEGATE_SPECIAL_FUNCTION_MISSING, DELEGATE_SPECIAL_FUNCTION_MISSING!>D<!>
|
||||
}
|
||||
|
||||
fun resolveToExtension() {
|
||||
val (uwu) = X() // KT-65760
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// ISSUE: KT-65881, KT-65760
|
||||
|
||||
class I: Iterator<Int> {
|
||||
override fun hasNext(): Boolean = false
|
||||
override fun next(): Int = 0
|
||||
}
|
||||
|
||||
object A {
|
||||
object plusAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object minusAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object timesAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object divAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object remAssign {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object unaryPlus {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object unaryMinus {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object not {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object plus {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object minus {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object times {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object div {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object rem {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object get {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object set {
|
||||
operator fun invoke(x: Int, y: Int): A = A
|
||||
}
|
||||
object contains {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object invoke {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object rangeTo {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object rangeUntil {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object compareTo {
|
||||
operator fun invoke(x: Int): A = A
|
||||
}
|
||||
object iterator {
|
||||
operator fun invoke(): I = I()
|
||||
}
|
||||
object component1 {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
object component2 {
|
||||
operator fun invoke(): A = A
|
||||
}
|
||||
}
|
||||
|
||||
fun usePlusAssign() { A <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+=<!> 1 }
|
||||
fun useMinusAssign() { A <!RESOLUTION_TO_CLASSIFIER!>-=<!> 1 }
|
||||
fun useTimesAssign() { A <!RESOLUTION_TO_CLASSIFIER!>*=<!> 1 }
|
||||
fun useDivAssign() { A <!RESOLUTION_TO_CLASSIFIER!>/=<!> 1 }
|
||||
fun useRemAssign() { A <!RESOLUTION_TO_CLASSIFIER!>%=<!> 1 }
|
||||
val useUnaryPlus = <!RESOLUTION_TO_CLASSIFIER!>+<!>A
|
||||
val useUnaryMinus = <!RESOLUTION_TO_CLASSIFIER!>-<!>A
|
||||
val useNot = <!RESOLUTION_TO_CLASSIFIER!>!<!>A
|
||||
val usePlus = A <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+<!> 1
|
||||
val useMinus = A <!RESOLUTION_TO_CLASSIFIER!>-<!> 1
|
||||
val useTimes = A <!RESOLUTION_TO_CLASSIFIER!>*<!> 1
|
||||
val useDiv = A <!RESOLUTION_TO_CLASSIFIER!>/<!> 1
|
||||
val useRem = A <!RESOLUTION_TO_CLASSIFIER!>%<!> 1
|
||||
val useGet = <!RESOLUTION_TO_CLASSIFIER!>A<!NO_GET_METHOD!>[1]<!><!>
|
||||
fun useSet() { <!RESOLUTION_TO_CLASSIFIER!>A<!NO_SET_METHOD!>[1]<!><!> = 3 }
|
||||
val useContains = 1 <!RESOLUTION_TO_CLASSIFIER!>in<!> A
|
||||
val useNotContains = 1 <!RESOLUTION_TO_CLASSIFIER!>!in<!> A
|
||||
val useInvoke = <!FUNCTION_EXPECTED!>A<!>()
|
||||
val useRangeTo = A <!RESOLUTION_TO_CLASSIFIER!>..<!> 3
|
||||
val useRangeUntil = A <!RESOLUTION_TO_CLASSIFIER!>..<<!> 3
|
||||
val useCompareTo = A <!RESOLUTION_TO_CLASSIFIER!>><!> 2
|
||||
fun useIterator() {
|
||||
for (x in <!ITERATOR_MISSING!>A<!>) { }
|
||||
}
|
||||
fun useComponentN() {
|
||||
val (x, y) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>A<!>
|
||||
}
|
||||
|
||||
object D {
|
||||
object getValue {
|
||||
operator fun invoke(thisRef: Any?, property: Any?): Int = 0
|
||||
}
|
||||
object setValue {
|
||||
operator fun invoke(thisRef: Any?, property: Any?, newValue: Int) { }
|
||||
}
|
||||
}
|
||||
|
||||
class X {
|
||||
val component1 = { "UwU" }
|
||||
}
|
||||
|
||||
operator fun X.<!EXTENSION_FUNCTION_SHADOWED_BY_MEMBER_PROPERTY_WITH_INVOKE!>component1<!>(): String = "Not UwU"
|
||||
|
||||
fun useDelegate() {
|
||||
val m by D
|
||||
var n by <!DELEGATE_SPECIAL_FUNCTION_MISSING!>D<!>
|
||||
}
|
||||
|
||||
fun resolveToExtension() {
|
||||
val (<!PROPERTY_AS_OPERATOR!>uwu<!>) = X() // KT-65760
|
||||
}
|
||||
@@ -12,11 +12,11 @@ val <X3> C<X3>.getValue: D<X3> get() = TODO()
|
||||
operator fun <X4> D<X4>.invoke(x: Any?, y: Any?): X4 = TODO()
|
||||
|
||||
fun foo(a: A<String>, c: C<String>) {
|
||||
val x1 by <!PROPERTY_AS_OPERATOR!>a<!>
|
||||
val x1 by <!NOT_FUNCTION_AS_OPERATOR!>a<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x1<!>
|
||||
x1.length
|
||||
|
||||
val y1 by <!PROPERTY_AS_OPERATOR!>c<!>
|
||||
val y1 by <!NOT_FUNCTION_AS_OPERATOR!>c<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>y1<!>
|
||||
y1.length
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
val Int.plusAssign: (Int) -> Unit
|
||||
get() = {}
|
||||
|
||||
fun main() {
|
||||
1 <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 2
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
|
||||
val Int.plusAssign: (Int) -> Unit
|
||||
get() = {}
|
||||
|
||||
|
||||
+22
-22
@@ -10,25 +10,25 @@ class A { }
|
||||
var a = A()
|
||||
|
||||
val A.inc: I get() = I()
|
||||
fun useInc() { a<!PROPERTY_AS_OPERATOR, RESULT_TYPE_MISMATCH!>++<!> }
|
||||
fun useInc() { a<!NOT_FUNCTION_AS_OPERATOR, RESULT_TYPE_MISMATCH!>++<!> }
|
||||
|
||||
val A.dec: I get() = I()
|
||||
fun useDec() { a<!PROPERTY_AS_OPERATOR, RESULT_TYPE_MISMATCH!>--<!> }
|
||||
fun useDec() { a<!NOT_FUNCTION_AS_OPERATOR, RESULT_TYPE_MISMATCH!>--<!> }
|
||||
|
||||
val A.plusAssign: I get() = I()
|
||||
fun usePlusAssign() { a <!PROPERTY_AS_OPERATOR!>+=<!> 1 }
|
||||
fun usePlusAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 1 }
|
||||
|
||||
val A.minusAssign: I get() = I()
|
||||
fun useMinusAssign() { a <!PROPERTY_AS_OPERATOR!>-=<!> 1 }
|
||||
fun useMinusAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>-=<!> 1 }
|
||||
|
||||
val A.timesAssign: I get() = I()
|
||||
fun useTimesAssign() { a <!PROPERTY_AS_OPERATOR!>*=<!> 1 }
|
||||
fun useTimesAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>*=<!> 1 }
|
||||
|
||||
val A.divAssign: I get() = I()
|
||||
fun useDivAssign() { a <!PROPERTY_AS_OPERATOR!>/=<!> 1 }
|
||||
fun useDivAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>/=<!> 1 }
|
||||
|
||||
val A.remAssign: I get() = I()
|
||||
fun useRemAssign() { a <!PROPERTY_AS_OPERATOR!>%=<!> 1 }
|
||||
fun useRemAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>%=<!> 1 }
|
||||
|
||||
// operators over values
|
||||
|
||||
@@ -36,47 +36,47 @@ class E { }
|
||||
val e = E()
|
||||
|
||||
val E.unaryPlus: I get() = I()
|
||||
val useUnaryPlus = <!PROPERTY_AS_OPERATOR!>+<!>e
|
||||
val useUnaryPlus = <!NOT_FUNCTION_AS_OPERATOR!>+<!>e
|
||||
|
||||
val E.unaryMinus: I get() = I()
|
||||
val useUnaryMinus = <!PROPERTY_AS_OPERATOR!>-<!>e
|
||||
val useUnaryMinus = <!NOT_FUNCTION_AS_OPERATOR!>-<!>e
|
||||
|
||||
val E.not: I get() = I()
|
||||
val useNot = <!PROPERTY_AS_OPERATOR!>!<!>e
|
||||
val useNot = <!NOT_FUNCTION_AS_OPERATOR!>!<!>e
|
||||
|
||||
val E.plus: I get() = I()
|
||||
val usePlus = e <!PROPERTY_AS_OPERATOR!>+<!> 1
|
||||
val usePlus = e <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1
|
||||
|
||||
val E.minus: I get() = I()
|
||||
val useMinus = e <!PROPERTY_AS_OPERATOR!>-<!> 1
|
||||
val useMinus = e <!NOT_FUNCTION_AS_OPERATOR!>-<!> 1
|
||||
|
||||
val E.times: I get() = I()
|
||||
val useTimes = e <!PROPERTY_AS_OPERATOR!>*<!> 1
|
||||
val useTimes = e <!NOT_FUNCTION_AS_OPERATOR!>*<!> 1
|
||||
|
||||
val E.div: I get() = I()
|
||||
val useDiv = e <!PROPERTY_AS_OPERATOR!>/<!> 1
|
||||
val useDiv = e <!NOT_FUNCTION_AS_OPERATOR!>/<!> 1
|
||||
|
||||
val E.rem: I get() = I()
|
||||
val useRem = e <!PROPERTY_AS_OPERATOR!>%<!> 1
|
||||
val useRem = e <!NOT_FUNCTION_AS_OPERATOR!>%<!> 1
|
||||
|
||||
val E.get: I get() = I()
|
||||
val useGet = <!PROPERTY_AS_OPERATOR!>e[1]<!>
|
||||
val useGet = <!NOT_FUNCTION_AS_OPERATOR!>e[1]<!>
|
||||
|
||||
val E.set: I get() = I()
|
||||
fun useSet() { <!PROPERTY_AS_OPERATOR!>e[1]<!> = 3 }
|
||||
fun useSet() { <!NOT_FUNCTION_AS_OPERATOR!>e[1]<!> = 3 }
|
||||
|
||||
val E.contains: I get() = I()
|
||||
val useContains = 1 <!PROPERTY_AS_OPERATOR!>in<!> e
|
||||
val useNotContains = 1 <!PROPERTY_AS_OPERATOR, PROPERTY_AS_OPERATOR!>!in<!> e
|
||||
val useContains = 1 <!NOT_FUNCTION_AS_OPERATOR!>in<!> e
|
||||
val useNotContains = 1 <!NOT_FUNCTION_AS_OPERATOR, NOT_FUNCTION_AS_OPERATOR!>!in<!> e
|
||||
|
||||
val E.invoke: I get() = I()
|
||||
val useInvoke = <!NONE_APPLICABLE!>e<!>()
|
||||
|
||||
val E.rangeTo: I get() = I()
|
||||
val useRangeTo = e <!PROPERTY_AS_OPERATOR!>..<!> 3
|
||||
val useRangeTo = e <!NOT_FUNCTION_AS_OPERATOR!>..<!> 3
|
||||
|
||||
val E.rangeUntil: I get() = I()
|
||||
val useRangeUntil = e <!PROPERTY_AS_OPERATOR!>..<<!> 3
|
||||
val useRangeUntil = e <!NOT_FUNCTION_AS_OPERATOR!>..<<!> 3
|
||||
|
||||
val E.compareTo: I get() = I()
|
||||
val useCompareTo = e <!PROPERTY_AS_OPERATOR!>><!> 2
|
||||
val useCompareTo = e <!NOT_FUNCTION_AS_OPERATOR!>><!> 2
|
||||
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
// ISSUE: KT-59715
|
||||
|
||||
class FunctionComponent {
|
||||
val component1: () -> String = { "hello" }
|
||||
}
|
||||
|
||||
class I {
|
||||
operator fun invoke(): String = "hello"
|
||||
}
|
||||
|
||||
class InvokeComponent {
|
||||
val component1: I = I()
|
||||
}
|
||||
|
||||
fun test_1(c: FunctionComponent) {
|
||||
val (<!NOT_FUNCTION_AS_OPERATOR!>x<!>) = FunctionComponent()
|
||||
val (<!NOT_FUNCTION_AS_OPERATOR!>y<!>) = c
|
||||
}
|
||||
|
||||
fun test_2(c: InvokeComponent) {
|
||||
val (<!NOT_FUNCTION_AS_OPERATOR!>x<!>) = FunctionComponent()
|
||||
val (<!NOT_FUNCTION_AS_OPERATOR!>y<!>) = c
|
||||
}
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
// ISSUE: KT-59715
|
||||
|
||||
class FunctionComponent {
|
||||
|
||||
Reference in New Issue
Block a user