Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

env_or_default macro #48952

Closed
vbrandl opened this issue Mar 12, 2018 · 16 comments
Closed

env_or_default macro #48952

vbrandl opened this issue Mar 12, 2018 · 16 comments
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@vbrandl
Copy link
Contributor

vbrandl commented Mar 12, 2018

I find my self doing something like this quite often:

const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");

fn main() {
    println!("{}", VERSION.unwrap_or("unknown version"));
}

I think it would be nice to have a env_or_default macro that defaults to a fallback string at compile time if the environment variable cannot be found. I'm thinking of something like

const VERSION: &str = env_or_default!("CARGO_PKG_VERSION", "unknown version");

I know the runtime cost isn't that high but if it can be done at compile time, it should be done.

@kennytm
Copy link
Member

kennytm commented Mar 12, 2018

Alternatively we could just make .unwrap_or() a const fn to allow it being used in the const constructor.

const VERSION: &str = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown version");

@kennytm kennytm added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. A-const-fn C-feature-request Category: A feature request, i.e: not implemented / a PR. A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) labels Mar 12, 2018
@hanna-kruppe
Copy link
Contributor

hanna-kruppe commented Mar 12, 2018

Agreed. We can't make unwrap_or a const fn just yet (needs rust-lang/rfcs#2342) but once we can, we should and then this macro would be redundant and deprecated.

@ExpHP
Copy link
Contributor

ExpHP commented Mar 12, 2018

I don't think it is uncommon to require different semantics than just a default for None. The majority of my env lookups usually treat the empty string as equivalent to an unset variable, because (a) they're easier to set in the shell, (b) an empty string is not a useful value for many types of things, such as integers, paths, or version numbers.

Having something like LIBXYZ_DIR= cargo build search the current directory is silly.

fn nonempty_env(name: &str) -> Option<String> {
    match env::var(name) {
        Ok("") | Err(env::VarError::NotPresent) => None,
        Err(e) => panic!("error looking up {}: {}", name, e),
        Ok(s) => Some(s),
    }
}

So for me, env_or_default! would still not be useful.

@matobet
Copy link

matobet commented Jul 4, 2020

@hanna-kruppe now that rust-lang/rfcs#2342 has been merged, can we make .unwrap_or const fn?

@hanna-kruppe
Copy link
Contributor

I think so.

@TheButlah
Copy link

Saw #76330, but it was closed because destructors cannot run in const contexts just yet

@frederikhors
Copy link

I'm new to Rust. I'm using rust 1.60.0.

I'm trying to use this code (PLAYGROUND HERE):

pub const VERSION: &'static str = option_env!("VERSION").unwrap_or_else(|| "dev");

but I'm getting this error:

the trait bound `[closure@src\constants.rs:4:81: 4:89]: ~const FnOnce<()>` is not satisfied
the trait `~const FnOnce<()>` is not implemented for `[closure@src\constants.rs:4:81: 4:89]`
wrap the `[closure@src\constants.rs:4:81: 4:89]` in a closure with no arguments: `|| { /* code */ }`rustcE0277
constants.rs(4, 66): the trait `FnOnce<()>` is implemented for `[closure@src\constants.rs:4:81: 4:89]`, but that implementation is not `const`
option.rs(797, 12): required by a bound in `Option::<T>::unwrap_or_else`

Can you help me understand what's wrong with it?

@oli-obk
Copy link
Contributor

oli-obk commented May 7, 2022

The diagnostic should actually just tell you that the function is not a const fn. But we messed up a bit, so you get a different error first. You just can't do this yet that way, you have to match manually and implement the some and none arms of the match yourself.

@robertbastian
Copy link
Contributor

I have a use case for this that's not covered by unwrap_or:

include!(core::option_env!("DATA_ROOT").unwrap_or("empty_data/mod.rs"));

This doesn't compile because include! requires a string literal. env_or_default! would evaluate to a string literal and thus be compatible with include!, include_str!, and include_bytes!.

@punkeel
Copy link

punkeel commented Mar 9, 2023

Tracking issue for const fn unwrap_or: #91930.

This issue also contains a nice workaround:

pub const VERSION: &str= match option_env!("VERSION") {
    Some(v) => v,
    None => "dev",
};

@WhyNotHugo
Copy link

Might I suggest closing this in favour of #91930? It allows doing this with unwrap_or.

@robertbastian
Copy link
Contributor

That does not cover the use case in my previous comment.

@WhyNotHugo
Copy link

Maybe it's best to adapt include! to accept any &'static str, and not just a string literal?

@robertbastian
Copy link
Contributor

I assume include!s are resolved very early in the compiler, I highly doubt that const expressions will be evaluated at that point.

@Dylan-DPC
Copy link
Member

Closing this in favour of #91930

@Dylan-DPC Dylan-DPC closed this as not planned Won't fix, can't repro, duplicate, stale Dec 3, 2023
@robertbastian
Copy link
Contributor

That doesn't work for includes

@RalfJung RalfJung added the A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) label Dec 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests