What's an inline constructor in Kotlin?
Asked Answered
F

1

16

First of all, I have to clarify I'm not asking what's an inline function is or what's an inline class is. There's nowhere in Kotlin Language documentation or specification any reference to an inline constructor but if you look in Arrays.kt source you see this class: ByteArray has an inline constructor:

/**
 * An array of bytes. When targeting the JVM, instances of this class are represented as `byte[]`.
 * @constructor Creates a new array of the specified [size], with all elements initialized to zero.
 */
public class ByteArray(size: Int) {
    /**
     * Creates a new array of the specified [size], where each element is calculated by calling the specified
     * [init] function.
     *
     * The function [init] is called for each array element sequentially starting from the first one.
     * It should return the value for an array element given its index.
     */
    public inline constructor(size: Int, init: (Int) -> Byte)

Let's consider we want to create a similar class, something like this:

    public class Student(name: String) {
        public inline constructor(name: String, age: Int) : this(name)
    }

If you try to create that class in Kotlin and write an inline constructor for it you see that it's impossible and IDE refers to this error:

Modifier 'inline' is not applicable to 'constructor'

So let's recap, how ByteArray definition is correct?

Fiddlededee answered 3/5, 2021 at 18:22 Comment(7)
Im not sure, but I assume its due to the lambda (inlining is mostly used on things that take lambdas to avoid the use of funtion objects)Estreat
It won't work if you have a lambda either, the error is Modifier 'inline' is not applicable to 'constructor' which is defined by the language spec (kotlinlang.org/spec). I don't know for sure, but at a guess, because these are built-in types they're "breaking the rules" and making an exception in this specific case, and allowing the init function to be inlined by the compiler, to make initialising arrays more efficientTizes
Pretty sure this is something that is not available to use, and only appears in the psuedo-source code for built-in classes.Danndanna
@Tizes breaking the rules? after all it's Kotlin code anyway so they have to use a different compiler to compile standard library then?Fiddlededee
@Danndanna I don't think it's psuedo-source code, it's the official source code.Fiddlededee
I mean the compiler could be specially written to treat these built-in array types differently, so when this Kotlin code is translated to bytecode, it gets treated as a special case and inline is allowed. I mean like you said yourself, if you try to use inline constructor it won't compile, but it works for this internal stuff (and that constructor signature is explicitly spelled out in the spec: kotlinlang.org/spec/…). Could be a specially written case, or maybe inlining constructors is possible but disallowed in generalTizes
It is pseudo-code. The standard library is not compiled from the code you're looking at there. That function doesn't even have a body. It's only there for documentation purposes. There's a comment at the top that it's auto-generated. I think it's marked inline to let you know that any lambda you pass won't generate a function object.Danndanna
S
19

The ByteArray declaration you are looking at is not real, it’s a so called built-in type. This declaration exists for convenience, but is never truly compiled to a binary. (Indeed, on the JVM, arrays are special and don’t have corresponding class files anywhere.)

This constructor is marked inline because in practice the compiler emits the code corresponding to what would be its body at every call site. All the call-site checking is done accordingly (the lambda argument is treated in such a way that the compiler knows it’s going to be inclined).

Constructor inlining is not possible for user classes, so the inline modifier is prohibited in user code.

Sage answered 3/5, 2021 at 19:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.