@@ -42,9 +42,10 @@ use std::{mem, ptr};
4242#[ derive( Clone , Debug ) ]
4343pub enum ImportDirectiveSubclass < ' a > {
4444 SingleImport {
45- target : Ident ,
4645 source : Ident ,
47- result : PerNS < Cell < Result < & ' a NameBinding < ' a > , Determinacy > > > ,
46+ target : Ident ,
47+ source_bindings : PerNS < Cell < Result < & ' a NameBinding < ' a > , Determinacy > > > ,
48+ target_bindings : PerNS < Cell < Option < & ' a NameBinding < ' a > > > > ,
4849 type_ns_only : bool ,
4950 } ,
5051 GlobImport {
@@ -227,14 +228,30 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
227228 }
228229
229230 let check_usable = |this : & mut Self , binding : & ' a NameBinding < ' a > | {
231+ if let Some ( blacklisted_binding) = this. blacklisted_binding {
232+ if ptr:: eq ( binding, blacklisted_binding) {
233+ return Err ( ( Determined , Weak :: No ) ) ;
234+ }
235+ }
230236 // `extern crate` are always usable for backwards compatibility, see issue #37020,
231237 // remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`.
232238 let usable = this. is_accessible ( binding. vis ) || binding. is_extern_crate ( ) ;
233239 if usable { Ok ( binding) } else { Err ( ( Determined , Weak :: No ) ) }
234240 } ;
235241
236242 if record_used {
237- return resolution. binding . ok_or ( ( Determined , Weak :: No ) ) . and_then ( |binding| {
243+ return resolution. binding . and_then ( |binding| {
244+ // If the primary binding is blacklisted, search further and return the shadowed
245+ // glob binding if it exists. What we really want here is having two separate
246+ // scopes in a module - one for non-globs and one for globs, but until that's done
247+ // use this hack to avoid inconsistent resolution ICEs during import validation.
248+ if let Some ( blacklisted_binding) = self . blacklisted_binding {
249+ if ptr:: eq ( binding, blacklisted_binding) {
250+ return resolution. shadowed_glob ;
251+ }
252+ }
253+ Some ( binding)
254+ } ) . ok_or ( ( Determined , Weak :: No ) ) . and_then ( |binding| {
238255 if self . last_import_segment && check_usable ( self , binding) . is_err ( ) {
239256 Err ( ( Determined , Weak :: No ) )
240257 } else {
@@ -646,10 +663,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
646663 if let Some ( ( span, err, note) ) = self . finalize_import ( import) {
647664 errors = true ;
648665
649- if let SingleImport { source, ref result , .. } = import. subclass {
666+ if let SingleImport { source, ref source_bindings , .. } = import. subclass {
650667 if source. name == "self" {
651668 // Silence `unresolved import` error if E0429 is already emitted
652- if let Err ( Determined ) = result . value_ns . get ( ) {
669+ if let Err ( Determined ) = source_bindings . value_ns . get ( ) {
653670 continue ;
654671 }
655672 }
@@ -769,9 +786,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
769786 } ;
770787
771788 directive. imported_module . set ( Some ( module) ) ;
772- let ( source, target, result, type_ns_only) = match directive. subclass {
773- SingleImport { source, target, ref result, type_ns_only } =>
774- ( source, target, result, type_ns_only) ,
789+ let ( source, target, source_bindings, target_bindings, type_ns_only) =
790+ match directive. subclass {
791+ SingleImport { source, target, ref source_bindings,
792+ ref target_bindings, type_ns_only } =>
793+ ( source, target, source_bindings, target_bindings, type_ns_only) ,
775794 GlobImport { .. } => {
776795 self . resolve_glob_import ( directive) ;
777796 return true ;
@@ -781,7 +800,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
781800
782801 let mut indeterminate = false ;
783802 self . per_ns ( |this, ns| if !type_ns_only || ns == TypeNS {
784- if let Err ( Undetermined ) = result [ ns] . get ( ) {
803+ if let Err ( Undetermined ) = source_bindings [ ns] . get ( ) {
785804 // For better failure detection, pretend that the import will
786805 // not define any names while resolving its module path.
787806 let orig_vis = directive. vis . replace ( ty:: Visibility :: Invisible ) ;
@@ -790,13 +809,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
790809 ) ;
791810 directive. vis . set ( orig_vis) ;
792811
793- result [ ns] . set ( binding) ;
812+ source_bindings [ ns] . set ( binding) ;
794813 } else {
795814 return
796815 } ;
797816
798817 let parent = directive. parent_scope . module ;
799- match result [ ns] . get ( ) {
818+ match source_bindings [ ns] . get ( ) {
800819 Err ( Undetermined ) => indeterminate = true ,
801820 Err ( Determined ) => {
802821 this. update_resolution ( parent, target, ns, |_, resolution| {
@@ -814,6 +833,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
814833 }
815834 Ok ( binding) => {
816835 let imported_binding = this. import ( binding, directive) ;
836+ target_bindings[ ns] . set ( Some ( imported_binding) ) ;
817837 let conflict = this. try_define ( parent, target, ns, imported_binding) ;
818838 if let Err ( old_binding) = conflict {
819839 this. report_conflict ( parent, target, ns, imported_binding, old_binding) ;
@@ -885,8 +905,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
885905 PathResult :: Indeterminate | PathResult :: NonModule ( ..) => unreachable ! ( ) ,
886906 } ;
887907
888- let ( ident, result, type_ns_only) = match directive. subclass {
889- SingleImport { source, ref result, type_ns_only, .. } => ( source, result, type_ns_only) ,
908+ let ( ident, source_bindings, target_bindings, type_ns_only) = match directive. subclass {
909+ SingleImport { source, ref source_bindings, ref target_bindings, type_ns_only, .. } =>
910+ ( source, source_bindings, target_bindings, type_ns_only) ,
890911 GlobImport { is_prelude, ref max_vis } => {
891912 if directive. module_path . len ( ) <= 1 {
892913 // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
@@ -925,17 +946,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
925946 let mut all_ns_err = true ;
926947 self . per_ns ( |this, ns| if !type_ns_only || ns == TypeNS {
927948 let orig_vis = directive. vis . replace ( ty:: Visibility :: Invisible ) ;
949+ let orig_blacklisted_binding =
950+ mem:: replace ( & mut this. blacklisted_binding , target_bindings[ ns] . get ( ) ) ;
928951 let orig_last_import_segment = mem:: replace ( & mut this. last_import_segment , true ) ;
929952 let binding = this. resolve_ident_in_module (
930953 module, ident, ns, Some ( & directive. parent_scope ) , true , directive. span
931954 ) ;
932955 this. last_import_segment = orig_last_import_segment;
956+ this. blacklisted_binding = orig_blacklisted_binding;
933957 directive. vis . set ( orig_vis) ;
934958
935959 match binding {
936960 Ok ( binding) => {
937961 // Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
938- let initial_def = result [ ns] . get ( ) . map ( |initial_binding| {
962+ let initial_def = source_bindings [ ns] . get ( ) . map ( |initial_binding| {
939963 all_ns_err = false ;
940964 this. record_use ( ident, ns, initial_binding,
941965 directive. module_path . is_empty ( ) ) ;
@@ -1040,7 +1064,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
10401064 let mut reexport_error = None ;
10411065 let mut any_successful_reexport = false ;
10421066 self . per_ns ( |this, ns| {
1043- if let Ok ( binding) = result [ ns] . get ( ) {
1067+ if let Ok ( binding) = source_bindings [ ns] . get ( ) {
10441068 let vis = directive. vis . get ( ) ;
10451069 if !binding. pseudo_vis ( ) . is_at_least ( vis, & * this) {
10461070 reexport_error = Some ( ( ns, binding) ) ;
@@ -1084,7 +1108,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
10841108 let mut full_path = directive. module_path . clone ( ) ;
10851109 full_path. push ( Segment :: from_ident ( ident) ) ;
10861110 self . per_ns ( |this, ns| {
1087- if let Ok ( binding) = result [ ns] . get ( ) {
1111+ if let Ok ( binding) = source_bindings [ ns] . get ( ) {
10881112 this. lint_if_path_starts_with_module (
10891113 directive. crate_lint ( ) ,
10901114 & full_path,
@@ -1098,7 +1122,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
10981122 // Record what this import resolves to for later uses in documentation,
10991123 // this may resolve to either a value or a type, but for documentation
11001124 // purposes it's good enough to just favor one over the other.
1101- self . per_ns ( |this, ns| if let Some ( binding) = result [ ns] . get ( ) . ok ( ) {
1125+ self . per_ns ( |this, ns| if let Some ( binding) = source_bindings [ ns] . get ( ) . ok ( ) {
11021126 let mut def = binding. def ( ) ;
11031127 if let Def :: Macro ( def_id, _) = def {
11041128 // `DefId`s from the "built-in macro crate" should not leak from resolve because
0 commit comments