@@ -44,7 +44,7 @@ use rustc_ast::{self as ast, *};
44
44
use rustc_ast_pretty:: pprust;
45
45
use rustc_data_structures:: captures:: Captures ;
46
46
use rustc_data_structures:: fingerprint:: Fingerprint ;
47
- use rustc_data_structures:: fx:: FxHashSet ;
47
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
48
48
use rustc_data_structures:: sorted_map:: SortedMap ;
49
49
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
50
50
use rustc_data_structures:: sync:: Lrc ;
@@ -67,6 +67,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
67
67
use rustc_span:: { Span , DUMMY_SP } ;
68
68
69
69
use smallvec:: SmallVec ;
70
+ use std:: collections:: hash_map:: Entry ;
70
71
use tracing:: { debug, trace} ;
71
72
72
73
macro_rules! arena_vec {
@@ -154,10 +155,9 @@ struct LoweringContext<'a, 'hir: 'a> {
154
155
155
156
current_hir_id_owner : LocalDefId ,
156
157
item_local_id_counter : hir:: ItemLocalId ,
157
- node_id_to_hir_id : IndexVec < NodeId , Option < hir:: HirId > > ,
158
158
159
159
/// NodeIds that are lowered inside the current HIR owner.
160
- local_node_ids : Vec < NodeId > ,
160
+ node_id_to_local_id : FxHashMap < NodeId , hir :: ItemLocalId > ,
161
161
162
162
allow_try_trait : Option < Lrc < [ Symbol ] > > ,
163
163
allow_gen_future : Option < Lrc < [ Symbol ] > > ,
@@ -311,8 +311,7 @@ pub fn lower_crate<'a, 'hir>(
311
311
anonymous_lifetime_mode : AnonymousLifetimeMode :: PassThrough ,
312
312
current_hir_id_owner : CRATE_DEF_ID ,
313
313
item_local_id_counter : hir:: ItemLocalId :: new ( 0 ) ,
314
- node_id_to_hir_id : IndexVec :: new ( ) ,
315
- local_node_ids : Vec :: new ( ) ,
314
+ node_id_to_local_id : FxHashMap :: default ( ) ,
316
315
generator_kind : None ,
317
316
task_context : None ,
318
317
current_item : None ,
@@ -439,23 +438,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
439
438
440
439
let current_attrs = std:: mem:: take ( & mut self . attrs ) ;
441
440
let current_bodies = std:: mem:: take ( & mut self . bodies ) ;
442
- let current_node_ids = std:: mem:: take ( & mut self . local_node_ids ) ;
441
+ let current_node_ids = std:: mem:: take ( & mut self . node_id_to_local_id ) ;
443
442
let current_owner = std:: mem:: replace ( & mut self . current_hir_id_owner , def_id) ;
444
443
let current_local_counter =
445
444
std:: mem:: replace ( & mut self . item_local_id_counter , hir:: ItemLocalId :: new ( 1 ) ) ;
446
445
447
446
// Always allocate the first `HirId` for the owner itself.
448
- let _old = self . node_id_to_hir_id . insert ( owner, hir:: HirId :: make_owner ( def_id ) ) ;
447
+ let _old = self . node_id_to_local_id . insert ( owner, hir:: ItemLocalId :: new ( 0 ) ) ;
449
448
debug_assert_eq ! ( _old, None ) ;
450
- self . local_node_ids . push ( owner) ;
451
449
452
450
let item = f ( self ) ;
453
451
debug_assert_eq ! ( def_id, item. def_id( ) ) ;
454
452
let info = self . make_owner_info ( item) ;
455
453
456
454
self . attrs = current_attrs;
457
455
self . bodies = current_bodies;
458
- self . local_node_ids = current_node_ids;
456
+ self . node_id_to_local_id = current_node_ids;
459
457
self . current_hir_id_owner = current_owner;
460
458
self . item_local_id_counter = current_local_counter;
461
459
@@ -468,32 +466,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
468
466
fn make_owner_info ( & mut self , node : hir:: OwnerNode < ' hir > ) -> hir:: OwnerInfo < ' hir > {
469
467
let attrs = std:: mem:: take ( & mut self . attrs ) ;
470
468
let mut bodies = std:: mem:: take ( & mut self . bodies ) ;
471
- let local_node_ids = std:: mem:: take ( & mut self . local_node_ids ) ;
469
+ let node_id_to_local_id = std:: mem:: take ( & mut self . node_id_to_local_id ) ;
472
470
473
- let local_id_to_def_id = local_node_ids
471
+ let local_id_to_def_id = node_id_to_local_id
474
472
. iter ( )
475
- . filter_map ( |& node_id| {
476
- let hir_id = self . node_id_to_hir_id [ node_id] ?;
477
- if hir_id. local_id == hir:: ItemLocalId :: new ( 0 ) {
473
+ . filter_map ( |( & node_id, & local_id) | {
474
+ if local_id == hir:: ItemLocalId :: new ( 0 ) {
478
475
None
479
476
} else {
480
477
let def_id = self . resolver . opt_local_def_id ( node_id) ?;
478
+
481
479
self . owners . ensure_contains_elem ( def_id, || hir:: MaybeOwner :: Phantom ) ;
482
480
if let o @ hir:: MaybeOwner :: Phantom = & mut self . owners [ def_id] {
483
481
// Do not override a `MaybeOwner::Owner` that may already here.
482
+ let hir_id = hir:: HirId { owner : self . current_hir_id_owner , local_id } ;
484
483
* o = hir:: MaybeOwner :: NonOwner ( hir_id) ;
485
484
}
486
- Some ( ( hir_id . local_id , def_id) )
485
+ Some ( ( local_id, def_id) )
487
486
}
488
487
} )
489
488
. collect ( ) ;
490
489
491
- let trait_map = local_node_ids
490
+ let trait_map = node_id_to_local_id
492
491
. into_iter ( )
493
- . filter_map ( |node_id| {
494
- let hir_id = self . node_id_to_hir_id [ node_id] ?;
492
+ . filter_map ( |( node_id, local_id) | {
495
493
let traits = self . resolver . take_trait_map ( node_id) ?;
496
- Some ( ( hir_id . local_id , traits. into_boxed_slice ( ) ) )
494
+ Some ( ( local_id, traits. into_boxed_slice ( ) ) )
497
495
} )
498
496
. collect ( ) ;
499
497
@@ -558,14 +556,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
558
556
fn lower_node_id ( & mut self , ast_node_id : NodeId ) -> hir:: HirId {
559
557
assert_ne ! ( ast_node_id, DUMMY_NODE_ID ) ;
560
558
561
- * self . node_id_to_hir_id . get_or_insert_with ( ast_node_id, || {
562
- // Generate a new `HirId`.
563
- let owner = self . current_hir_id_owner ;
564
- let local_id = self . item_local_id_counter ;
565
- self . item_local_id_counter . increment_by ( 1 ) ;
566
- self . local_node_ids . push ( ast_node_id) ;
567
- hir:: HirId { owner, local_id }
568
- } )
559
+ let owner = self . current_hir_id_owner ;
560
+ let local_id = match self . node_id_to_local_id . entry ( ast_node_id) {
561
+ Entry :: Occupied ( o) => * o. get ( ) ,
562
+ Entry :: Vacant ( v) => {
563
+ // Generate a new `HirId`.
564
+ let local_id = self . item_local_id_counter ;
565
+ self . item_local_id_counter . increment_by ( 1 ) ;
566
+ v. insert ( local_id) ;
567
+ local_id
568
+ }
569
+ } ;
570
+ hir:: HirId { owner, local_id }
569
571
}
570
572
571
573
fn next_id ( & mut self ) -> hir:: HirId {
@@ -574,11 +576,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
574
576
}
575
577
576
578
fn lower_res ( & mut self , res : Res < NodeId > ) -> Res {
577
- res. map_id ( |id| {
578
- self . node_id_to_hir_id . get ( id) . copied ( ) . flatten ( ) . unwrap_or_else ( || {
579
- panic ! ( "expected `NodeId` to be lowered already for res {:#?}" , res) ;
580
- } )
581
- } )
579
+ let res: Result < Res , ( ) > = res. apply_id ( |id| {
580
+ let owner = self . current_hir_id_owner ;
581
+ let local_id = self . node_id_to_local_id . get ( & id) . copied ( ) . ok_or ( ( ) ) ?;
582
+ Ok ( hir:: HirId { owner, local_id } )
583
+ } ) ;
584
+ // We may fail to find a HirId when the Res points to a Local from an enclosing HIR owner.
585
+ // This can happen when trying to lower the return type `x` in erroneous code like
586
+ // async fn foo(x: u8) -> x {}
587
+ // In that case, `x` is lowered as a function parameter, and the return type is lowered as
588
+ // an opaque type as a synthetized HIR owner.
589
+ res. unwrap_or ( Res :: Err )
582
590
}
583
591
584
592
fn expect_full_res ( & mut self , id : NodeId ) -> Res < NodeId > {
0 commit comments