Skip to content

Commit cb2e54e

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

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
@@ -2122,12 +2122,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
21222122
let mut parameter_info = Vec::new();
21232123
let mut all_candidates = Vec::new();
21242124

2125+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
21252126
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
21262127
for (index, (pat, ty)) in inputs.enumerate() {
21272128
debug!(?pat, ?ty);
21282129
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
21292130
if let Some(pat) = pat {
2130-
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
2131+
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
21312132
}
21322133
});
21332134

@@ -3384,6 +3385,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
33843385
Ident::new(kw::SelfLower, span),
33853386
delegation.id,
33863387
PatternSource::FnParam,
3388+
this.ribs[ValueNS].len() - 1,
33873389
&mut bindings,
33883390
);
33893391
this.visit_block(body);
@@ -3392,10 +3394,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
33923394
}
33933395

33943396
fn resolve_params(&mut self, params: &'ast [Param]) {
3397+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
33953398
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
33963399
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
33973400
for Param { pat, .. } in params {
3398-
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
3401+
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
33993402
}
34003403
});
34013404
for Param { ty, .. } in params {
@@ -3613,20 +3616,22 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
36133616
/// Arising from `source`, resolve a top level pattern.
36143617
fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
36153618
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3616-
self.resolve_pattern(pat, pat_src, &mut bindings);
3619+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
3620+
self.resolve_pattern(pat, pat_src, top_rib_idx, &mut bindings);
36173621
}
36183622

36193623
fn resolve_pattern(
36203624
&mut self,
36213625
pat: &'ast Pat,
36223626
pat_src: PatternSource,
3627+
top_rib_idx: usize,
36233628
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
36243629
) {
36253630
// We walk the pattern before declaring the pattern's inner bindings,
36263631
// so that we avoid resolving a literal expression to a binding defined
36273632
// by the pattern.
36283633
visit::walk_pat(self, pat);
3629-
self.resolve_pattern_inner(pat, pat_src, bindings);
3634+
self.resolve_pattern_inner(pat, pat_src, top_rib_idx, bindings);
36303635
// This has to happen *after* we determine which pat_idents are variants:
36313636
self.check_consistent_bindings(pat);
36323637
}
@@ -3654,6 +3659,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
36543659
&mut self,
36553660
pat: &'ast Pat,
36563661
pat_src: PatternSource,
3662+
top_rib_idx: usize,
36573663
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
36583664
) {
36593665
// Visit all direct subpatterns of this pattern.
@@ -3666,7 +3672,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
36663672
let has_sub = sub.is_some();
36673673
let res = self
36683674
.try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
3669-
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
3675+
.unwrap_or_else(|| {
3676+
self.fresh_binding(ident, pat.id, pat_src, top_rib_idx, bindings)
3677+
});
36703678
self.r.record_partial_res(pat.id, PartialRes::new(res));
36713679
self.r.record_pat_span(pat.id, pat.span);
36723680
}
@@ -3697,7 +3705,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
36973705
// part of the or-pattern internally rejects already bound names.
36983706
// For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
36993707
bindings.push((PatBoundCtx::Product, Default::default()));
3700-
self.resolve_pattern_inner(p, pat_src, bindings);
3708+
self.resolve_pattern_inner(p, pat_src, top_rib_idx, bindings);
37013709
// Move up the non-overlapping bindings to the or-pattern.
37023710
// Existing bindings just get "merged".
37033711
let collected = bindings.pop().unwrap().1;
@@ -3714,7 +3722,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
37143722
}
37153723
PatKind::Guard(ref subpat, ref cond) => {
37163724
self.with_rib(ValueNS, RibKind::Normal, |this| {
3717-
this.resolve_pattern_inner(subpat, pat_src, bindings);
3725+
this.resolve_pattern_inner(subpat, pat_src, top_rib_idx, bindings);
37183726
this.resolve_expr(cond, None);
37193727
});
37203728

@@ -3732,6 +3740,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
37323740
ident: Ident,
37333741
pat_id: NodeId,
37343742
pat_src: PatternSource,
3743+
top_rib_idx: usize,
37353744
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
37363745
) -> Res {
37373746
// Add the binding to the local ribs, if it doesn't already exist in the bindings map.
@@ -3764,18 +3773,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
37643773
bindings.last_mut().unwrap().1.insert(ident);
37653774
}
37663775

3767-
if already_bound_or {
3776+
let res = if already_bound_or {
37683777
// `Variant1(a) | Variant2(a)`, ok
37693778
// Reuse definition from the first `a`.
3770-
self.innermost_rib_bindings(ValueNS)[&ident]
3779+
self.ribs[ValueNS][top_rib_idx].bindings[&ident]
37713780
} else {
37723781
let res = Res::Local(pat_id);
37733782
if ident_valid {
37743783
// A completely fresh binding add to the set if it's valid.
3775-
self.innermost_rib_bindings(ValueNS).insert(ident, res);
3784+
self.ribs[ValueNS][top_rib_idx].bindings.insert(ident, res);
37763785
}
37773786
res
3778-
}
3787+
};
3788+
3789+
// Record the binding in the innermost rib so guard expressions can use it.
3790+
self.innermost_rib_bindings(ValueNS).insert(ident, res);
3791+
3792+
res
37793793
}
37803794

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

0 commit comments

Comments
 (0)