@@ -3,7 +3,7 @@ use crate::config::StripUnconfigured;
33use crate :: configure;
44use crate :: hygiene:: SyntaxContext ;
55use crate :: mbe:: macro_rules:: annotate_err_with_kind;
6- use crate :: module:: { parse_external_mod , push_directory , Directory , DirectoryOwnership } ;
6+ use crate :: module:: { mod_dir_path , parse_external_mod , DirOwnership , ParsedExternalMod } ;
77use crate :: placeholders:: { placeholder, PlaceholderExpander } ;
88
99use rustc_ast as ast;
@@ -355,16 +355,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
355355 // FIXME: Avoid visiting the crate as a `Mod` item,
356356 // make crate a first class expansion target instead.
357357 pub fn expand_crate ( & mut self , mut krate : ast:: Crate ) -> ast:: Crate {
358- let mut module = ModuleData {
359- mod_path : vec ! [ Ident :: from_str( & self . cx. ecfg. crate_name) ] ,
360- directory : match self . cx . source_map ( ) . span_to_unmapped_path ( krate. span ) {
361- FileName :: Real ( name) => name. into_local_path ( ) ,
362- other => PathBuf :: from ( other. to_string ( ) ) ,
363- } ,
358+ let file_path = match self . cx . source_map ( ) . span_to_unmapped_path ( krate. span ) {
359+ FileName :: Real ( name) => name. into_local_path ( ) ,
360+ other => PathBuf :: from ( other. to_string ( ) ) ,
364361 } ;
365- module. directory . pop ( ) ;
366- self . cx . root_path = module. directory . clone ( ) ;
367- self . cx . current_expansion . module = Rc :: new ( module) ;
362+ let dir_path = file_path. parent ( ) . unwrap_or ( & file_path) . to_owned ( ) ;
363+ self . cx . root_path = dir_path. clone ( ) ;
364+ self . cx . current_expansion . module = Rc :: new ( ModuleData {
365+ mod_path : vec ! [ Ident :: from_str( & self . cx. ecfg. crate_name) ] ,
366+ file_path_stack : vec ! [ file_path] ,
367+ dir_path,
368+ } ) ;
368369
369370 let krate_item = AstFragment :: Items ( smallvec ! [ P ( ast:: Item {
370371 attrs: krate. attrs,
@@ -1245,10 +1246,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12451246 }
12461247
12471248 fn visit_block ( & mut self , block : & mut P < Block > ) {
1248- let old_directory_ownership = self . cx . current_expansion . directory_ownership ;
1249- self . cx . current_expansion . directory_ownership = DirectoryOwnership :: UnownedViaBlock ;
1249+ let orig_dir_ownership = mem:: replace (
1250+ & mut self . cx . current_expansion . dir_ownership ,
1251+ DirOwnership :: UnownedViaBlock ,
1252+ ) ;
12501253 noop_visit_block ( block, self ) ;
1251- self . cx . current_expansion . directory_ownership = old_directory_ownership ;
1254+ self . cx . current_expansion . dir_ownership = orig_dir_ownership ;
12521255 }
12531256
12541257 fn flat_map_item ( & mut self , item : P < ast:: Item > ) -> SmallVec < [ P < ast:: Item > ; 1 ] > {
@@ -1276,63 +1279,76 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12761279 } )
12771280 }
12781281 ast:: ItemKind :: Mod ( _, ref mut mod_kind) if ident != Ident :: invalid ( ) => {
1279- let sess = & self . cx . sess . parse_sess ;
1280- let orig_ownership = self . cx . current_expansion . directory_ownership ;
1281- let mut module = ( * self . cx . current_expansion . module ) . clone ( ) ;
1282-
1283- let pushed = & mut false ; // Record `parse_external_mod` pushing so we can pop.
1284- let dir = Directory { ownership : orig_ownership, path : module. directory } ;
1285- let Directory { ownership, path } = match mod_kind {
1286- ModKind :: Loaded ( _, Inline :: Yes , _) => {
1282+ let ( file_path, dir_path, dir_ownership) = match mod_kind {
1283+ ModKind :: Loaded ( _, inline, _) => {
12871284 // Inline `mod foo { ... }`, but we still need to push directories.
1285+ assert ! (
1286+ * inline == Inline :: Yes ,
1287+ "`mod` item is loaded from a file for the second time"
1288+ ) ;
1289+ let ( dir_path, dir_ownership) = mod_dir_path (
1290+ & self . cx . sess ,
1291+ ident,
1292+ & attrs,
1293+ & self . cx . current_expansion . module ,
1294+ self . cx . current_expansion . dir_ownership ,
1295+ ) ;
12881296 item. attrs = attrs;
1289- push_directory ( & self . cx . sess , ident, & item. attrs , dir)
1290- }
1291- ModKind :: Loaded ( _, Inline :: No , _) => {
1292- panic ! ( "`mod` item is loaded from a file for the second time" )
1297+ ( None , dir_path, dir_ownership)
12931298 }
12941299 ModKind :: Unloaded => {
12951300 // We have an outline `mod foo;` so we need to parse the file.
1296- let ( items, inner_span, dir) =
1297- parse_external_mod ( & self . cx . sess , ident, span, dir, & mut attrs, pushed) ;
1301+ let old_attrs_len = attrs. len ( ) ;
1302+ let ParsedExternalMod {
1303+ mut items,
1304+ inner_span,
1305+ file_path,
1306+ dir_path,
1307+ dir_ownership,
1308+ } = parse_external_mod (
1309+ & self . cx . sess ,
1310+ ident,
1311+ span,
1312+ & self . cx . current_expansion . module ,
1313+ self . cx . current_expansion . dir_ownership ,
1314+ & mut attrs,
1315+ ) ;
12981316
1299- let krate =
1300- ast:: Crate { attrs, items, span : inner_span, proc_macros : vec ! [ ] } ;
13011317 if let Some ( extern_mod_loaded) = self . cx . extern_mod_loaded {
1302- extern_mod_loaded ( & krate , ident) ;
1318+ ( attrs , items ) = extern_mod_loaded ( ident, attrs , items , inner_span ) ;
13031319 }
13041320
1305- * mod_kind = ModKind :: Loaded ( krate. items , Inline :: No , inner_span) ;
1306- item. attrs = krate. attrs ;
1307- // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1308- item = match self . configure ( item) {
1309- Some ( node) => node,
1310- None => {
1311- if * pushed {
1312- sess. included_mod_stack . borrow_mut ( ) . pop ( ) ;
1313- }
1314- return Default :: default ( ) ;
1315- }
1316- } ;
1317- dir
1321+ * mod_kind = ModKind :: Loaded ( items, Inline :: No , inner_span) ;
1322+ item. attrs = attrs;
1323+ if item. attrs . len ( ) > old_attrs_len {
1324+ // If we loaded an out-of-line module and added some inner attributes,
1325+ // then we need to re-configure it.
1326+ // FIXME: Attributes also need to be recollected
1327+ // for resolution and expansion.
1328+ item = configure ! ( self , item) ;
1329+ }
1330+ ( Some ( file_path) , dir_path, dir_ownership)
13181331 }
13191332 } ;
13201333
13211334 // Set the module info before we flat map.
1322- self . cx . current_expansion . directory_ownership = ownership;
1323- module. directory = path;
1335+ let mut module = self . cx . current_expansion . module . with_dir_path ( dir_path) ;
13241336 module. mod_path . push ( ident) ;
1337+ if let Some ( file_path) = file_path {
1338+ module. file_path_stack . push ( file_path) ;
1339+ }
1340+
13251341 let orig_module =
13261342 mem:: replace ( & mut self . cx . current_expansion . module , Rc :: new ( module) ) ;
1343+ let orig_dir_ownership =
1344+ mem:: replace ( & mut self . cx . current_expansion . dir_ownership , dir_ownership) ;
13271345
13281346 let result = noop_flat_map_item ( item, self ) ;
13291347
13301348 // Restore the module info.
1349+ self . cx . current_expansion . dir_ownership = orig_dir_ownership;
13311350 self . cx . current_expansion . module = orig_module;
1332- self . cx . current_expansion . directory_ownership = orig_ownership;
1333- if * pushed {
1334- sess. included_mod_stack . borrow_mut ( ) . pop ( ) ;
1335- }
1351+
13361352 result
13371353 }
13381354 _ => {
0 commit comments