1
1
use crate :: base:: * ;
2
2
use crate :: config:: StripUnconfigured ;
3
+ use crate :: configure;
3
4
use crate :: hygiene:: { ExpnData , ExpnId , ExpnKind , SyntaxContext } ;
4
5
use crate :: mbe:: macro_rules:: annotate_err_with_kind;
6
+ use crate :: module:: { parse_external_mod, push_directory, Directory , DirectoryOwnership } ;
5
7
use crate :: placeholders:: { placeholder, PlaceholderExpander } ;
6
8
use crate :: proc_macro:: collect_derives;
7
9
@@ -17,10 +19,8 @@ use rustc_ast_pretty::pprust;
17
19
use rustc_attr:: { self as attr, is_builtin_attr, HasAttrs } ;
18
20
use rustc_errors:: { Applicability , FatalError , PResult } ;
19
21
use rustc_feature:: Features ;
20
- use rustc_parse:: configure;
21
22
use rustc_parse:: parser:: Parser ;
22
23
use rustc_parse:: validate_attr;
23
- use rustc_parse:: DirectoryOwnership ;
24
24
use rustc_session:: lint:: builtin:: UNUSED_DOC_COMMENTS ;
25
25
use rustc_session:: lint:: BuiltinLintDiagnostics ;
26
26
use rustc_session:: parse:: { feature_err, ParseSess } ;
@@ -1427,59 +1427,83 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1427
1427
. make_items ( ) ;
1428
1428
}
1429
1429
1430
+ let mut attrs = mem:: take ( & mut item. attrs ) ; // We do this to please borrowck.
1431
+ let ident = item. ident ;
1432
+ let span = item. span ;
1433
+
1430
1434
match item. kind {
1431
1435
ast:: ItemKind :: MacCall ( ..) => {
1436
+ item. attrs = attrs;
1432
1437
self . check_attributes ( & item. attrs ) ;
1433
1438
item. and_then ( |item| match item. kind {
1434
1439
ItemKind :: MacCall ( mac) => self
1435
- . collect (
1436
- AstFragmentKind :: Items ,
1437
- InvocationKind :: Bang { mac, span : item. span } ,
1438
- )
1440
+ . collect ( AstFragmentKind :: Items , InvocationKind :: Bang { mac, span } )
1439
1441
. make_items ( ) ,
1440
1442
_ => unreachable ! ( ) ,
1441
1443
} )
1442
1444
}
1443
- ast:: ItemKind :: Mod ( ast:: Mod { inner, inline, .. } )
1444
- if item. ident != Ident :: invalid ( ) =>
1445
- {
1446
- let orig_directory_ownership = self . cx . current_expansion . directory_ownership ;
1445
+ ast:: ItemKind :: Mod ( ref mut old_mod @ ast:: Mod { .. } ) if ident != Ident :: invalid ( ) => {
1446
+ let sess = self . cx . parse_sess ;
1447
+ let orig_ownership = self . cx . current_expansion . directory_ownership ;
1447
1448
let mut module = ( * self . cx . current_expansion . module ) . clone ( ) ;
1448
- module. mod_path . push ( item. ident ) ;
1449
1449
1450
- if inline {
1451
- if let Some ( path) = attr:: first_attr_value_str_by_name ( & item. attrs , sym:: path) {
1452
- self . cx . current_expansion . directory_ownership =
1453
- DirectoryOwnership :: Owned { relative : None } ;
1454
- module. directory . push ( & * path. as_str ( ) ) ;
1455
- } else {
1456
- module. directory . push ( & * item. ident . as_str ( ) ) ;
1457
- }
1450
+ let pushed = & mut false ; // Record `parse_external_mod` pushing so we can pop.
1451
+ let dir = Directory { ownership : orig_ownership, path : module. directory } ;
1452
+ let Directory { ownership, path } = if old_mod. inline {
1453
+ // Inline `mod foo { ... }`, but we still need to push directories.
1454
+ item. attrs = attrs;
1455
+ push_directory ( ident, & item. attrs , dir)
1458
1456
} else {
1459
- let path = self . cx . parse_sess . source_map ( ) . span_to_unmapped_path ( inner) ;
1460
- let mut path = match path {
1461
- FileName :: Real ( path) => path,
1462
- other => PathBuf :: from ( other. to_string ( ) ) ,
1457
+ // We have an outline `mod foo;` so we need to parse the file.
1458
+ let ( new_mod, dir) =
1459
+ parse_external_mod ( sess, ident, span, dir, & mut attrs, pushed) ;
1460
+
1461
+ let krate = ast:: Crate {
1462
+ span : new_mod. inner ,
1463
+ module : new_mod,
1464
+ attrs,
1465
+ proc_macros : vec ! [ ] ,
1463
1466
} ;
1464
- let directory_ownership = match path. file_name ( ) . unwrap ( ) . to_str ( ) {
1465
- Some ( "mod.rs" ) => DirectoryOwnership :: Owned { relative : None } ,
1466
- Some ( _) => DirectoryOwnership :: Owned { relative : Some ( item. ident ) } ,
1467
- None => DirectoryOwnership :: UnownedViaMod ,
1467
+ if let Some ( extern_mod_loaded) = self . cx . extern_mod_loaded {
1468
+ extern_mod_loaded ( & krate) ;
1469
+ }
1470
+
1471
+ * old_mod = krate. module ;
1472
+ item. attrs = krate. attrs ;
1473
+ // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
1474
+ item = match self . configure ( item) {
1475
+ Some ( node) => node,
1476
+ None => {
1477
+ if * pushed {
1478
+ sess. included_mod_stack . borrow_mut ( ) . pop ( ) ;
1479
+ }
1480
+ return Default :: default ( ) ;
1481
+ }
1468
1482
} ;
1469
- path. pop ( ) ;
1470
- module. directory = path;
1471
- self . cx . current_expansion . directory_ownership = directory_ownership;
1472
- }
1483
+ dir
1484
+ } ;
1473
1485
1486
+ // Set the module info before we flat map.
1487
+ self . cx . current_expansion . directory_ownership = ownership;
1488
+ module. directory = path;
1489
+ module. mod_path . push ( ident) ;
1474
1490
let orig_module =
1475
1491
mem:: replace ( & mut self . cx . current_expansion . module , Rc :: new ( module) ) ;
1492
+
1476
1493
let result = noop_flat_map_item ( item, self ) ;
1494
+
1495
+ // Restore the module info.
1477
1496
self . cx . current_expansion . module = orig_module;
1478
- self . cx . current_expansion . directory_ownership = orig_directory_ownership;
1497
+ self . cx . current_expansion . directory_ownership = orig_ownership;
1498
+ if * pushed {
1499
+ sess. included_mod_stack . borrow_mut ( ) . pop ( ) ;
1500
+ }
1479
1501
result
1480
1502
}
1481
-
1482
- _ => noop_flat_map_item ( item, self ) ,
1503
+ _ => {
1504
+ item. attrs = attrs;
1505
+ noop_flat_map_item ( item, self )
1506
+ }
1483
1507
}
1484
1508
}
1485
1509
0 commit comments