@@ -467,7 +467,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
467467 // Without `edition_redirect`, the first import consumes the redirect
468468 // using that import's edition. The resulting binding is fixed for
469469 // downstream users.
470- decl = self . edition_adjusted_decl ( decl, import. span . edition ( ) ) ;
470+ decl = self . edition_adjusted_decl ( decl, import. span ) ;
471471
472472 let vis = self . import_decl_vis ( decl, import. summary ( ) ) ;
473473
@@ -483,28 +483,33 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
483483 // each target in this import so a downstream edition adjustment retains
484484 // its visibility and re-export provenance. Other crates consume the
485485 // redirects above and produce re-exports with no redirects.
486- let edition_redirects = if self . features . edition_redirect ( ) {
487- decl. edition_redirects
488- . iter ( )
489- . map ( |redirect| crate :: EditionRedirectDecl {
490- before : redirect. before ,
491- target : self . arenas . alloc_decl ( DeclData {
492- kind : DeclKind :: Import { source_decl : redirect. target , import } ,
493- ambiguity : CmCell :: new ( None ) ,
494- span : import. span ,
495- initial_vis : vis. to_mod_id ( ) ,
496- ambiguity_vis_max : CmCell :: new ( None ) ,
497- ambiguity_vis_min : CmCell :: new ( None ) ,
498- expansion : import. parent_scope . expansion ,
499- parent_module : Some ( import. parent_scope . module ) ,
500- edition_redirects : & [ ] ,
501- } ) ,
502- } )
503- . collect :: < SmallVec < [ _ ; 1 ] > > ( )
486+ let edition_redirects = if decl. edition_redirects . is_empty ( ) {
487+ // Fast path when there are no edition redirects.
488+ & [ ]
504489 } else {
505- SmallVec :: new ( )
490+ let edition_redirects = if self . features . edition_redirect ( ) {
491+ decl. edition_redirects
492+ . iter ( )
493+ . map ( |redirect| crate :: EditionRedirectDecl {
494+ before : redirect. before ,
495+ target : self . arenas . alloc_decl ( DeclData {
496+ kind : DeclKind :: Import { source_decl : redirect. target , import } ,
497+ ambiguity : CmCell :: new ( None ) ,
498+ span : import. span ,
499+ initial_vis : vis. to_mod_id ( ) ,
500+ ambiguity_vis_max : CmCell :: new ( None ) ,
501+ ambiguity_vis_min : CmCell :: new ( None ) ,
502+ expansion : import. parent_scope . expansion ,
503+ parent_module : Some ( import. parent_scope . module ) ,
504+ edition_redirects : & [ ] ,
505+ } ) ,
506+ } )
507+ . collect :: < SmallVec < [ _ ; 1 ] > > ( )
508+ } else {
509+ SmallVec :: new ( )
510+ } ;
511+ self . arenas . alloc_edition_redirects ( & edition_redirects)
506512 } ;
507- let edition_redirects = self . arenas . alloc_edition_redirects ( & edition_redirects) ;
508513
509514 self . arenas . alloc_decl ( DeclData {
510515 kind : DeclKind :: Import { source_decl : decl, import } ,
@@ -625,7 +630,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
625630 }
626631 glob_decl
627632 } else if glob_decl. res ( ) != old_glob_decl. res ( )
628- || !Self :: same_edition_redirects ( old_glob_decl, glob_decl)
633+ || ( !( old_glob_decl. edition_redirects . is_empty ( )
634+ && glob_decl. edition_redirects . is_empty ( ) )
635+ && !Self :: same_edition_redirects ( old_glob_decl, glob_decl) )
629636 {
630637 // Redirects are part of a binding's behavior. If two globs resolve
631638 // to the same item but redirect differently, retaining either
@@ -668,6 +675,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
668675 /// considered: they affect only the metadata produced for downstream
669676 /// crates, not local name resolution.
670677 fn same_edition_redirects ( decl1 : Decl < ' ra > , decl2 : Decl < ' ra > ) -> bool {
678+ // Fast path when there are no edition redirects.
679+ if decl1. edition_redirects . is_empty ( ) && decl2. edition_redirects . is_empty ( ) {
680+ return true ;
681+ }
682+
671683 decl1. edition_redirects . len ( ) == decl2. edition_redirects . len ( )
672684 && decl1. edition_redirects . iter ( ) . zip ( decl2. edition_redirects ) . all (
673685 |( redirect1, redirect2) | {
@@ -1860,8 +1872,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
18601872 . iter ( )
18611873 . filter_map ( |( key, resolution) | {
18621874 let res = resolution. borrow ( ) ;
1863- let decl =
1864- self . edition_adjusted_decl ( res. determined_decl ( ) ?, import. span . edition ( ) ) ;
1875+ let decl = self . edition_adjusted_decl ( res. determined_decl ( ) ?, import. span ) ;
18651876 let mut key = * key;
18661877 let scope = match key. ident . ctxt . update_unchecked ( |ctxt| {
18671878 ctxt. reverse_glob_adjust ( module. expansion , import. span )
@@ -1960,30 +1971,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19601971 }
19611972 }
19621973
1963- /// Produces the sorted, metadata-ready edition redirects for `decl` in
1964- /// `ns`.
1965- ///
1966- /// Targets declared in the current crate are resolved here, after ordinary
1967- /// imports have settled and once the namespace exported by the declaration
1968- /// is known. Redirects on external declarations are already resolved in
1969- /// crate metadata and are copied through unchanged.
1970- fn resolved_edition_redirects (
1974+ /// Resolves local redirect targets after ordinary imports have settled and
1975+ /// once the namespace exported by `decl` is known.
1976+ fn resolve_local_edition_redirects (
19711977 & mut self ,
19721978 ns : Namespace ,
19731979 decl : Decl < ' ra > ,
1980+ redirects : Vec < crate :: LocalEditionRedirect < ' ra > > ,
19741981 ) -> SmallVec < [ MetadataEditionRedirect ; 1 ] > {
1975- let Some ( redirects) = self . local_edition_redirects ( decl) else {
1976- // External declarations already carry resolved redirect targets
1977- // from crate metadata.
1978- return decl
1979- . edition_redirects
1980- . iter ( )
1981- . map ( |redirect| MetadataEditionRedirect {
1982- before : redirect. before ,
1983- target : redirect. target . res ( ) . expect_non_local ( ) ,
1984- } )
1985- . collect ( ) ;
1986- } ;
19871982 redirects
19881983 . into_iter ( )
19891984 . filter_map ( |redirect| {
@@ -2080,9 +2075,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20802075
20812076 let Some ( def_id) = module. opt_def_id ( ) else { return } ;
20822077
2078+ enum EditionRedirectSlot {
2079+ Child ( usize ) ,
2080+ AmbiguousMain ( usize ) ,
2081+ AmbiguousSecond ( usize ) ,
2082+ }
2083+
20832084 let mut children = Vec :: new ( ) ;
20842085 let mut ambig_children = Vec :: new ( ) ;
2085- module. to_module ( ) . for_each_child_mut ( self , |this, ident, orig_ident_span, ns, decl| {
2086+ let mut pending_edition_redirects = Vec :: new ( ) ;
2087+ module. to_module ( ) . for_each_child ( self , |this, ident, orig_ident_span, ns, decl| {
20862088 let res = decl. res ( ) . expect_non_local ( ) ;
20872089 if res != def:: Res :: Err {
20882090 let vis = if this. rust_embed_hack ( module, decl) {
@@ -2091,34 +2093,84 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20912093 decl. vis ( )
20922094 } ;
20932095 let ident = ident. orig ( orig_ident_span) ;
2096+ let mut edition_redirects = |decl, child| {
2097+ // Local redirect targets must be resolved after
2098+ // `for_each_child` releases its borrow. Otherwise copy any
2099+ // already-resolved redirects decoded from external crate
2100+ // metadata.
2101+ if !this. local_edition_redirects . is_empty ( )
2102+ && let Some ( redirects) = this. local_edition_redirects ( decl)
2103+ {
2104+ pending_edition_redirects. push ( ( child, ns, decl, redirects) ) ;
2105+ SmallVec :: new ( )
2106+ } else if decl. edition_redirects . is_empty ( ) {
2107+ SmallVec :: new ( )
2108+ } else {
2109+ decl. edition_redirects
2110+ . iter ( )
2111+ . map ( |redirect| MetadataEditionRedirect {
2112+ before : redirect. before ,
2113+ target : redirect. target . res ( ) . expect_non_local ( ) ,
2114+ } )
2115+ . collect ( )
2116+ }
2117+ } ;
20942118 if let Some ( ( ambig_binding1, ambig_binding2) ) = decl. descent_to_ambiguity ( ) {
2119+ let index = ambig_children. len ( ) ;
20952120 let main = ModChild {
20962121 ident,
20972122 res,
20982123 vis,
20992124 reexport_chain : ambig_binding1. reexport_chain ( ) ,
2100- edition_redirects : this. resolved_edition_redirects ( ns, ambig_binding1) ,
2125+ edition_redirects : edition_redirects (
2126+ ambig_binding1,
2127+ EditionRedirectSlot :: AmbiguousMain ( index) ,
2128+ ) ,
21012129 } ;
21022130 let second = ModChild {
21032131 ident,
21042132 res : ambig_binding2. res ( ) . expect_non_local ( ) ,
21052133 vis : ambig_binding2. vis ( ) ,
21062134 reexport_chain : ambig_binding2. reexport_chain ( ) ,
2107- edition_redirects : this. resolved_edition_redirects ( ns, ambig_binding2) ,
2135+ edition_redirects : edition_redirects (
2136+ ambig_binding2,
2137+ EditionRedirectSlot :: AmbiguousSecond ( index) ,
2138+ ) ,
21082139 } ;
21092140 ambig_children. push ( AmbigModChild { main, second } )
21102141 } else {
2142+ let index = children. len ( ) ;
21112143 children. push ( ModChild {
21122144 ident,
21132145 res,
21142146 vis,
21152147 reexport_chain : decl. reexport_chain ( ) ,
2116- edition_redirects : this. resolved_edition_redirects ( ns, decl) ,
2148+ edition_redirects : edition_redirects (
2149+ decl,
2150+ EditionRedirectSlot :: Child ( index) ,
2151+ ) ,
21172152 } ) ;
21182153 }
21192154 }
21202155 } ) ;
21212156
2157+ // Resolving a target can record import uses and diagnostics, so wait
2158+ // until `for_each_child` releases its borrow of the module resolutions.
2159+ for ( child, ns, decl, redirects) in pending_edition_redirects {
2160+ let redirects = self . resolve_local_edition_redirects ( ns, decl, redirects) ;
2161+ match child {
2162+ EditionRedirectSlot :: Child ( index) => {
2163+ children[ index] . edition_redirects = redirects;
2164+ }
2165+ EditionRedirectSlot :: AmbiguousMain ( index) => {
2166+ ambig_children[ index] . main . edition_redirects = redirects;
2167+ }
2168+ EditionRedirectSlot :: AmbiguousSecond ( index) => {
2169+ ambig_children[ index] . second . edition_redirects = redirects;
2170+ }
2171+ }
2172+ }
2173+
21222174 if !children. is_empty ( ) {
21232175 module_children. insert ( def_id. expect_local ( ) , children) ;
21242176 }
0 commit comments