Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the error "the trait Sized is not implemented" when trying to return a value from a vector

Tags:

rust

I am trying to return the values of a vector:

fn merge<'a>(left: &'a [i32], right: &'a [i32]) -> [i32] {
    let mut merged: Vec<i32> = Vec::new();
    // push elements to merged
    *merged
}

I get the error message:

error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
 --> src/lib.rs:1:52
  |
1 | fn merge<'a>(left: &'a [i32], right: &'a [i32]) -> [i32] {
  |                                                    ^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `[i32]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: the return type of a function must have a statically known size

I can't find out how to fix this.

like image 807
jogleul Avatar asked Jan 27 '15 16:01

jogleul


1 Answers

The compiler is telling you that it is impossible to return a [T].

Rust has owned vectors (Vec<T>), slices (&[T]) and fixed-size arrays ([T; N], where N is a non-negative integer like 6).

A slice is composed of a pointer to data and a length. This is what your left and right values are. However, what isn't specified in a slice is who ultimately owns the data. Slices just borrow data from something else. You can treat the & as a signal that the data is borrowed.

A Vec is one thing that owns data and can let other things borrow it via a slice. For your problem, you need to allocate some memory to store the values, and Vec does that for you. You can then return the entire Vec, transferring ownership to the caller.

The specific error message means that the compiler doesn't know how much space to allocate for the type [i32], because it's never meant to be allocated directly. You'll see this error for other things in Rust, usually when you try to dereference a trait object, but that's distinctly different from the case here.

Here's the most likely fix you want:

fn merge(left: &[i32], right: &[i32]) -> Vec<i32> {
    let mut merged = Vec::new();
    // push elements to merged
    merged
}

Additionally, you don't need to specify lifetimes here, and I removed the redundant type annotation on your merged declaration.

See also:

  • Is there any way to return a reference to a variable created in a function?
  • Why can fixed-size arrays be on the stack, but str cannot?
  • Why is `let ref a: Trait = Struct` forbidden?
like image 186
Shepmaster Avatar answered Sep 18 '22 12:09

Shepmaster