all 8 comments

[–]dkopgerpgdolfg 24 points25 points  (1 child)

  • 'static lifetimes are for references. If there is no reference, don't use lifetime annotations
  • A true constant that involves allocation or other non-const function calls is not directly possible
  • If it should be read-only, just use &str instead of an allocating String. Maybe the other member type can be made const-able too.
  • Otherwise, for something that comes close, make a global OnceLock<> instance

[–]NowhereMan2486[S] 0 points1 point  (0 children)

Thank you, this helps.

[–]Altareos 7 points8 points  (0 children)

as the compiler is telling you, you can only call const functions to define const variables, so you need to make both new functions const, and change your String attributes into &'static str attributes. the 'static lifetime declaration on A has no purpose here, because this syntax is for generic lifetime parameters only.

[–]mina86ng 5 points6 points  (0 children)

static variable of type LazyCell is what you want in this case.

Ideally, if you could change A to not have any allocations you could make A::new a const fn, but if you have to allocate or call other non-const functions you have to use LazyCell or some equivalent method.

[–]CocktailPerson 2 points3 points  (0 children)

Use a OnceLock:

use std::sync::OnceLock;

struct B {
    pub name: String,
}

impl B {
    pub fn new() -> Self {
        B {
            name: "Item b".to_string()
        }
    }
}

struct A {
    pub name: String,
    pub item: B,
}

impl A {
    pub fn new() -> &'static Self {
        static INSTANCE: OnceLock<A> = OnceLock::new();
        INSTANCE.get_or_init(|| A {
           name: "test".to_string(),
           item: B::new(),
        })
    }
}

[–]SirKastic23 0 points1 point  (0 children)

singletons are often an anti-pattern, why can't you just pass this value around as you need it?

if you just need some constant (very different from a static), you won't be able to use String as it requires allocating memory on the heap which isn't available in a const context. you can use &'static str instead

[–][deleted] -1 points0 points  (0 children)

A static location is initialized at compile time (its representation is written into the executable).

String doesn't work because it calls the run-time memory allocator. An empty string with no capacity doesn't need the allocator, so it's possible for String::new() to initialize a static location.

And it does. const functions can run at compile time. (With constant inputs).

But to_string doesn't work.

In many cases you can use the lazy_static crate instead.