@@ -86,7 +86,6 @@ pub fn find_builtin_macro(
8686register_builtin ! {
8787 LAZY :
8888 ( column, Column ) => column_expand,
89- ( compile_error, CompileError ) => compile_error_expand,
9089 ( file, File ) => file_expand,
9190 ( line, Line ) => line_expand,
9291 ( assert, Assert ) => assert_expand,
@@ -97,6 +96,7 @@ register_builtin! {
9796 ( format_args_nl, FormatArgsNl ) => format_args_expand,
9897
9998 EAGER :
99+ ( compile_error, CompileError ) => compile_error_expand,
100100 ( concat, Concat ) => concat_expand,
101101 ( include, Include ) => include_expand,
102102 ( include_bytes, IncludeBytes ) => include_bytes_expand,
@@ -213,25 +213,6 @@ fn file_expand(
213213 ExpandResult :: ok ( expanded)
214214}
215215
216- fn compile_error_expand (
217- _db : & dyn AstDatabase ,
218- _id : LazyMacroId ,
219- tt : & tt:: Subtree ,
220- ) -> ExpandResult < tt:: Subtree > {
221- if tt. count ( ) == 1 {
222- if let tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( it) ) = & tt. token_trees [ 0 ] {
223- let s = it. text . as_str ( ) ;
224- if s. contains ( '"' ) {
225- return ExpandResult :: ok ( quote ! { loop { #it } } ) ;
226- }
227- } ;
228- }
229-
230- ExpandResult :: only_err ( mbe:: ExpandError :: BindingError (
231- "`compile_error!` argument be a string" . into ( ) ,
232- ) )
233- }
234-
235216fn format_args_expand (
236217 _db : & dyn AstDatabase ,
237218 _id : LazyMacroId ,
@@ -280,6 +261,30 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
280261 token. value ( ) . map ( |it| it. into_owned ( ) )
281262}
282263
264+ fn compile_error_expand (
265+ _db : & dyn AstDatabase ,
266+ _id : EagerMacroId ,
267+ tt : & tt:: Subtree ,
268+ ) -> ExpandResult < Option < ( tt:: Subtree , FragmentKind ) > > {
269+ let err = match & * tt. token_trees {
270+ [ tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( it) ) ] => {
271+ let text = it. text . as_str ( ) ;
272+ if text. starts_with ( '"' ) && text. ends_with ( '"' ) {
273+ // FIXME: does not handle raw strings
274+ mbe:: ExpandError :: Other ( format ! (
275+ "`compile_error!` called: {}" ,
276+ & text[ 1 ..text. len( ) - 1 ]
277+ ) )
278+ } else {
279+ mbe:: ExpandError :: BindingError ( "`compile_error!` argument must be a string" . into ( ) )
280+ }
281+ }
282+ _ => mbe:: ExpandError :: BindingError ( "`compile_error!` argument must be a string" . into ( ) ) ,
283+ } ;
284+
285+ ExpandResult { value : Some ( ( quote ! { } , FragmentKind :: Items ) ) , err : Some ( err) }
286+ }
287+
283288fn concat_expand (
284289 _db : & dyn AstDatabase ,
285290 _arg_id : EagerMacroId ,
@@ -417,17 +422,25 @@ fn env_expand(
417422 Err ( e) => return ExpandResult :: only_err ( e) ,
418423 } ;
419424
420- // FIXME:
421- // If the environment variable is not defined int rustc, then a compilation error will be emitted.
422- // We might do the same if we fully support all other stuffs.
423- // But for now on, we should return some dummy string for better type infer purpose.
424- // However, we cannot use an empty string here, because for
425- // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become
426- // `include!("foo.rs"), which might go to infinite loop
427- let s = get_env_inner ( db, arg_id, & key) . unwrap_or_else ( || "__RA_UNIMPLEMENTED__" . to_string ( ) ) ;
425+ let mut err = None ;
426+ let s = get_env_inner ( db, arg_id, & key) . unwrap_or_else ( || {
427+ // The only variable rust-analyzer ever sets is `OUT_DIR`, so only diagnose that to avoid
428+ // unnecessary diagnostics for eg. `CARGO_PKG_NAME`.
429+ if key == "OUT_DIR" {
430+ err = Some ( mbe:: ExpandError :: Other (
431+ r#"`OUT_DIR` not set, enable "load out dirs from check" to fix"# . into ( ) ,
432+ ) ) ;
433+ }
434+
435+ // If the variable is unset, still return a dummy string to help type inference along.
436+ // We cannot use an empty string here, because for
437+ // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become
438+ // `include!("foo.rs"), which might go to infinite loop
439+ "__RA_UNIMPLEMENTED__" . to_string ( )
440+ } ) ;
428441 let expanded = quote ! { #s } ;
429442
430- ExpandResult :: ok ( Some ( ( expanded, FragmentKind :: Expr ) ) )
443+ ExpandResult { value : Some ( ( expanded, FragmentKind :: Expr ) ) , err }
431444}
432445
433446fn option_env_expand (
@@ -638,7 +651,8 @@ mod tests {
638651 "# ,
639652 ) ;
640653
641- assert_eq ! ( expanded, r#"loop{"error!"}"# ) ;
654+ // This expands to nothing (since it's in item position), but emits an error.
655+ assert_eq ! ( expanded, "" ) ;
642656 }
643657
644658 #[ test]
0 commit comments