@@ -944,6 +944,46 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
944944 // "self-confirming" import resolutions during import validation and checking.
945945 ignore_binding : Option < NameBinding < ' ra > > ,
946946 ignore_import : Option < Import < ' ra > > ,
947+ ) -> Result < NameBinding < ' ra > , ControlFlow < Determinacy , Determinacy > > {
948+ let res = self . reborrow ( ) . resolve_ident_in_module_non_globs_unadjusted (
949+ module,
950+ ident,
951+ ns,
952+ parent_scope,
953+ shadowing,
954+ finalize,
955+ ignore_binding,
956+ ignore_import,
957+ ) ;
958+
959+ match res {
960+ Ok ( _) | Err ( ControlFlow :: Break ( _) ) => return res,
961+ Err ( ControlFlow :: Continue ( _) ) => { }
962+ }
963+
964+ self . resolve_ident_in_module_globs_unadjusted (
965+ module,
966+ ident,
967+ ns,
968+ parent_scope,
969+ shadowing,
970+ finalize,
971+ ignore_binding,
972+ ignore_import,
973+ )
974+ }
975+
976+ /// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in `module`.
977+ fn resolve_ident_in_module_non_globs_unadjusted < ' r > (
978+ mut self : CmResolver < ' r , ' ra , ' tcx > ,
979+ module : Module < ' ra > ,
980+ ident : Ident ,
981+ ns : Namespace ,
982+ parent_scope : & ParentScope < ' ra > ,
983+ shadowing : Shadowing ,
984+ finalize : Option < Finalize > ,
985+ ignore_binding : Option < NameBinding < ' ra > > ,
986+ ignore_import : Option < Import < ' ra > > ,
947987 ) -> Result < NameBinding < ' ra > , ControlFlow < Determinacy , Determinacy > > {
948988 let key = BindingKey :: new ( ident, ns) ;
949989 // `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding
@@ -954,13 +994,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
954994 . try_borrow_mut_unchecked ( )
955995 . map_err ( |_| ControlFlow :: Continue ( Determined ) ) ?;
956996
957- // If the primary binding is unusable, search further and return the shadowed glob
958- // binding if it exists. What we really want here is having two separate scopes in
959- // a module - one for non-globs and one for globs, but until that's done use this
960- // hack to avoid inconsistent resolution ICEs during import validation.
961- let binding = [ resolution. non_glob_binding , resolution. glob_binding ]
962- . into_iter ( )
963- . find_map ( |binding| if binding == ignore_binding { None } else { binding } ) ;
997+ let binding = resolution. non_glob_binding . filter ( |b| Some ( * b) != ignore_binding) ;
964998
965999 if let Some ( finalize) = finalize {
9661000 return self . get_mut ( ) . finalize_module_binding (
@@ -974,19 +1008,67 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9741008 ) ;
9751009 }
9761010
977- let check_usable = |this : CmResolver < ' r , ' ra , ' tcx > , binding : NameBinding < ' ra > | {
978- let usable = this. is_accessible_from ( binding. vis , parent_scope. module ) ;
979- if usable { Ok ( binding) } else { Err ( ControlFlow :: Break ( Determined ) ) }
980- } ;
981-
9821011 // Items and single imports are not shadowable, if we have one, then it's determined.
983- if let Some ( binding) = binding
984- && !binding. is_glob_import ( )
985- {
986- return check_usable ( self , binding) ;
1012+ if let Some ( binding) = binding {
1013+ let accessible = self . is_accessible_from ( binding. vis , parent_scope. module ) ;
1014+ return if accessible { Ok ( binding) } else { Err ( ControlFlow :: Break ( Determined ) ) } ;
1015+ }
1016+
1017+ // Check if one of single imports can still define the name, block if it can.
1018+ if self . reborrow ( ) . single_import_can_define_name (
1019+ & resolution,
1020+ None ,
1021+ ns,
1022+ ignore_import,
1023+ ignore_binding,
1024+ parent_scope,
1025+ ) {
1026+ return Err ( ControlFlow :: Break ( Undetermined ) ) ;
1027+ }
1028+
1029+ // Check if one of unexpanded macros can still define the name.
1030+ if !module. unexpanded_invocations . borrow ( ) . is_empty ( ) {
1031+ return Err ( ControlFlow :: Continue ( Undetermined ) ) ;
9871032 }
9881033
989- // --- From now on we either have a glob resolution or no resolution. ---
1034+ // No resolution and no one else can define the name - determinate error.
1035+ Err ( ControlFlow :: Continue ( Determined ) )
1036+ }
1037+
1038+ /// Attempts to resolve `ident` in namespace `ns` of glob bindings in `module`.
1039+ fn resolve_ident_in_module_globs_unadjusted < ' r > (
1040+ mut self : CmResolver < ' r , ' ra , ' tcx > ,
1041+ module : Module < ' ra > ,
1042+ ident : Ident ,
1043+ ns : Namespace ,
1044+ parent_scope : & ParentScope < ' ra > ,
1045+ shadowing : Shadowing ,
1046+ finalize : Option < Finalize > ,
1047+ ignore_binding : Option < NameBinding < ' ra > > ,
1048+ ignore_import : Option < Import < ' ra > > ,
1049+ ) -> Result < NameBinding < ' ra > , ControlFlow < Determinacy , Determinacy > > {
1050+ let key = BindingKey :: new ( ident, ns) ;
1051+ // `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding
1052+ // doesn't need to be mutable. It will fail when there is a cycle of imports, and without
1053+ // the exclusive access infinite recursion will crash the compiler with stack overflow.
1054+ let resolution = & * self
1055+ . resolution_or_default ( module, key)
1056+ . try_borrow_mut_unchecked ( )
1057+ . map_err ( |_| ControlFlow :: Continue ( Determined ) ) ?;
1058+
1059+ let binding = resolution. glob_binding . filter ( |b| Some ( * b) != ignore_binding) ;
1060+
1061+ if let Some ( finalize) = finalize {
1062+ return self . get_mut ( ) . finalize_module_binding (
1063+ ident,
1064+ binding,
1065+ if resolution. non_glob_binding . is_some ( ) { resolution. glob_binding } else { None } ,
1066+ parent_scope,
1067+ module,
1068+ finalize,
1069+ shadowing,
1070+ ) ;
1071+ }
9901072
9911073 // Check if one of single imports can still define the name,
9921074 // if it can then our result is not determined and can be invalidated.
@@ -1014,21 +1096,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10141096 // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
10151097 // shadowing is enabled, see `macro_expanded_macro_export_errors`).
10161098 if let Some ( binding) = binding {
1017- if binding. determined ( ) || ns == MacroNS || shadowing == Shadowing :: Restricted {
1018- return check_usable ( self , binding) ;
1099+ return if binding. determined ( ) || ns == MacroNS || shadowing == Shadowing :: Restricted {
1100+ let accessible = self . is_accessible_from ( binding. vis , parent_scope. module ) ;
1101+ if accessible { Ok ( binding) } else { Err ( ControlFlow :: Break ( Determined ) ) }
10191102 } else {
1020- return Err ( ControlFlow :: Break ( Undetermined ) ) ;
1021- }
1103+ Err ( ControlFlow :: Break ( Undetermined ) )
1104+ } ;
10221105 }
10231106
1024- // --- From now on we have no resolution. ---
1025-
10261107 // Now we are in situation when new item/import can appear only from a glob or a macro
10271108 // expansion. With restricted shadowing names from globs and macro expansions cannot
10281109 // shadow names from outer scopes, so we can freely fallback from module search to search
10291110 // in outer scopes. For `resolve_ident_in_scope_set` to continue search in outer
10301111 // scopes we return `Undetermined` with `ControlFlow::Continue`.
1031-
10321112 // Check if one of unexpanded macros can still define the name,
10331113 // if it can then our "no resolution" result is not determined and can be invalidated.
10341114 if !module. unexpanded_invocations . borrow ( ) . is_empty ( ) {
0 commit comments