@@ -42,7 +42,7 @@ use rustc_ast::{self as ast, *};
4242use rustc_ast_pretty:: pprust;
4343use rustc_data_structures:: captures:: Captures ;
4444use rustc_data_structures:: fingerprint:: Fingerprint ;
45- use rustc_data_structures:: fx:: FxHashSet ;
45+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4646use rustc_data_structures:: sorted_map:: SortedMap ;
4747use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
4848use rustc_data_structures:: sync:: Lrc ;
@@ -65,6 +65,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
6565use rustc_span:: { Span , DUMMY_SP } ;
6666
6767use smallvec:: SmallVec ;
68+ use std:: collections:: hash_map:: Entry ;
6869use tracing:: { debug, trace} ;
6970
7071macro_rules! arena_vec {
@@ -152,10 +153,9 @@ struct LoweringContext<'a, 'hir: 'a> {
152153
153154 current_hir_id_owner : LocalDefId ,
154155 item_local_id_counter : hir:: ItemLocalId ,
155- node_id_to_hir_id : IndexVec < NodeId , Option < hir:: HirId > > ,
156156
157157 /// NodeIds that are lowered inside the current HIR owner.
158- local_node_ids : Vec < NodeId > ,
158+ node_id_to_local_id : FxHashMap < NodeId , hir :: ItemLocalId > ,
159159
160160 allow_try_trait : Option < Lrc < [ Symbol ] > > ,
161161 allow_gen_future : Option < Lrc < [ Symbol ] > > ,
@@ -309,8 +309,7 @@ pub fn lower_crate<'a, 'hir>(
309309 anonymous_lifetime_mode : AnonymousLifetimeMode :: PassThrough ,
310310 current_hir_id_owner : CRATE_DEF_ID ,
311311 item_local_id_counter : hir:: ItemLocalId :: new ( 0 ) ,
312- node_id_to_hir_id : IndexVec :: new ( ) ,
313- local_node_ids : Vec :: new ( ) ,
312+ node_id_to_local_id : FxHashMap :: default ( ) ,
314313 generator_kind : None ,
315314 task_context : None ,
316315 current_item : None ,
@@ -437,23 +436,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
437436
438437 let current_attrs = std:: mem:: take ( & mut self . attrs ) ;
439438 let current_bodies = std:: mem:: take ( & mut self . bodies ) ;
440- let current_node_ids = std:: mem:: take ( & mut self . local_node_ids ) ;
439+ let current_node_ids = std:: mem:: take ( & mut self . node_id_to_local_id ) ;
441440 let current_owner = std:: mem:: replace ( & mut self . current_hir_id_owner , def_id) ;
442441 let current_local_counter =
443442 std:: mem:: replace ( & mut self . item_local_id_counter , hir:: ItemLocalId :: new ( 1 ) ) ;
444443
445444 // Always allocate the first `HirId` for the owner itself.
446- let _old = self . node_id_to_hir_id . insert ( owner, hir:: HirId :: make_owner ( def_id ) ) ;
445+ let _old = self . node_id_to_local_id . insert ( owner, hir:: ItemLocalId :: new ( 0 ) ) ;
447446 debug_assert_eq ! ( _old, None ) ;
448- self . local_node_ids . push ( owner) ;
449447
450448 let item = f ( self ) ;
451449 debug_assert_eq ! ( def_id, item. def_id( ) ) ;
452450 let info = self . make_owner_info ( item) ;
453451
454452 self . attrs = current_attrs;
455453 self . bodies = current_bodies;
456- self . local_node_ids = current_node_ids;
454+ self . node_id_to_local_id = current_node_ids;
457455 self . current_hir_id_owner = current_owner;
458456 self . item_local_id_counter = current_local_counter;
459457
@@ -466,34 +464,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
466464 fn make_owner_info ( & mut self , node : hir:: OwnerNode < ' hir > ) -> hir:: OwnerInfo < ' hir > {
467465 let attrs = std:: mem:: take ( & mut self . attrs ) ;
468466 let mut bodies = std:: mem:: take ( & mut self . bodies ) ;
469- let local_node_ids = std:: mem:: take ( & mut self . local_node_ids ) ;
467+ let node_id_to_local_id = std:: mem:: take ( & mut self . node_id_to_local_id ) ;
470468
471- let local_id_to_def_id = local_node_ids
469+ let local_id_to_def_id = node_id_to_local_id
472470 . iter ( )
473- . filter_map ( |& node_id| {
471+ . filter_map ( |( & node_id, & local_id ) | {
474472 let def_id = self . resolver . opt_local_def_id ( node_id) ?;
475- let hir_id = self . node_id_to_hir_id [ node_id] ?;
476473
477474 self . owners . ensure_contains_elem ( def_id, || hir:: MaybeOwner :: Phantom ) ;
478475 if let o @ hir:: MaybeOwner :: Phantom = & mut self . owners [ def_id] {
479476 // Do not override a `MaybeOwner::Owner` that may already here.
477+ let hir_id = hir:: HirId { owner : self . current_hir_id_owner , local_id } ;
480478 * o = hir:: MaybeOwner :: NonOwner ( hir_id) ;
481479 }
482480
483- if hir_id. local_id == hir:: ItemLocalId :: new ( 0 ) {
484- None
485- } else {
486- Some ( ( hir_id. local_id , def_id) )
487- }
481+ if local_id == hir:: ItemLocalId :: new ( 0 ) { None } else { Some ( ( local_id, def_id) ) }
488482 } )
489483 . collect ( ) ;
490484
491- let trait_map = local_node_ids
485+ let trait_map = node_id_to_local_id
492486 . into_iter ( )
493- . filter_map ( |node_id| {
494- let hir_id = self . node_id_to_hir_id [ node_id] ?;
487+ . filter_map ( |( node_id, local_id) | {
495488 let traits = self . resolver . take_trait_map ( node_id) ?;
496- Some ( ( hir_id . local_id , traits. into_boxed_slice ( ) ) )
489+ Some ( ( local_id, traits. into_boxed_slice ( ) ) )
497490 } )
498491 . collect ( ) ;
499492
@@ -558,14 +551,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
558551 fn lower_node_id ( & mut self , ast_node_id : NodeId ) -> hir:: HirId {
559552 assert_ne ! ( ast_node_id, DUMMY_NODE_ID ) ;
560553
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- } )
554+ let owner = self . current_hir_id_owner ;
555+ let local_id = match self . node_id_to_local_id . entry ( ast_node_id) {
556+ Entry :: Occupied ( o) => * o. get ( ) ,
557+ Entry :: Vacant ( v) => {
558+ // Generate a new `HirId`.
559+ let local_id = self . item_local_id_counter ;
560+ self . item_local_id_counter . increment_by ( 1 ) ;
561+ v. insert ( local_id) ;
562+ local_id
563+ }
564+ } ;
565+ hir:: HirId { owner, local_id }
569566 }
570567
571568 fn next_id ( & mut self ) -> hir:: HirId {
@@ -574,11 +571,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
574571 }
575572
576573 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- } )
574+ let res: Result < Res , ( ) > = res. apply_id ( |id| {
575+ let owner = self . current_hir_id_owner ;
576+ let local_id = self . node_id_to_local_id . get ( & id) . copied ( ) . ok_or ( ( ) ) ?;
577+ Ok ( hir:: HirId { owner, local_id } )
578+ } ) ;
579+ // We may fail to find a HirId when the Res points to a Local from an enclosing HIR owner.
580+ // This can happen when trying to lower the return type `x` in erroneous code like
581+ // async fn foo(x: u8) -> x {}
582+ // In that case, `x` is lowered as a function parameter, and the return type is lowered as
583+ // an opaque type as a synthetized HIR owner.
584+ res. unwrap_or ( Res :: Err )
582585 }
583586
584587 fn expect_full_res ( & mut self , id : NodeId ) -> Res < NodeId > {
0 commit comments