Reputation: 844
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.
Upvotes: 2
Views: 164
Reputation: 430358
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.
Upvotes: 4
Reputation: 3599
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.
#[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);
}
Upvotes: 2