4

This function will work for the type i32, but for the type str:

fn getValues() -> [str; 2] {
    [
        "37107287533902102798797998220837590246510135740250",
        "46376937677490009712648124896970078050417018260538",
    ]
}

I get the error:

error[E0277]: the size for values of type `str` cannot be known at compilation time
 --> src/lib.rs:1:1
  |
1 | / fn getValues() -> [str; 2] {
2 | |     [
3 | |         "37107287533902102798797998220837590246510135740250",
4 | |         "46376937677490009712648124896970078050417018260538",
5 | |     ]
6 | | }
  | |_^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `str`
  = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: slice and array elements must have `Sized` type

This error makes me think I need to add the size but I did: a size of 2. What is Rust wanting?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
camccar
  • 690
  • 12
  • 24

2 Answers2

10

str is the str primitive type, which is an unsized type, having some limitations -- you encountered one of them.

To solve your issue, instead of returning a plain str, you need to return a &str, a borrowed string slice. In this specific case you could even use &'static str, because string literals always have a static lifetime.

Also, because a primitive array is also a DST (dynamically sized type, another way to size unsized type), you need to specify the number of elements (which you did correctly).

So, the complete declaration would be fn getValues()-> [&'static str; 100].

If you do not know the size of the array at compile time, you might want to use a Vec, if you have some non-literal strings you likely want to use a String. That would look like

fn getValues() -> Vec<String> { vec!["shoten".into()] }

P.S.: Do not shy away from those heap-allocated, owned types -- they do make programming easier. Fighting with references and lifetimes is good style, but you don't need to do all that upfront, but instead optimize and refactor later.

gimpf
  • 4,503
  • 1
  • 27
  • 40
  • Worked fine. I'm a little confused as to why I need to put static if string literals always have a static lifetime. – camccar Oct 28 '18 at 15:06
  • Lifetimes are part of the type, and types need to be completely specified for function signatures in rust. The is something called [lifetime elision](https://doc.rust-lang.org/nomicon/lifetime-elision.html) which simplifies _specific_ cases, but Rust only rarely used such deduced properties. In this case elision does not apply because there is no lifetime use for the input arguments (as there are none). – gimpf Oct 28 '18 at 15:12
  • 1
    @camccar No the duplicate say an equivalent of this answer. – Stargateur Oct 28 '18 at 21:54
  • I don't see anywhere that says prepend with static. – camccar Oct 28 '18 at 21:57
2

It's saying str doesn't have a fixed size, not that the array doesn't. You can't have values of type str, you can only have them behind some kind of pointer.

Use [&'static str; 100].

DK.
  • 55,277
  • 5
  • 189
  • 162
  • Curios, why can't I have values of type str? – camccar Oct 28 '18 at 15:09
  • 1
    @camccar it's because the str type doesn't have a size. Therefore, its size can't be calculated for pre-allocating memory on the stack. On the other hand, a reference does have a size (It's basically just a pointer) – Optimistic Peach Oct 28 '18 at 16:00