Почему crossinline ломает return в этой inline-функции?
Lambda, передаваемая в executeAction, использует return, чтобы выйти из цикла. Автор хочет, чтобы этот return продолжал работать. Решите, нужен ли здесь crossinline, и поправьте сигнатуру.
inline fun executeAction(crossinline action: () -> Unit) {
action()
}
fun someFun() {
executeAction {
for (i in 0..10) {
if (i == 5) return
}
}
}
Найдите и исправьте ошибку.
crossinline запрещает non-local return из lambda, но код на него полагается: return выходит из someFun, поэтому с crossinline не скомпилируется. Уберите crossinline — обычный inline встраивает action и разрешает non-local return.
- ✗Воспринимать
crossinlineкак безобидную оптимизацию, а не как запрет non-local return - ✗Думать, что
returnвыходит только из lambda, поэтомуcrossinlineничего не меняет - ✗Чинить добавлением
noinline, что заодно отключает встраивание lambda
- →В какой ситуации
crossinlineна этом параметре действительно понадобился бы? - →В чём разница между
crossinlineиnoinline?
Баг
crossinline помечает lambda-параметр как запрещённый для non-local return. Но someFun рассчитывает именно на non-local return: return внутри lambda должен выйти из someFun. С crossinline компилятор отвергнет такой return — код не соберётся.
inline fun executeAction(crossinline action: () -> Unit) {
action()
}
fun someFun() {
executeAction {
for (i in 0..10) {
if (i == 5) return // ❌ запрещён при crossinline
}
}
}
Исправление
Уберите crossinline. Обычный inline встраивает action напрямую в someFun, поэтому non-local return разрешён и выходит из someFun.
inline fun executeAction(action: () -> Unit) {
action()
}
fun someFun() {
executeAction {
for (i in 0..10) {
if (i == 5) return // ✅ выходит из someFun
}
}
}
crossinline нужен только когда встроенную lambda вызывают из другого контекста выполнения (вложенная lambda, анонимный объект), где non-local return был бы нелегален.