2

I'm trying to create static or constant from matching the env::home_dir:

static home: String = match env::home_dir() {
    Some(ref p) => p.to_str().unwrap().to_owned(),
    None => "./".to_string(),
};

But I'm getting a compiler bug:

src/main.rs:15:8: 15:13 error: internal compiler error: no enclosing scope found for scope: CodeExtent(346/Misc(20))
src/main.rs:15          Some(ref p) => p.to_str().unwrap().to_owned(),
                             ^~~~~
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
note: run with `RUST_BACKTRACE=1` for a backtrace
thread 'rustc' panicked at 'Box<Any>', ../src/libsyntax/diagnostic.rs:175

Is this a bug in my code or I should report this bug? Is it possible to get home as constant or static value?

I need to use it multiple times to add some file names for some file operations and I want to have them all in same folder.

2 Answers 2

4

Is this a bug in my code

Your code has something that doesn't make sense, so I guess it's a bug.

should I report this bug?

Probably. A compiler shouldn't crash, it should report the error nicely to the user. Look to see if there is an existing bug first though, and comment on it if there is.

Is it possible to get home as constant or static value?

Not exactly. Constant values are required to live for the entire length of the program. That means they exist before main starts and after main exits. It is impossible for the call to env::home_dir() to meet that exact criteria.

The most straight-forward thing to do is to get the value once and then pass it where it is needed. This allows you to avoid getting the value multiple times:

fn main() {
    let home = env::home_dir();
    let home = home.as_ref().map(|d| d.as_path()).unwrap_or(Path::new("./"));

    function_1(&home);
    function_2(&home);
    function_3(&home);
}

You could also place it into a struct, either as a &Path or a PathBuf:

struct Thing {
    home: PathBuf,
}

fn main() {
    let home = env::home_dir().unwrap_or_else(|| PathBuf::from("./"));
    let t = Thing { home: home };

    t.function_1();
    t.function_2();
    t.function_3();
}

This is probably what I'd do. There's no reason to keep that memory allocated forever, as a static value would.

I need to use it multiple times to add some file names for some file operations and I want to have them all in same folder.

There's nothing preventing you from simply creating a function to place the logic in:

fn safe_home_dir() -> PathBuf {
    env::home_dir().unwrap_or_else(|| PathBuf::from("./"))
} 

Then just call the function multiple times. You could profile to see how expensive it was, but my gut feeling is that there isn't going to be appreciable slowness here.


If you really needed it to be static, then you can use the lazy_static crate.

Sign up to request clarification or add additional context in comments.

1 Comment

AFAIK the reasons that Rust has "No life before main" are (1) Static Initialization Order Fiasco (a well known issue in C++) and (2) Start-up performance (it's easy to accidentally clutter your binary with lots of pre-main code).
2

Answer

Static variables can't have logic, to do this you have to use the lazy_static crate, which enables you to do logic. A small note, in order to access the veriable you have to deference it. so println!("{}", HOME); doesn't work, but println!("{}", *HOME); does.

Solution

#[macro_use]
extern crate lazy_static;
use std::env;
lazy_static! {
    static ref HOME: String = {
        match env::home_dir() {
            Some(p) => p.to_str().unwrap().to_owned(),
            None => "./".to_string(),
        }
    };
}

fn main() {
    println!("{:?}", *HOME);
}

2 Comments

Thanks, this worked) But what to do with the compiller bug?
@IvanTemchenko Go to the rust repo, and make an issue. Provide the snippet of code, that caused the compiler bug, along with your version of rust. You can find out your version of rust by typing the command rustc -vV.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.