Some, still Some, ...and then None?

Here, dir is an Option<FlexPath>, which is printed everytime as Some("/path/to/file").

println!("{dir:?}");
let workspace_or_main_dir = workspace_dir.as_ref().unwrap_or(dir.as_ref().unwrap());

// Target path
let target_path = PathBuf::from_str(&workspace_or_main_dir.resolve("target").to_string_with_flex_separator()).unwrap();

// Read the run cache file
let mut run_cache_file: Option<RunCacheFile> = None;
let run_cache_path = PathBuf::from_str(&workspace_or_main_dir.resolve("target/.run-cache.toml").to_string_with_flex_separator()).unwrap();
if std::fs::exists(&run_cache_path).unwrap() && std::fs::metadata(&run_cache_path).unwrap().is_file() {
    run_cache_file = Some(toml::from_str::<RunCacheFile>(&std::fs::read_to_string(&run_cache_path).unwrap()).unwrap());
}
if run_cache_file.is_none() {
    run_cache_file = Some(RunCacheFile {
        packages: vec![]
    });
}
let mut run_cache_file = run_cache_file.unwrap();

// Initial lockfile
if lockfile.is_none() {
    lockfile = Some(WhackLockfile {
        package: vec![]
    });
}
let mut lockfile = lockfile.unwrap();

// Current directory (prefer non-workspace directory)
println!("{dir:?}");
let dir = dir.as_ref().unwrap_or(workspace_dir.as_ref().unwrap());

However, in the last .unwrap() you see it simply panics. Why? It didn't panic the first time we used dir in the above code region (so it should be Some).

In the last line, you unwrap workspace_dir, not dir, and it was never unwrapped before. What's the question?

In the beginning:

println!("{dir:?}");
let workspace_or_main_dir = workspace_dir.as_ref().unwrap_or(dir.as_ref().unwrap());

In the ending lines:

println!("{dir:?}");
let dir = dir.as_ref().unwrap_or(workspace_dir.as_ref().unwrap());

What I mean is that workspace_dir is read as None, and dir is always read as Some. And it panicked because dir was wrongly assumed None, causing workspace_dir to evaluate.

No, in the last line: workspace_dir.unwrap() is evaluated before dir.unwrap_or().

Maybe, you would like unwrap_or_else()

let dir = dir.as_ref().unwrap_or_else(|| workspace_dir.as_ref().unwrap());

This effectively delays the evaluation of workspace.unwrap().

3 Likes

Wait, yes, I forgot that I was not lazily evaluating indeed. Thanks!

You could shorten that to

let dir = dir.as_ref().or(workspace_dir.as_ref()).unwrap();

3 Likes