1+ //! The implementation of built-in macros which relate to the file system. 
2+ 
13use  std:: path:: { Path ,  PathBuf } ; 
24use  std:: rc:: Rc ; 
35use  std:: sync:: Arc ; 
@@ -11,9 +13,11 @@ use rustc_expand::base::{
1113} ; 
1214use  rustc_expand:: module:: DirOwnership ; 
1315use  rustc_lint_defs:: BuiltinLintDiag ; 
14- use  rustc_parse:: parser:: { ForceCollect ,  Parser } ; 
16+ use  rustc_parse:: lexer:: StripTokens ; 
17+ use  rustc_parse:: parser:: ForceCollect ; 
1518use  rustc_parse:: { new_parser_from_file,  unwrap_or_emit_fatal,  utf8_error} ; 
1619use  rustc_session:: lint:: builtin:: INCOMPLETE_INCLUDE ; 
20+ use  rustc_session:: parse:: ParseSess ; 
1721use  rustc_span:: source_map:: SourceMap ; 
1822use  rustc_span:: { ByteSymbol ,  Pos ,  Span ,  Symbol } ; 
1923use  smallvec:: SmallVec ; 
@@ -23,11 +27,7 @@ use crate::util::{
2327    check_zero_tts,  get_single_str_from_tts,  get_single_str_spanned_from_tts,  parse_expr, 
2428} ; 
2529
26- // These macros all relate to the file system; they either return 
27- // the column/row/filename of the expression, or they include 
28- // a given file into the current one. 
29- 
30- /// line!(): expands to the current line number 
30+ /// Expand `line!()` to the current line number. 
3131pub ( crate )  fn  expand_line ( 
3232    cx :  & mut  ExtCtxt < ' _ > , 
3333    sp :  Span , 
@@ -42,7 +42,7 @@ pub(crate) fn expand_line(
4242    ExpandResult :: Ready ( MacEager :: expr ( cx. expr_u32 ( topmost,  loc. line  as  u32 ) ) ) 
4343} 
4444
45- /*  column!(): expands  to the current column number */  
45+ /// Expand ` column!()`  to the current column number.  
4646pub ( crate )  fn  expand_column ( 
4747    cx :  & mut  ExtCtxt < ' _ > , 
4848    sp :  Span , 
@@ -57,9 +57,7 @@ pub(crate) fn expand_column(
5757    ExpandResult :: Ready ( MacEager :: expr ( cx. expr_u32 ( topmost,  loc. col . to_usize ( )  as  u32  + 1 ) ) ) 
5858} 
5959
60- /// file!(): expands to the current filename */ 
61- /// The source_file (`loc.file`) contains a bunch more information we could spit 
62- /// out if we wanted. 
60+ /// Expand `file!()` to the current filename. 
6361pub ( crate )  fn  expand_file ( 
6462    cx :  & mut  ExtCtxt < ' _ > , 
6563    sp :  Span , 
@@ -81,6 +79,7 @@ pub(crate) fn expand_file(
8179    ) ) ) 
8280} 
8381
82+ /// Expand `stringify!($input)`. 
8483pub ( crate )  fn  expand_stringify ( 
8584    cx :  & mut  ExtCtxt < ' _ > , 
8685    sp :  Span , 
@@ -91,6 +90,7 @@ pub(crate) fn expand_stringify(
9190    ExpandResult :: Ready ( MacEager :: expr ( cx. expr_str ( sp,  Symbol :: intern ( & s) ) ) ) 
9291} 
9392
93+ /// Expand `module_path!()` to (a textual representation of) the current module path. 
9494pub ( crate )  fn  expand_mod ( 
9595    cx :  & mut  ExtCtxt < ' _ > , 
9696    sp :  Span , 
@@ -104,9 +104,9 @@ pub(crate) fn expand_mod(
104104    ExpandResult :: Ready ( MacEager :: expr ( cx. expr_str ( sp,  Symbol :: intern ( & string) ) ) ) 
105105} 
106106
107- /// include! : parse the given file as an expr  
108- /// This is generally a bad idea because it's going to behave  
109- /// unhygienically . 
107+ /// Expand ` include!($input)`.  
108+ /// 
109+ /// This works in item and expression position. Notably, it doesn't work in pattern position . 
110110pub ( crate )  fn  expand_include < ' cx > ( 
111111    cx :  & ' cx  mut  ExtCtxt < ' _ > , 
112112    sp :  Span , 
@@ -116,64 +116,76 @@ pub(crate) fn expand_include<'cx>(
116116    let  ExpandResult :: Ready ( mac)  = get_single_str_from_tts ( cx,  sp,  tts,  "include!" )  else  { 
117117        return  ExpandResult :: Retry ( ( ) ) ; 
118118    } ; 
119-     let  file  = match  mac { 
120-         Ok ( file )  => file , 
119+     let  path  = match  mac { 
120+         Ok ( path )  => path , 
121121        Err ( guar)  => return  ExpandResult :: Ready ( DummyResult :: any ( sp,  guar) ) , 
122122    } ; 
123123    // The file will be added to the code map by the parser 
124-     let  file  = match  resolve_path ( & cx. sess ,  file . as_str ( ) ,  sp)  { 
125-         Ok ( f )  => f , 
124+     let  path  = match  resolve_path ( & cx. sess ,  path . as_str ( ) ,  sp)  { 
125+         Ok ( path )  => path , 
126126        Err ( err)  => { 
127127            let  guar = err. emit ( ) ; 
128128            return  ExpandResult :: Ready ( DummyResult :: any ( sp,  guar) ) ; 
129129        } 
130130    } ; 
131-     let  p = unwrap_or_emit_fatal ( new_parser_from_file ( cx. psess ( ) ,  & file,  Some ( sp) ) ) ; 
132131
133132    // If in the included file we have e.g., `mod bar;`, 
134-     // then the path of `bar.rs` should be relative to the directory of `file `. 
133+     // then the path of `bar.rs` should be relative to the directory of `path `. 
135134    // See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion. 
136135    // `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained. 
137-     let  dir_path = file . parent ( ) . unwrap_or ( & file ) . to_owned ( ) ; 
136+     let  dir_path = path . parent ( ) . unwrap_or ( & path ) . to_owned ( ) ; 
138137    cx. current_expansion . module  = Rc :: new ( cx. current_expansion . module . with_dir_path ( dir_path) ) ; 
139138    cx. current_expansion . dir_ownership  = DirOwnership :: Owned  {  relative :  None  } ; 
140139
141140    struct  ExpandInclude < ' a >  { 
142-         p :  Parser < ' a > , 
141+         psess :  & ' a  ParseSess , 
142+         path :  PathBuf , 
143143        node_id :  ast:: NodeId , 
144+         span :  Span , 
144145    } 
145146    impl < ' a >  MacResult  for  ExpandInclude < ' a >  { 
146-         fn  make_expr ( mut  self :  Box < ExpandInclude < ' a > > )  -> Option < Box < ast:: Expr > >  { 
147-             let  expr = parse_expr ( & mut  self . p ) . ok ( ) ?; 
148-             if  self . p . token  != token:: Eof  { 
149-                 self . p . psess . buffer_lint ( 
147+         fn  make_expr ( self :  Box < ExpandInclude < ' a > > )  -> Option < Box < ast:: Expr > >  { 
148+             let  mut  p = unwrap_or_emit_fatal ( new_parser_from_file ( 
149+                 self . psess , 
150+                 & self . path , 
151+                 // Don't strip frontmatter for backward compatibility, `---` may be the start of a 
152+                 // manifold negation. FIXME: Ideally, we wouldn't strip shebangs here either. 
153+                 StripTokens :: Shebang , 
154+                 Some ( self . span ) , 
155+             ) ) ; 
156+             let  expr = parse_expr ( & mut  p) . ok ( ) ?; 
157+             if  p. token  != token:: Eof  { 
158+                 p. psess . buffer_lint ( 
150159                    INCOMPLETE_INCLUDE , 
151-                     self . p . token . span , 
160+                     p. token . span , 
152161                    self . node_id , 
153162                    BuiltinLintDiag :: IncompleteInclude , 
154163                ) ; 
155164            } 
156165            Some ( expr) 
157166        } 
158167
159-         fn  make_items ( mut  self :  Box < ExpandInclude < ' a > > )  -> Option < SmallVec < [ Box < ast:: Item > ;  1 ] > >  { 
168+         fn  make_items ( self :  Box < ExpandInclude < ' a > > )  -> Option < SmallVec < [ Box < ast:: Item > ;  1 ] > >  { 
169+             let  mut  p = unwrap_or_emit_fatal ( new_parser_from_file ( 
170+                 self . psess , 
171+                 & self . path , 
172+                 StripTokens :: ShebangAndFrontmatter , 
173+                 Some ( self . span ) , 
174+             ) ) ; 
160175            let  mut  ret = SmallVec :: new ( ) ; 
161176            loop  { 
162-                 match  self . p . parse_item ( ForceCollect :: No )  { 
177+                 match  p. parse_item ( ForceCollect :: No )  { 
163178                    Err ( err)  => { 
164179                        err. emit ( ) ; 
165180                        break ; 
166181                    } 
167182                    Ok ( Some ( item) )  => ret. push ( item) , 
168183                    Ok ( None )  => { 
169-                         if  self . p . token  != token:: Eof  { 
170-                             self . p 
171-                                 . dcx ( ) 
172-                                 . create_err ( errors:: ExpectedItem  { 
173-                                     span :  self . p . token . span , 
174-                                     token :  & pprust:: token_to_string ( & self . p . token ) , 
175-                                 } ) 
176-                                 . emit ( ) ; 
184+                         if  p. token  != token:: Eof  { 
185+                             p. dcx ( ) . emit_err ( errors:: ExpectedItem  { 
186+                                 span :  p. token . span , 
187+                                 token :  & pprust:: token_to_string ( & p. token ) , 
188+                             } ) ; 
177189                        } 
178190
179191                        break ; 
@@ -184,10 +196,17 @@ pub(crate) fn expand_include<'cx>(
184196        } 
185197    } 
186198
187-     ExpandResult :: Ready ( Box :: new ( ExpandInclude  {  p,  node_id :  cx. current_expansion . lint_node_id  } ) ) 
199+     ExpandResult :: Ready ( Box :: new ( ExpandInclude  { 
200+         psess :  cx. psess ( ) , 
201+         path, 
202+         node_id :  cx. current_expansion . lint_node_id , 
203+         span :  sp, 
204+     } ) ) 
188205} 
189206
190- /// `include_str!`: read the given file, insert it as a literal string expr 
207+ /// Expand `include_str!($input)` to the content of the UTF-8-encoded file given by path `$input` as a string literal. 
208+ /// 
209+ /// This works in expression, pattern and statement position. 
191210pub ( crate )  fn  expand_include_str ( 
192211    cx :  & mut  ExtCtxt < ' _ > , 
193212    sp :  Span , 
@@ -206,6 +225,7 @@ pub(crate) fn expand_include_str(
206225        Ok ( ( bytes,  bsp) )  => match  std:: str:: from_utf8 ( & bytes)  { 
207226            Ok ( src)  => { 
208227                let  interned_src = Symbol :: intern ( src) ; 
228+                 // MacEager converts the expr into a pat if need be. 
209229                MacEager :: expr ( cx. expr_str ( cx. with_def_site_ctxt ( bsp) ,  interned_src) ) 
210230            } 
211231            Err ( utf8err)  => { 
@@ -218,6 +238,9 @@ pub(crate) fn expand_include_str(
218238    } ) 
219239} 
220240
241+ /// Expand `include_bytes!($input)` to the content of the file given by path `$input`. 
242+ /// 
243+ /// This works in expression, pattern and statement position. 
221244pub ( crate )  fn  expand_include_bytes ( 
222245    cx :  & mut  ExtCtxt < ' _ > , 
223246    sp :  Span , 
@@ -237,6 +260,7 @@ pub(crate) fn expand_include_bytes(
237260            // Don't care about getting the span for the raw bytes, 
238261            // because the console can't really show them anyway. 
239262            let  expr = cx. expr ( sp,  ast:: ExprKind :: IncludedBytes ( ByteSymbol :: intern ( & bytes) ) ) ; 
263+             // MacEager converts the expr into a pat if need be. 
240264            MacEager :: expr ( expr) 
241265        } 
242266        Err ( dummy)  => dummy, 
0 commit comments