Skip to content

Commit 2e3106b

Browse files
committed
resolve: Cleanup two main macro resolution functions, tweak some comments
1 parent 6ee9e97 commit 2e3106b

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)]
@@ -555,15 +556,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
555556
assert!(force || !record_used); // `record_used` implies `force`
556557
ident = ident.modern();
557558

558-
// Names from inner scope that can't shadow names from outer scopes, e.g.
559-
// mod m { ... }
559+
// This is *the* result, resolution from the scope closest to the resolved identifier.
560+
// However, sometimes this result is "weak" because it comes from a glob import or
561+
// a macro expansion, and in this case it cannot shadow names from outer scopes, e.g.
562+
// mod m { ... } // solution in outer scope
560563
// {
561-
// use prefix::*; // if this imports another `m`, then it can't shadow the outer `m`
562-
// // and we have and ambiguity error
564+
// use prefix::*; // imports another `m` - innermost solution
565+
// // weak, cannot shadow the outer `m`, need to report ambiguity error
563566
// m::mac!();
564567
// }
565-
// This includes names from globs and from macro expansions.
566-
let mut potentially_ambiguous_result: Option<(&NameBinding, FromPrelude)> = None;
568+
// So we have to save the innermost solution and continue searching in outer scopes
569+
// to detect potential ambiguities.
570+
let mut innermost_result: Option<(&NameBinding, FromPrelude)> = None;
567571

568572
enum WhereToResolve<'a> {
569573
Module(Module<'a>),
@@ -706,32 +710,25 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
706710
return Ok(result);
707711
}
708712

709-
// Found a solution that is ambiguous with a previously found solution.
710-
// Push an ambiguity error for later reporting and
711-
// return something for better recovery.
712-
if let Some(previous_result) = potentially_ambiguous_result {
713-
if result.0.def() != previous_result.0.def() {
713+
if let Some(innermost_result) = innermost_result {
714+
// Found another solution, if the first one was "weak", report an error.
715+
if result.0.def() != innermost_result.0.def() &&
716+
(innermost_result.0.is_glob_import() ||
717+
innermost_result.0.expansion != Mark::root()) {
714718
self.ambiguity_errors.push(AmbiguityError {
715719
span: path_span,
716720
name: ident.name,
717-
b1: previous_result.0,
721+
b1: innermost_result.0,
718722
b2: result.0,
719723
});
720-
return Ok(previous_result);
724+
return Ok(innermost_result);
721725
}
726+
} else {
727+
// Found the first solution.
728+
innermost_result = Some(result);
722729
}
723730

724-
// Found a solution that's not an ambiguity yet, but is "suspicious" and
725-
// can participate in ambiguities later on.
726-
// Remember it and go search for other solutions in outer scopes.
727-
if result.0.is_glob_import() || result.0.expansion != Mark::root() {
728-
potentially_ambiguous_result = Some(result);
729-
730-
continue_search!();
731-
}
732-
733-
// Found a solution that can't be ambiguous, great success.
734-
return Ok(result);
731+
continue_search!();
735732
},
736733
Err(Determinacy::Determined) => {
737734
continue_search!();
@@ -740,9 +737,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
740737
}
741738
}
742739

743-
// Previously found potentially ambiguous result turned out to not be ambiguous after all.
744-
if let Some(previous_result) = potentially_ambiguous_result {
745-
return Ok(previous_result);
740+
// The first found solution was the only one, return it.
741+
if let Some(innermost_result) = innermost_result {
742+
return Ok(innermost_result);
746743
}
747744

748745
let determinacy = Determinacy::determined(force);
@@ -761,30 +758,31 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
761758
}
762759

763760
fn resolve_legacy_scope(&mut self,
764-
scope: &'a Cell<LegacyScope<'a>>,
761+
invocation_legacy_scope: &'a Cell<LegacyScope<'a>>,
765762
ident: Ident,
766763
record_used: bool)
767764
-> Option<&'a NameBinding<'a>> {
768765
let ident = ident.modern();
769766

770-
// Names from inner scope that can't shadow names from outer scopes, e.g.
771-
// macro_rules! mac { ... }
767+
// This is *the* result, resolution from the scope closest to the resolved identifier.
768+
// However, sometimes this result is "weak" because it comes from a macro expansion,
769+
// and in this case it cannot shadow names from outer scopes, e.g.
770+
// macro_rules! m { ... } // solution in outer scope
772771
// {
773-
// define_mac!(); // if this generates another `macro_rules! mac`, then it can't shadow
774-
// // the outer `mac` and we have and ambiguity error
775-
// mac!();
772+
// define_m!(); // generates another `macro_rules! m` - innermost solution
773+
// // weak, cannot shadow the outer `m`, need to report ambiguity error
774+
// m!();
776775
// }
777-
let mut potentially_ambiguous_result: Option<&NameBinding> = None;
776+
// So we have to save the innermost solution and continue searching in outer scopes
777+
// to detect potential ambiguities.
778+
let mut innermost_result: Option<&NameBinding> = None;
778779

779780
// Go through all the scopes and try to resolve the name.
780-
let mut where_to_resolve = scope;
781+
let mut where_to_resolve = invocation_legacy_scope;
781782
loop {
782783
let result = match where_to_resolve.get() {
783-
LegacyScope::Binding(legacy_binding) => if ident == legacy_binding.ident {
784-
Some(legacy_binding.binding)
785-
} else {
786-
None
787-
}
784+
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
785+
Some(legacy_binding.binding),
788786
_ => None,
789787
};
790788

@@ -813,45 +811,33 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
813811
return Some(result);
814812
}
815813

816-
// Found a solution that is ambiguous with a previously found solution.
817-
// Push an ambiguity error for later reporting and
818-
// return something for better recovery.
819-
if let Some(previous_result) = potentially_ambiguous_result {
820-
if result.def() != previous_result.def() {
814+
if let Some(innermost_result) = innermost_result {
815+
// Found another solution, if the first one was "weak", report an error.
816+
if result.def() != innermost_result.def() &&
817+
innermost_result.expansion != Mark::root() {
821818
self.ambiguity_errors.push(AmbiguityError {
822819
span: ident.span,
823820
name: ident.name,
824-
b1: previous_result,
821+
b1: innermost_result,
825822
b2: result,
826823
});
827-
return Some(previous_result);
824+
return Some(innermost_result);
828825
}
826+
} else {
827+
// Found the first solution.
828+
innermost_result = Some(result);
829829
}
830830

831-
// Found a solution that's not an ambiguity yet, but is "suspicious" and
832-
// can participate in ambiguities later on.
833-
// Remember it and go search for other solutions in outer scopes.
834-
if result.expansion != Mark::root() {
835-
potentially_ambiguous_result = Some(result);
836-
837-
continue_search!();
838-
}
839-
840-
// Found a solution that can't be ambiguous.
841-
return Some(result);
831+
continue_search!();
842832
}
843833
None => {
844834
continue_search!();
845835
}
846836
}
847837
}
848838

849-
// Previously found potentially ambiguous result turned out to not be ambiguous after all.
850-
if let Some(previous_result) = potentially_ambiguous_result {
851-
return Some(previous_result);
852-
}
853-
854-
None
839+
// The first found solution was the only one (or there was no solution at all), return it.
840+
innermost_result
855841
}
856842

857843
pub fn finalize_current_module_macro_resolutions(&mut self) {

0 commit comments

Comments
 (0)