@@ -81,9 +81,9 @@ pub enum LegacyScope<'a> {
81
81
// Binding produced by a `macro_rules` item.
82
82
// Not modularized, can shadow previous legacy bindings, etc.
83
83
pub struct LegacyBinding < ' a > {
84
- pub binding : & ' a NameBinding < ' a > ,
85
- pub parent : Cell < LegacyScope < ' a > > ,
86
- pub ident : Ident ,
84
+ binding : & ' a NameBinding < ' a > ,
85
+ parent : Cell < LegacyScope < ' a > > ,
86
+ ident : Ident ,
87
87
}
88
88
89
89
pub struct ProcMacError {
@@ -761,42 +761,101 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
761
761
}
762
762
}
763
763
764
- crate fn resolve_legacy_scope ( & mut self ,
765
- mut scope : & ' a Cell < LegacyScope < ' a > > ,
766
- ident : Ident ,
767
- record_used : bool )
768
- -> Option < ( & ' a NameBinding < ' a > , FromExpansion ) > {
764
+ fn resolve_legacy_scope ( & mut self ,
765
+ scope : & ' a Cell < LegacyScope < ' a > > ,
766
+ ident : Ident ,
767
+ record_used : bool )
768
+ -> Option < ( & ' a NameBinding < ' a > , FromExpansion ) > {
769
769
let ident = ident. modern ( ) ;
770
- let mut relative_depth: u32 = 0 ;
770
+
771
+ // Names from inner scope that can't shadow names from outer scopes, e.g.
772
+ // macro_rules! mac { ... }
773
+ // {
774
+ // define_mac!(); // if this generates another `macro_rules! mac`, then it can't shadow
775
+ // // the outer `mac` and we have and ambiguity error
776
+ // mac!();
777
+ // }
778
+ let mut potentially_ambiguous_result: Option < ( & NameBinding , FromExpansion ) > = None ;
779
+
780
+ // Go through all the scopes and try to resolve the name.
781
+ let mut where_to_resolve = scope;
782
+ let mut relative_depth = 0u32 ;
771
783
loop {
772
- match scope. get ( ) {
773
- LegacyScope :: Empty => break ,
774
- LegacyScope :: Expansion ( invocation) => {
775
- match invocation. expansion . get ( ) {
776
- LegacyScope :: Invocation ( _) => scope. set ( invocation. legacy_scope . get ( ) ) ,
777
- LegacyScope :: Empty => {
778
- scope = & invocation. legacy_scope ;
779
- }
780
- _ => {
784
+ let result = match where_to_resolve. get ( ) {
785
+ LegacyScope :: Binding ( legacy_binding) => if ident == legacy_binding. ident {
786
+ Some ( ( legacy_binding. binding , FromExpansion ( relative_depth > 0 ) ) )
787
+ } else {
788
+ None
789
+ }
790
+ _ => None ,
791
+ } ;
792
+
793
+ macro_rules! continue_search { ( ) => {
794
+ where_to_resolve = match where_to_resolve. get( ) {
795
+ LegacyScope :: Binding ( binding) => & binding. parent,
796
+ LegacyScope :: Invocation ( invocation) => {
797
+ relative_depth = relative_depth. saturating_sub( 1 ) ;
798
+ & invocation. legacy_scope
799
+ }
800
+ LegacyScope :: Expansion ( invocation) => match invocation. expansion. get( ) {
801
+ LegacyScope :: Empty => & invocation. legacy_scope,
802
+ LegacyScope :: Binding ( ..) | LegacyScope :: Expansion ( ..) => {
781
803
relative_depth += 1 ;
782
- scope = & invocation. expansion ;
804
+ & invocation. expansion
805
+ }
806
+ LegacyScope :: Invocation ( ..) => {
807
+ where_to_resolve. set( invocation. legacy_scope. get( ) ) ;
808
+ where_to_resolve
783
809
}
784
810
}
785
- }
786
- LegacyScope :: Invocation ( invocation) => {
787
- relative_depth = relative_depth. saturating_sub ( 1 ) ;
788
- scope = & invocation. legacy_scope ;
789
- }
790
- LegacyScope :: Binding ( potential_binding) => {
791
- if potential_binding. ident == ident {
792
- if record_used && relative_depth > 0 {
793
- self . disallowed_shadowing . push ( potential_binding) ;
811
+ LegacyScope :: Empty => break , // nowhere else to search
812
+ } ;
813
+
814
+ continue ;
815
+ } }
816
+
817
+ match result {
818
+ Some ( result) => {
819
+ if !record_used {
820
+ return Some ( result) ;
821
+ }
822
+
823
+ // Found a solution that is ambiguous with a previously found solution.
824
+ // Push an ambiguity error for later reporting and
825
+ // return something for better recovery.
826
+ if let Some ( previous_result) = potentially_ambiguous_result {
827
+ if result. 0 . def ( ) != previous_result. 0 . def ( ) {
828
+ self . ambiguity_errors . push ( AmbiguityError {
829
+ span : ident. span ,
830
+ name : ident. name ,
831
+ b1 : previous_result. 0 ,
832
+ b2 : result. 0 ,
833
+ } ) ;
834
+ return Some ( previous_result) ;
794
835
}
795
- return Some ( ( potential_binding. binding , FromExpansion ( relative_depth > 0 ) ) ) ;
796
836
}
797
- scope = & potential_binding. parent ;
837
+
838
+ // Found a solution that's not an ambiguity yet, but is "suspicious" and
839
+ // can participate in ambiguities later on.
840
+ // Remember it and go search for other solutions in outer scopes.
841
+ if ( result. 1 ) . 0 {
842
+ potentially_ambiguous_result = Some ( result) ;
843
+
844
+ continue_search ! ( ) ;
845
+ }
846
+
847
+ // Found a solution that can't be ambiguous.
848
+ return Some ( result) ;
798
849
}
799
- } ;
850
+ None => {
851
+ continue_search ! ( ) ;
852
+ }
853
+ }
854
+ }
855
+
856
+ // Previously found potentially ambiguous result turned out to not be ambiguous after all.
857
+ if let Some ( previous_result) = potentially_ambiguous_result {
858
+ return Some ( previous_result) ;
800
859
}
801
860
802
861
None
@@ -823,8 +882,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
823
882
824
883
let check_consistency = |this : & Self , new_def : Def | {
825
884
if let Some ( def) = def {
826
- if this. ambiguity_errors . is_empty ( ) && this. disallowed_shadowing . is_empty ( ) &&
827
- new_def != def && new_def != Def :: Err {
885
+ if this. ambiguity_errors . is_empty ( ) && new_def != def && new_def != Def :: Err {
828
886
// Make sure compilation does not succeed if preferred macro resolution
829
887
// has changed after the macro had been expanded. In theory all such
830
888
// situations should be reported as ambiguity errors, so this is span-bug.
0 commit comments