Call for help on `new()` method of Box<T>. What is the `box` keyword?

impl<T> Box<T> {
    pub fn new(x: T) -> Self {
        box x
    }
    ...
}

I find this in Box<T> implementation, and the line box x confuses me a long time:

  1. What is box (lowercased)? It seems to be a keyword of Rust.
  2. What do box x do? What is the return type?

Yes, it's an old keyword that has never been in the stable (post-1.0) language and probably never will be.

box x as an expression has the type Box<T> where T is the type of x. It places x in a new heap allocation and returns a unique, owning pointer to that allocation. I think the only difference from Box::new(x) is that x is not placed on the stack first (see some of the comments on that issue).

That can be answered by looking at that 3-line function alone. Its type must be Box<T> because it is returned by the function immediately. For the same reason, it must have the same semantics of Box::new() – there's nothing else in that function.

I just checked the latest stable version of Rust standard library, Box::new() still uses box x. Seems that the box keyword is still in use? Or, maybe, normal users cannot use box any longer in their own code?

I think what the box keyword does here is almost identical to what malloc() function does.

Any longer? They have never been able to, unless you mean with a nightly compiler, in which case you still can.

The final type return by Box::new() is exactly Box<T>, this is doubtless. However, I am not sure if implicit type conversion happened here. By an example of C language:

char *new_str() {
    return malloc(8);
}

malloc() return void * but it is then converted to char * implicitly.

There isn't any implicit type conversion here.

I never tried. Just a guess. :thinking:

Rust has very very few type conversions that happen implicitly. The only that come to mind are stuff like *mut T to *const T and &'long T to &'short T and &T to &dyn SomeTrait.

2 Likes

TL;DR: Box was originally a part of language and had special syntax — and today it's a bit special, still, but that only happened because there was no time to properly rip it out before Rust 1.0 release.
IOW: you should be able to create your own Box-like type now, but couldn't do that via copy-paste of the original Box implementation.
You can read about that story here.

2 Likes

Right, I said it's never been in the stable language. The standard library is allowed to use unstable features, like box_syntax. You can use box in your own code if you use a nightly compiler and put #![feature(box_syntax)] in your crate root.

It's similar, but note that box and Box::new take care of both allocation and initialization, while malloc only does allocation. They also always return a valid pointer, while malloc can return NULL to indicate that allocation failed (in which situation Box::new would panic/abort/call some OOM handler). The closest thing to malloc in Rust's std is std::alloc::alloc.