На каком-то бытовом уровне схоже, конечно. Типа, и то, и другое встраивается. Но различия, конечно есть.
Есть ситуации, когда компилятор обязан встроить inline функцию, потому что другого ему не позволит JVM, например:
inline fun <reified T> f() {
print(T::class.java.name)
}
reified дженерики поддерживаются только для inline функций, потому что в JVM на этапе выполнения никаких дженериков нет, и поэтому данную функцию можно использовать только с известным на момент компиляции типом. Тело функции встроится в место вызова и всё хорошо.
А вот если у тебя просто inline fun, вне зависимости от того, есть ли у неё функциональный параметр, то уже возможны варианты. При обычном вызове тело функции будет встроено, и на этом основаны всякие экстешны, они не просаживают произволительность. Но также ты можешь взять и передать эту функцию в другую в качестве параметра, и в этом случае ей просто некуда встраиваться:
inline fun f() { ... }
fun g(p: ()-> Unit) {
p()
}
fun main() {
f() // заинлайнена
g(::f) // не заинлайнена
}
Если хочешь разобраться - смотри декомпилированный байткод, там всё есть. Ещё почитай про модификаторы noinline, crossinline.