@@ -53,7 +53,7 @@ pub fn expand_env<'cx>(
5353 tts : TokenStream ,
5454) -> Box < dyn base:: MacResult + ' cx > {
5555 let mut exprs = match get_exprs_from_tts ( cx, tts) {
56- Some ( exprs) if exprs. is_empty ( ) => {
56+ Some ( exprs) if exprs. is_empty ( ) || exprs . len ( ) > 2 => {
5757 cx. span_err ( sp, "env! takes 1 or 2 arguments" ) ;
5858 return DummyResult :: any ( sp) ;
5959 }
@@ -64,28 +64,48 @@ pub fn expand_env<'cx>(
6464 let Some ( ( var, _style) ) = expr_to_string ( cx, exprs. next ( ) . unwrap ( ) , "expected string literal" ) else {
6565 return DummyResult :: any ( sp) ;
6666 } ;
67- let msg = match exprs. next ( ) {
68- None => Symbol :: intern ( & format ! ( "environment variable `{}` not defined" , var) ) ,
67+
68+ let custom_msg = match exprs. next ( ) {
69+ None => None ,
6970 Some ( second) => match expr_to_string ( cx, second, "expected string literal" ) {
7071 None => return DummyResult :: any ( sp) ,
71- Some ( ( s, _style) ) => s ,
72+ Some ( ( s, _style) ) => Some ( s ) ,
7273 } ,
7374 } ;
7475
75- if exprs. next ( ) . is_some ( ) {
76- cx. span_err ( sp, "env! takes 1 or 2 arguments" ) ;
77- return DummyResult :: any ( sp) ;
78- }
79-
8076 let sp = cx. with_def_site_ctxt ( sp) ;
8177 let value = env:: var ( var. as_str ( ) ) . ok ( ) . as_deref ( ) . map ( Symbol :: intern) ;
8278 cx. sess . parse_sess . env_depinfo . borrow_mut ( ) . insert ( ( var, value) ) ;
8379 let e = match value {
8480 None => {
85- cx. span_err ( sp, msg. as_str ( ) ) ;
81+ let ( msg, help) = match custom_msg {
82+ None => (
83+ format ! ( "environment variable `{var}` not defined at compile time" ) ,
84+ Some ( help_for_missing_env_var ( var. as_str ( ) ) ) ,
85+ ) ,
86+ Some ( s) => ( s. to_string ( ) , None ) ,
87+ } ;
88+ let mut diag = cx. struct_span_err ( sp, & msg) ;
89+ if let Some ( help) = help {
90+ diag. help ( help) ;
91+ }
92+ diag. emit ( ) ;
8693 return DummyResult :: any ( sp) ;
8794 }
8895 Some ( value) => cx. expr_str ( sp, value) ,
8996 } ;
9097 MacEager :: expr ( e)
9198}
99+
100+ fn help_for_missing_env_var ( var : & str ) -> String {
101+ if var. starts_with ( "CARGO_" )
102+ || var. starts_with ( "DEP_" )
103+ || matches ! ( var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET" )
104+ {
105+ format ! (
106+ "Cargo sets build script variables at run time. Use `std::env::var(\" {var}\" )` instead"
107+ )
108+ } else {
109+ format ! ( "Use `std::env::var(\" {var}\" )` to read the variable at run time" )
110+ }
111+ }
0 commit comments