Skip to content

Commit 9a539ad

Browse files
committed
resolve: Cleanup two main macro resolution functions, tweak some comments
1 parent f34ac26 commit 9a539ad

File tree

1 file changed

+50
-64
lines changed

1 file changed

+50
-64
lines changed

src/librustc_resolve/macros.rs

Lines changed: 50 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use std::mem;
4545
use rustc_data_structures::sync::Lrc;
4646
use rustc_data_structures::small_vec::ExpectOne;
4747

48+
#[derive(Clone, Copy)]
4849
crate struct FromPrelude(bool);
4950

5051
#[derive(Clone)]
@@ -578,15 +579,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
578579
assert!(force || !record_used); // `record_used` implies `force`
579580
ident = ident.modern();
580581

581-
// Names from inner scope that can't shadow names from outer scopes, e.g.
582-
// mod m { ... }
582+
// This is *the* result, resolution from the scope closest to the resolved identifier.
583+
// However, sometimes this result is "weak" because it comes from a glob import or
584+
// a macro expansion, and in this case it cannot shadow names from outer scopes, e.g.
585+
// mod m { ... } // solution in outer scope
583586
// {
584-
// use prefix::*; // if this imports another `m`, then it can't shadow the outer `m`
585-
// // and we have and ambiguity error
587+
// use prefix::*; // imports another `m` - innermost solution
588+
// // weak, cannot shadow the outer `m`, need to report ambiguity error
586589
// m::mac!();
587590
// }
588-
// This includes names from globs and from macro expansions.
589-
let mut potentially_ambiguous_result: Option<(&NameBinding, FromPrelude)> = None;
591+
// So we have to save the innermost solution and continue searching in outer scopes
592+
// to detect potential ambiguities.
593+
let mut innermost_result: Option<(&NameBinding, FromPrelude)> = None;
590594

591595
enum WhereToResolve<'a> {
592596
Module(Module<'a>),
@@ -729,32 +733,25 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
729733
return Ok(result);
730734
}
731735

732-
// Found a solution that is ambiguous with a previously found solution.
733-
// Push an ambiguity error for later reporting and
734-
// return something for better recovery.
735-
if let Some(previous_result) = potentially_ambiguous_result {
736-
if result.0.def() != previous_result.0.def() {
736+
if let Some(innermost_result) = innermost_result {
737+
// Found another solution, if the first one was "weak", report an error.
738+
if result.0.def() != innermost_result.0.def() &&
739+
(innermost_result.0.is_glob_import() ||
740+
innermost_result.0.expansion != Mark::root()) {
737741
self.ambiguity_errors.push(AmbiguityError {
738742
span: path_span,
739743
name: ident.name,
740-
b1: previous_result.0,
744+
b1: innermost_result.0,
741745
b2: result.0,
742746
});
743-
return Ok(previous_result);
747+
return Ok(innermost_result);
744748
}
749+
} else {
750+
// Found the first solution.
751+
innermost_result = Some(result);
745752
}
746753

747-
// Found a solution that's not an ambiguity yet, but is "suspicious" and
748-
// can participate in ambiguities later on.
749-
// Remember it and go search for other solutions in outer scopes.
750-
if result.0.is_glob_import() || result.0.expansion != Mark::root() {
751-
potentially_ambiguous_result = Some(result);
752-
753-
continue_search!();
754-
}
755-
756-
// Found a solution that can't be ambiguous, great success.
757-
return Ok(result);
754+
continue_search!();
758755
},
759756
Err(Determinacy::Determined) => {
760757
continue_search!();
@@ -763,9 +760,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
763760
}
764761
}
765762

766-
// Previously found potentially ambiguous result turned out to not be ambiguous after all.
767-
if let Some(previous_result) = potentially_ambiguous_result {
768-
return Ok(previous_result);
763+
// The first found solution was the only one, return it.
764+
if let Some(innermost_result) = innermost_result {
765+
return Ok(innermost_result);
769766
}
770767

771768
let determinacy = Determinacy::determined(force);
@@ -784,30 +781,31 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
784781
}
785782

786783
fn resolve_legacy_scope(&mut self,
787-
scope: &'a Cell<LegacyScope<'a>>,
784+
invocation_legacy_scope: &'a Cell<LegacyScope<'a>>,
788785
ident: Ident,
789786
record_used: bool)
790787
-> Option<&'a NameBinding<'a>> {
791788
let ident = ident.modern();
792789

793-
// Names from inner scope that can't shadow names from outer scopes, e.g.
794-
// macro_rules! mac { ... }
790+
// This is *the* result, resolution from the scope closest to the resolved identifier.
791+
// However, sometimes this result is "weak" because it comes from a macro expansion,
792+
// and in this case it cannot shadow names from outer scopes, e.g.
793+
// macro_rules! m { ... } // solution in outer scope
795794
// {
796-
// define_mac!(); // if this generates another `macro_rules! mac`, then it can't shadow
797-
// // the outer `mac` and we have and ambiguity error
798-
// mac!();
795+
// define_m!(); // generates another `macro_rules! m` - innermost solution
796+
// // weak, cannot shadow the outer `m`, need to report ambiguity error
797+
// m!();
799798
// }
800-
let mut potentially_ambiguous_result: Option<&NameBinding> = None;
799+
// So we have to save the innermost solution and continue searching in outer scopes
800+
// to detect potential ambiguities.
801+
let mut innermost_result: Option<&NameBinding> = None;
801802

802803
// Go through all the scopes and try to resolve the name.
803-
let mut where_to_resolve = scope;
804+
let mut where_to_resolve = invocation_legacy_scope;
804805
loop {
805806
let result = match where_to_resolve.get() {
806-
LegacyScope::Binding(legacy_binding) => if ident == legacy_binding.ident {
807-
Some(legacy_binding.binding)
808-
} else {
809-
None
810-
}
807+
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
808+
Some(legacy_binding.binding),
811809
_ => None,
812810
};
813811

@@ -836,45 +834,33 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
836834
return Some(result);
837835
}
838836

839-
// Found a solution that is ambiguous with a previously found solution.
840-
// Push an ambiguity error for later reporting and
841-
// return something for better recovery.
842-
if let Some(previous_result) = potentially_ambiguous_result {
843-
if result.def() != previous_result.def() {
837+
if let Some(innermost_result) = innermost_result {
838+
// Found another solution, if the first one was "weak", report an error.
839+
if result.def() != innermost_result.def() &&
840+
innermost_result.expansion != Mark::root() {
844841
self.ambiguity_errors.push(AmbiguityError {
845842
span: ident.span,
846843
name: ident.name,
847-
b1: previous_result,
844+
b1: innermost_result,
848845
b2: result,
849846
});
850-
return Some(previous_result);
847+
return Some(innermost_result);
851848
}
849+
} else {
850+
// Found the first solution.
851+
innermost_result = Some(result);
852852
}
853853

854-
// Found a solution that's not an ambiguity yet, but is "suspicious" and
855-
// can participate in ambiguities later on.
856-
// Remember it and go search for other solutions in outer scopes.
857-
if result.expansion != Mark::root() {
858-
potentially_ambiguous_result = Some(result);
859-
860-
continue_search!();
861-
}
862-
863-
// Found a solution that can't be ambiguous.
864-
return Some(result);
854+
continue_search!();
865855
}
866856
None => {
867857
continue_search!();
868858
}
869859
}
870860
}
871861

872-
// Previously found potentially ambiguous result turned out to not be ambiguous after all.
873-
if let Some(previous_result) = potentially_ambiguous_result {
874-
return Some(previous_result);
875-
}
876-
877-
None
862+
// The first found solution was the only one (or there was no solution at all), return it.
863+
innermost_result
878864
}
879865

880866
pub fn finalize_current_module_macro_resolutions(&mut self) {

0 commit comments

Comments
 (0)