27

I'm trying to declare a String constant in Rust, but I get a compiler error I just can't make sense of

const DATABASE : String::from("/var/lib/tracker/tracker.json");

and here's what I get when I try to compile it:

error: expected type, found `"/var/lib/tracker/tracker.json"`
  --> src/main.rs:19:31
   |
19 | const DATABASE : String::from("/var/lib/tracker/tracker.json");
   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: expected one of `!`, `+`, `->`, `::`, or `=`, found `)`
  --> src/main.rs:19:64
   |
19 | const DATABASE : String::from("/var/lib/tracker/tracker.json");
   |                                                                ^ expected one of `!`, `+`, `->`, `::`, or `=` here
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
arsalan86
  • 575
  • 2
  • 5
  • 9
  • Have you tried `const DATABASE = String::` instead of `const DATABASE :`? The : implies you are annotating the type, which you are not. – perfect5th Jul 18 '17 at 20:27
  • I did try that. Here's the compiler output: `error: expected ':', found '='` for: `const DATABASE = String::from("f")` – arsalan86 Jul 18 '17 at 20:28
  • 1
    Ah... you have to annotate the type of a const, and you can't use `String` because it needs a static size, so you'll have to use `&str`. try this: `const DATABASE: &str = "/var/lib/tracker/tracker.json";` See Shepmaster's answer. – perfect5th Jul 18 '17 at 20:32

1 Answers1

56

You should read The Rust Programming Language, specifically the chapter that discusses constants. The proper syntax for declaring a const is:

const NAME: Type = value;

In this case:

const DATABASE: String = String::from("/var/lib/tracker/tracker.json");

However, this won't work because allocating a string is not something that can be computed at compile time. That's what const means. You may want to use a string slice, specifically one with a static lifetime, which is implicit in consts and statics:

const DATABASE: &str = "/var/lib/tracker/tracker.json";

Functions that just need to read a string should accept a &str, so this is unlikely to cause any issues. It also has the nice benefit of requiring no allocation whatsoever, so it's pretty efficient.

If you need a String, it's likely that you will need to mutate it. In that case, making it global would lead to threading issues. Instead, you should just allocate when you need it with String::from(DATABASE) and pass in the String.

See also:

Saurabh
  • 5,176
  • 4
  • 32
  • 46
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Thanks! this worked, and the explanation is really helpful too! I am reading the book, and I now realize what I was doing wrong. – arsalan86 Jul 18 '17 at 20:39
  • 4
    Note: *not something that can be computed at compile time* => this is more an implementation limitation than a language limitation. It would be perfectly reasonable to pre-compute the String (and do nothing about the Drop), after all, there is not much difference between `&str` (pointer + length) and `String` (pointer + length + capacity). – Matthieu M. Jul 19 '17 at 09:20
  • 4
    The inability to call String::from at compile time is certainly a language limitation, not merely an implementation limitation ... and there's no other way to express pre-computation of a String. – Jim Balter Sep 21 '18 at 10:02
  • 2
    @JimBalter please see the update which links to multiple ways to express the concept. It's both a language limitation as well as an implementation limitation, but it's something that people are very actively working to try and allow. – Shepmaster Sep 21 '18 at 12:41
  • 1
    My comment was a correction of Matthieu's claim. You and I are both saying that it's both a language limitation and an implementation limitation, which it obviously is, contrary to what Matthieu said. You say at the link that this might be doable in the "far future", after several changes have been made to the language. – Jim Balter Sep 23 '18 at 23:34
  • 1
    @dustytrash there are three pieces of code so “this” is not helpful. Please provide a playground link with the problematic code in question. – Shepmaster Oct 04 '20 at 02:03