FE: forbid extension calls on inline functional parameters

Extension receivers are currently implicitly noinline, and changing that
would require modifying the syntax to allow marking them noinline or
crossinline.

^KT-5837 Open
^KT-25787 Fixed
^KT-47965 Fixed
^KT-50107 Fixed
^KT-52403 Fixed
This commit is contained in:
pyos
2022-05-19 13:09:52 +02:00
committed by Space
parent efa267bf86
commit fad35b95d4
32 changed files with 59 additions and 356 deletions
@@ -187,7 +187,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
if (receiverSymbol in inalienableParameters) {
if (!isInvokeOrInlineExtension(targetSymbol)) {
reporter.reportOn(
qualifiedAccessExpression.source,
receiverExpression.source ?: qualifiedAccessExpression.source,
FirErrors.USAGE_IS_NOT_INLINABLE,
receiverSymbol,
context
@@ -198,7 +198,8 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
private fun isInvokeOrInlineExtension(targetSymbol: FirBasedSymbol<*>?): Boolean {
if (targetSymbol !is FirNamedFunctionSymbol) return false
if (targetSymbol.isInline) return true
// TODO: receivers are currently not inline (KT-5837)
// if (targetSymbol.isInline) return true
return targetSymbol.name == OperatorNameConventions.INVOKE &&
targetSymbol.dispatchReceiverType?.isBuiltinFunctionalType(session) == true
}
@@ -238,12 +238,12 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
if (descriptor !is SimpleFunctionDescriptor) {
return false
}
// TODO: receivers are currently not inline (KT-5837)
// if (InlineUtil.isInline(descriptor)) return true
val containingDeclaration = descriptor.getContainingDeclaration()
val isInvoke = descriptor.getName() == OperatorNameConventions.INVOKE &&
return descriptor.getName() == OperatorNameConventions.INVOKE &&
containingDeclaration is ClassDescriptor && containingDeclaration.defaultType.isBuiltinFunctionalType
return isInvoke || InlineUtil.isInline(descriptor)
}
private fun checkVisibilityAndAccess(
@@ -1,22 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE
operator inline fun <T, U> Function1<T, U>.get(index : Int) {
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
s[1]
}
//noinline
operator fun <T, U, V> Function2<T, U, V>.get(index : Int) {
}
operator fun <T, U, V, W> @ExtensionFunctionType Function3<T, U, V, W>.get(index : Int) {
}
inline fun <T, U, V, W> inlineFunWithInvoke(s: (p: T, l: U) -> V, ext: T.(p: U, l: V) -> W) {
<!USAGE_IS_NOT_INLINABLE!>s[1]<!>
<!USAGE_IS_NOT_INLINABLE!>ext[1]<!>
}
@@ -1,10 +1,11 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE
operator inline fun <T, U> Function1<T, U>.get(index : Int) {
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
s[1]
<!USAGE_IS_NOT_INLINABLE!>s<!>[1]
}
//noinline
@@ -1,30 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -NON_LOCAL_RETURN_NOT_ALLOWED
operator fun <T, U> Function1<T, U>.minusAssign(p: Function1<T, U>) {}
inline <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun <T, U> Function1<T, U>.modAssign(p: Function1<T, U>) = {
this += p
p += this
}
inline operator fun <T, U> Function1<T, U>.plusAssign(p: Function1<T, U>) {
this -= <!USAGE_IS_NOT_INLINABLE!>p<!>
p <!USAGE_IS_NOT_INLINABLE!>-=<!> this
}
operator fun <T, U, V> @ExtensionFunctionType Function2<T, U, V>.minusAssign(ext : @ExtensionFunctionType Function2<T, U, V>) {}
inline <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun <T, U, V> @ExtensionFunctionType Function2<T, U, V>.modAssign(ext : @ExtensionFunctionType Function2<T, U, V>) = {
this += ext
ext += this
}
inline operator fun <T, U, V> @ExtensionFunctionType Function2<T, U, V>.plusAssign(ext : @ExtensionFunctionType Function2<T, U, V>) {
this -= <!USAGE_IS_NOT_INLINABLE!>ext<!>
ext <!USAGE_IS_NOT_INLINABLE!>-=<!> this
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U, ext: T.(p: U) -> V) {
s += s
ext += ext
}
@@ -1,10 +1,11 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -NON_LOCAL_RETURN_NOT_ALLOWED
operator fun <T, U> Function1<T, U>.minusAssign(p: Function1<T, U>) {}
inline <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun <T, U> Function1<T, U>.modAssign(p: Function1<T, U>) = {
this += p
p += this
<!USAGE_IS_NOT_INLINABLE!>p<!> += this
}
inline operator fun <T, U> Function1<T, U>.plusAssign(p: Function1<T, U>) {
@@ -16,7 +17,7 @@ operator fun <T, U, V> @ExtensionFunctionType Function2<T, U, V>.minusAssign(ext
inline <!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun <T, U, V> @ExtensionFunctionType Function2<T, U, V>.modAssign(ext : @ExtensionFunctionType Function2<T, U, V>) = {
this += ext
ext += this
<!USAGE_IS_NOT_INLINABLE!>ext<!> += this
}
inline operator fun <T, U, V> @ExtensionFunctionType Function2<T, U, V>.plusAssign(ext : @ExtensionFunctionType Function2<T, U, V>) {
@@ -25,6 +26,6 @@ inline operator fun <T, U, V> @ExtensionFunctionType Function2<T, U, V>.plusAssi
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U, ext: T.(p: U) -> V) {
s += s
ext += ext
<!USAGE_IS_NOT_INLINABLE!>s<!> += s
<!USAGE_IS_NOT_INLINABLE!>ext<!> += ext
}
@@ -1,26 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE
inline operator fun <T, U> Function1<T, U>.compareTo(p: Function1<T, U>) = 1
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
s < s
s <= s
s > s
s >= s
}
//noinline
operator fun <T, U, V> Function2<T, U, V>.compareTo(index : Function2<T, U, V>) = 1
operator fun <T, U, V, W> @ExtensionFunctionType Function3<T, U, V, W>.compareTo(index : @ExtensionFunctionType Function3<T, U, V, W>) = 1
inline fun <T, U, V, W> inlineFunWithInvoke(s: (p: T, l: U) -> V, ext: T.(p: U, l: V) -> W) {
s <!USAGE_IS_NOT_INLINABLE!><<!> <!USAGE_IS_NOT_INLINABLE!>s<!>
s <!USAGE_IS_NOT_INLINABLE!><=<!> <!USAGE_IS_NOT_INLINABLE!>s<!>
s <!USAGE_IS_NOT_INLINABLE!>><!> <!USAGE_IS_NOT_INLINABLE!>s<!>
s <!USAGE_IS_NOT_INLINABLE!>>=<!> <!USAGE_IS_NOT_INLINABLE!>s<!>
ext <!USAGE_IS_NOT_INLINABLE!><<!> <!USAGE_IS_NOT_INLINABLE!>ext<!>
ext <!USAGE_IS_NOT_INLINABLE!>><!> <!USAGE_IS_NOT_INLINABLE!>ext<!>
ext <!USAGE_IS_NOT_INLINABLE!><=<!> <!USAGE_IS_NOT_INLINABLE!>ext<!>
ext <!USAGE_IS_NOT_INLINABLE!>>=<!> <!USAGE_IS_NOT_INLINABLE!>ext<!>
}
@@ -1,12 +1,13 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE
inline operator fun <T, U> Function1<T, U>.compareTo(p: Function1<T, U>) = 1
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
s < s
s <= s
s > s
s >= s
<!USAGE_IS_NOT_INLINABLE!>s<!> < s
<!USAGE_IS_NOT_INLINABLE!>s<!> <= s
<!USAGE_IS_NOT_INLINABLE!>s<!> > s
<!USAGE_IS_NOT_INLINABLE!>s<!> >= s
}
//noinline
@@ -3,7 +3,7 @@ inline operator fun <T, U> Function1<T, U>.component1() = 1
inline operator fun <T, U> Function1<T, U>.component2() = 2
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
val (d1, e1) = s
val (d1, e1) = <!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>s<!>
}
operator fun <T, U, V> Function2<T, U, V>.component1() = 1
@@ -1,24 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -RECURSION_IN_INLINE
operator inline fun <T, U> Function1<T, U>.contains(p: Function1<T, U>): Boolean {
this in p
p in this
return false
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
s in s
s !in s
}
operator fun <T, U, V> Function2<T, U, V>.contains(p: Function2<T, U, V>): Boolean = false
operator fun <T, U, V, W> @ExtensionFunctionType Function3<T, U, V, W>.contains(ext: @ExtensionFunctionType Function3<T, U, V, W>): Boolean = false
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T, l: U) -> U, ext: T.(p: U, l: U) -> V) {
<!USAGE_IS_NOT_INLINABLE!>s<!> <!USAGE_IS_NOT_INLINABLE!>in<!> s
<!USAGE_IS_NOT_INLINABLE!>s<!> <!USAGE_IS_NOT_INLINABLE!>!in<!> s
<!USAGE_IS_NOT_INLINABLE!>ext<!> <!USAGE_IS_NOT_INLINABLE!>in<!> ext
<!USAGE_IS_NOT_INLINABLE!>ext<!> <!USAGE_IS_NOT_INLINABLE!>!in<!> ext
}
@@ -1,13 +1,14 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -RECURSION_IN_INLINE
operator inline fun <T, U> Function1<T, U>.contains(p: Function1<T, U>): Boolean {
this in p
this in <!USAGE_IS_NOT_INLINABLE!>p<!>
p in this
return false
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
s in s
s !in s
s in <!USAGE_IS_NOT_INLINABLE!>s<!>
s !in <!USAGE_IS_NOT_INLINABLE!>s<!>
}
@@ -17,13 +17,13 @@ inline operator fun <T, U, V> @ExtensionFunctionType Function2<T, U, V>.plus(p:
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U, ext: T.(p: U) -> V) {
s + s
ext + ext
<!USAGE_IS_NOT_INLINABLE!>s<!> + s
<!USAGE_IS_NOT_INLINABLE!>ext<!> + ext
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U, ext: T.(p: U) -> V) {
s + s
ext + ext
<!USAGE_IS_NOT_INLINABLE!>s<!> + s
<!USAGE_IS_NOT_INLINABLE!>ext<!> + ext
}
inline fun <T, U> Function1<T, U>.submit() {
@@ -1,29 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -RECURSION_IN_INLINE
inline operator fun <T, U> Function1<T, U>.rangeTo(p: Function1<T, U>): ClosedRange<Int> {
this..p
p..this
return 1..2
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
s..s
s..s
}
operator fun <T, U, V> Function2<T, U, V>.rangeTo(p: Function2<T, U, V>): ClosedRange<Int> {
return 1..2
}
operator fun <T, U, V, W> @ExtensionFunctionType Function3<T, U, V, W>.rangeTo(ext: @ExtensionFunctionType Function3<T, U, V, W>): ClosedRange<Int> {
return 1..2
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T, l: U) -> U, ext: T.(p: U, l: U) -> V) {
s<!USAGE_IS_NOT_INLINABLE!>..<!><!USAGE_IS_NOT_INLINABLE!>s<!>
s<!USAGE_IS_NOT_INLINABLE!>..<!><!USAGE_IS_NOT_INLINABLE!>s<!>
ext<!USAGE_IS_NOT_INLINABLE!>..<!><!USAGE_IS_NOT_INLINABLE!>ext<!>
ext<!USAGE_IS_NOT_INLINABLE!>..<!><!USAGE_IS_NOT_INLINABLE!>ext<!>
}
@@ -1,14 +1,15 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -RECURSION_IN_INLINE
inline operator fun <T, U> Function1<T, U>.rangeTo(p: Function1<T, U>): ClosedRange<Int> {
this..p
p..this
<!USAGE_IS_NOT_INLINABLE!>p<!>..this
return 1..2
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T) -> U) {
s..s
s..s
<!USAGE_IS_NOT_INLINABLE!>s<!>..s
<!USAGE_IS_NOT_INLINABLE!>s<!>..s
}
@@ -1,51 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -NON_LOCAL_RETURN_NOT_ALLOWED
infix fun Function1<Int, Unit>.noInlineExt(p: Int) {}
inline infix fun Function1<Int, Unit>.inlineExt2(p: Int) {
{
noInlineExt(11)
this.noInlineExt(11)
this noInlineExt 11
this
}()
}
inline fun Function1<Int, Unit>.inlineExt() {
{
inlineExt2(1)
this.inlineExt2(1)
this inlineExt2 1
this(11)
}()
}
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit) {
{
s(11)
s.invoke(11)
s <!INFIX_MODIFIER_REQUIRED!>invoke<!> 11
}()
}
inline fun inlineFunWithInvokeNonInline(noinline s: (p: Int) -> Unit) {
{
s(11)
s.invoke(11)
s <!INFIX_MODIFIER_REQUIRED!>invoke<!> 11
}()
}
inline fun testExtension(s: (p: Int) -> Unit) {
{
s.inlineExt()
} ()
}
inline fun inlineFunWrongExtension(s: (p: Int) -> Unit) {
{
s.<!USAGE_IS_NOT_INLINABLE!>noInlineExt<!>(11)
} ()
}
+2 -1
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -NON_LOCAL_RETURN_NOT_ALLOWED
infix fun Function1<Int, Unit>.noInlineExt(p: Int) {}
@@ -40,7 +41,7 @@ inline fun inlineFunWithInvokeNonInline(noinline s: (p: Int) -> Unit) {
inline fun testExtension(s: (p: Int) -> Unit) {
{
s.inlineExt()
<!USAGE_IS_NOT_INLINABLE!>s<!>.inlineExt()
} ()
}
@@ -1,28 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE
infix fun Function1<Int, Unit>.noInlineExt(p: Int) {}
inline infix fun Function1<Int, Unit>.inlineExt2(p: Int) {
noInlineExt(11)
this.noInlineExt(11)
this noInlineExt 11
this
}
inline fun Function1<Int, Unit>.inlineExt() {
inlineExt2(1)
this.inlineExt2(1)
this inlineExt2 1
}
inline fun testExtension(s: (p: Int) -> Unit) {
s.inlineExt()
}
inline fun inlineFunWrongExtension(s: (p: Int) -> Unit) {
s.<!USAGE_IS_NOT_INLINABLE!>noInlineExt<!>(11)
}
inline fun inlineFunNoInline(noinline s: (p: Int) -> Unit) {
s.noInlineExt(11)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE
infix fun Function1<Int, Unit>.noInlineExt(p: Int) {}
@@ -16,7 +17,7 @@ inline fun Function1<Int, Unit>.inlineExt() {
}
inline fun testExtension(s: (p: Int) -> Unit) {
s.inlineExt()
<!USAGE_IS_NOT_INLINABLE!>s<!>.inlineExt()
}
inline fun inlineFunWrongExtension(s: (p: Int) -> Unit) {
@@ -11,18 +11,18 @@ inline operator fun <T, V> @ExtensionFunctionType Function2<T, T, V>.inc() = thi
operator fun <T, V> @ExtensionFunctionType Function2<T, T, V>.dec() = this
inline fun <T, V> inlineFunWithInvoke(s: (p: T) -> V, ext: T.(p: T) -> V) {
+s
<!USAGE_IS_NOT_INLINABLE!>-<!>s
+<!USAGE_IS_NOT_INLINABLE!>s<!>
-<!USAGE_IS_NOT_INLINABLE!>s<!>
<!USAGE_IS_NOT_INLINABLE!>s<!>++
<!USAGE_IS_NOT_INLINABLE!>++<!>s
<!USAGE_IS_NOT_INLINABLE!>++<!><!USAGE_IS_NOT_INLINABLE!>s<!>
<!USAGE_IS_NOT_INLINABLE!>s<!>--
<!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>--<!>s
+ext
<!USAGE_IS_NOT_INLINABLE!>-<!>ext
<!USAGE_IS_NOT_INLINABLE!>--<!><!USAGE_IS_NOT_INLINABLE!>s<!>
+<!USAGE_IS_NOT_INLINABLE!>ext<!>
-<!USAGE_IS_NOT_INLINABLE!>ext<!>
<!USAGE_IS_NOT_INLINABLE!>ext<!>++
<!USAGE_IS_NOT_INLINABLE!>++<!>ext
<!USAGE_IS_NOT_INLINABLE!>++<!><!USAGE_IS_NOT_INLINABLE!>ext<!>
<!USAGE_IS_NOT_INLINABLE!>ext<!>--
<!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>--<!>ext
<!USAGE_IS_NOT_INLINABLE!>--<!><!USAGE_IS_NOT_INLINABLE!>ext<!>
}
inline fun <T, V> Function1<T, V>.inlineFunWithInvoke() {
@@ -11,16 +11,16 @@ inline operator fun <T, V> @ExtensionFunctionType Function2<T, T, V>.inc() = thi
operator fun <T, V> @ExtensionFunctionType Function2<T, T, V>.dec() = this
inline fun <T, V> inlineFunWithInvoke(s: (p: T) -> V, ext: T.(p: T) -> V) {
+s
+<!USAGE_IS_NOT_INLINABLE!>s<!>
-<!USAGE_IS_NOT_INLINABLE!>s<!>
s++
++s
<!USAGE_IS_NOT_INLINABLE!>s<!>++
++<!USAGE_IS_NOT_INLINABLE!>s<!>
<!USAGE_IS_NOT_INLINABLE!>s<!>--
--<!USAGE_IS_NOT_INLINABLE!>s<!>
+ext
+<!USAGE_IS_NOT_INLINABLE!>ext<!>
-<!USAGE_IS_NOT_INLINABLE!>ext<!>
ext++
++ext
<!USAGE_IS_NOT_INLINABLE!>ext<!>++
++<!USAGE_IS_NOT_INLINABLE!>ext<!>
<!USAGE_IS_NOT_INLINABLE!>ext<!>--
--<!USAGE_IS_NOT_INLINABLE!>ext<!>
}
@@ -1,21 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -RECURSION_IN_INLINE
inline operator fun <T, V> Function1<T, V>.not() : Boolean {
return !this
}
inline fun <T, V> inlineFunWithInvoke(s: (p: T) -> V) {
!s
}
operator fun <T, U, V> Function2<T, U, V>.not() : Boolean {
return !this
}
operator fun <T, U, V, W> @ExtensionFunctionType Function3<T, U, V, W>.not() : Boolean {
return !this
}
inline fun <T, U, V> inlineFunWithInvoke(s: (p: T, l: U) -> V, ext: T.(p: T, l : U) -> V) {
<!USAGE_IS_NOT_INLINABLE!>!<!>s
<!USAGE_IS_NOT_INLINABLE!>!<!>ext
}
@@ -1,10 +1,11 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -RECURSION_IN_INLINE
inline operator fun <T, V> Function1<T, V>.not() : Boolean {
return !this
}
inline fun <T, V> inlineFunWithInvoke(s: (p: T) -> V) {
!s
!<!USAGE_IS_NOT_INLINABLE!>s<!>
}
operator fun <T, U, V> Function2<T, U, V>.not() : Boolean {
@@ -21,7 +21,7 @@ inline fun test(crossinline c: () -> Unit) {
}
}
val l = { c() }
c.<!USAGE_IS_NOT_INLINABLE!>startCoroutine<!>(EmptyContinuation)
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
}
suspend fun calculate() = "OK"
@@ -1,37 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
// SKIP_TXT
// WITH_COROUTINES
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
import helpers.*
interface SuspendRunnable {
suspend fun run()
}
// Function is NOT suspend
// parameter is crossinline
// parameter is suspend
// Block is NOT allowed to be called inside the body of owner inline function
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
// It is NOT possible to call startCoroutine on the parameter
// suspend calls possible inside lambda matching to the parameter
inline fun test(crossinline c: suspend () -> Unit) {
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>c<!>()
val o = object : SuspendRunnable {
override suspend fun run() {
c()
}
}
val l: suspend () -> Unit = { c() }
c.<!USAGE_IS_NOT_INLINABLE!>startCoroutine<!>(EmptyContinuation)
}
suspend fun calculate() = "OK"
fun box() {
test {
calculate()
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
// SKIP_TXT
// WITH_COROUTINES
@@ -21,7 +21,7 @@ inline fun test(c: () -> Unit) {
}
}
val l = { c() }
c.<!USAGE_IS_NOT_INLINABLE!>startCoroutine<!>(EmptyContinuation)
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
}
fun builder(c: suspend () -> Unit) {
@@ -25,7 +25,7 @@ inline fun test(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>c: suspend () -> Uni
}
}
val l: suspend () -> Unit = { c() }
c.<!USAGE_IS_NOT_INLINABLE!>startCoroutine<!>(EmptyContinuation)
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
}
fun builder(c: suspend () -> Unit) {}
@@ -20,7 +20,7 @@ suspend inline fun test(crossinline c: () -> Unit) {
}
}
val l = { c() }
c.<!USAGE_IS_NOT_INLINABLE!>startCoroutine<!>(EmptyContinuation)
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
}
fun builder(c: suspend () -> Unit) {
@@ -1,40 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
// SKIP_TXT
// WITH_COROUTINES
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
import helpers.*
interface SuspendRunnable {
suspend fun run()
}
// Function is suspend
// parameter is crossinline
// parameter is suspend
// Block is allowed to be called inside the body of owner inline function
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
// It is NOT possible to call startCoroutine on the parameter
// suspend calls possible inside lambda matching to the parameter
suspend inline fun test(crossinline c: suspend () -> Unit) {
c()
val o = object : SuspendRunnable {
override suspend fun run() {
c()
}
}
val l: suspend () -> Unit = { c() }
c.<!USAGE_IS_NOT_INLINABLE!>startCoroutine<!>(EmptyContinuation)
}
fun builder(c: suspend () -> Unit) {}
suspend fun calculate() = "OK"
fun box() {
builder {
test {
calculate()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
// SKIP_TXT
// WITH_COROUTINES
@@ -20,7 +20,7 @@ suspend inline fun test(c: () -> Unit) {
}
}
val l = { c() }
c.<!USAGE_IS_NOT_INLINABLE!>startCoroutine<!>(EmptyContinuation)
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
}
suspend fun calculate() = "OK"
@@ -24,7 +24,7 @@ suspend inline fun test(c: <!REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE!>suspend<!>
}
}
val l: suspend () -> Unit = { c() }
c.<!USAGE_IS_NOT_INLINABLE!>startCoroutine<!>(EmptyContinuation)
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
}
fun builder(c: suspend () -> Unit) {