Skip to content

Commit fdba30b

Browse files
committed
resolve idents bound by guard patterns outside of their guards
1 parent c4a1fc4 commit fdba30b

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

compiler/rustc_resolve/src/late.rs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,12 +2176,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
21762176
let mut parameter_info = Vec::new();
21772177
let mut all_candidates = Vec::new();
21782178

2179+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
21792180
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
21802181
for (index, (pat, ty)) in inputs.enumerate() {
21812182
debug!(?pat, ?ty);
21822183
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
21832184
if let Some(pat) = pat {
2184-
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
2185+
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
21852186
}
21862187
});
21872188

@@ -3445,6 +3446,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
34453446
Ident::new(kw::SelfLower, span),
34463447
delegation.id,
34473448
PatternSource::FnParam,
3449+
this.ribs[ValueNS].len() - 1,
34483450
&mut bindings,
34493451
);
34503452
this.visit_block(body);
@@ -3453,10 +3455,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
34533455
}
34543456

34553457
fn resolve_params(&mut self, params: &'ast [Param]) {
3458+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
34563459
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
34573460
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
34583461
for Param { pat, .. } in params {
3459-
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
3462+
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
34603463
}
34613464
});
34623465
for Param { ty, .. } in params {
@@ -3674,20 +3677,22 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
36743677
/// Arising from `source`, resolve a top level pattern.
36753678
fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
36763679
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3677-
self.resolve_pattern(pat, pat_src, &mut bindings);
3680+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
3681+
self.resolve_pattern(pat, pat_src, top_rib_idx, &mut bindings);
36783682
}
36793683

36803684
fn resolve_pattern(
36813685
&mut self,
36823686
pat: &'ast Pat,
36833687
pat_src: PatternSource,
3688+
top_rib_idx: usize,
36843689
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
36853690
) {
36863691
// We walk the pattern before declaring the pattern's inner bindings,
36873692
// so that we avoid resolving a literal expression to a binding defined
36883693
// by the pattern.
36893694
visit::walk_pat(self, pat);
3690-
self.resolve_pattern_inner(pat, pat_src, bindings);
3695+
self.resolve_pattern_inner(pat, pat_src, top_rib_idx, bindings);
36913696
// This has to happen *after* we determine which pat_idents are variants:
36923697
self.check_consistent_bindings(pat);
36933698
}
@@ -3715,6 +3720,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37153720
&mut self,
37163721
pat: &'ast Pat,
37173722
pat_src: PatternSource,
3723+
top_rib_idx: usize,
37183724
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
37193725
) {
37203726
// Visit all direct subpatterns of this pattern.
@@ -3727,7 +3733,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37273733
let has_sub = sub.is_some();
37283734
let res = self
37293735
.try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
3730-
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
3736+
.unwrap_or_else(|| {
3737+
self.fresh_binding(ident, pat.id, pat_src, top_rib_idx, bindings)
3738+
});
37313739
self.r.record_partial_res(pat.id, PartialRes::new(res));
37323740
self.r.record_pat_span(pat.id, pat.span);
37333741
}
@@ -3758,7 +3766,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37583766
// part of the or-pattern internally rejects already bound names.
37593767
// For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
37603768
bindings.push((PatBoundCtx::Product, Default::default()));
3761-
self.resolve_pattern_inner(p, pat_src, bindings);
3769+
self.resolve_pattern_inner(p, pat_src, top_rib_idx, bindings);
37623770
// Move up the non-overlapping bindings to the or-pattern.
37633771
// Existing bindings just get "merged".
37643772
let collected = bindings.pop().unwrap().1;
@@ -3775,7 +3783,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37753783
}
37763784
PatKind::Guard(ref subpat, ref cond) => {
37773785
self.with_rib(ValueNS, RibKind::Normal, |this| {
3778-
this.resolve_pattern_inner(subpat, pat_src, bindings);
3786+
this.resolve_pattern_inner(subpat, pat_src, top_rib_idx, bindings);
37793787
this.resolve_expr(cond, None);
37803788
});
37813789

@@ -3793,6 +3801,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37933801
ident: Ident,
37943802
pat_id: NodeId,
37953803
pat_src: PatternSource,
3804+
top_rib_idx: usize,
37963805
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
37973806
) -> Res {
37983807
// Add the binding to the local ribs, if it doesn't already exist in the bindings map.
@@ -3825,18 +3834,23 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38253834
bindings.last_mut().unwrap().1.insert(ident);
38263835
}
38273836

3828-
if already_bound_or {
3837+
let res = if already_bound_or {
38293838
// `Variant1(a) | Variant2(a)`, ok
38303839
// Reuse definition from the first `a`.
3831-
self.innermost_rib_bindings(ValueNS)[&ident]
3840+
self.ribs[ValueNS][top_rib_idx].bindings[&ident]
38323841
} else {
38333842
let res = Res::Local(pat_id);
38343843
if ident_valid {
38353844
// A completely fresh binding add to the set if it's valid.
3836-
self.innermost_rib_bindings(ValueNS).insert(ident, res);
3845+
self.ribs[ValueNS][top_rib_idx].bindings.insert(ident, res);
38373846
}
38383847
res
3839-
}
3848+
};
3849+
3850+
// Record the binding in the innermost rib so guard expressions can use it.
3851+
self.innermost_rib_bindings(ValueNS).insert(ident, res);
3852+
3853+
res
38403854
}
38413855

38423856
fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> {

0 commit comments

Comments
 (0)