Skip to content

Commit 8e9c1db

Browse files
committed
resolve idents bound by guard patterns outside of their guards
1 parent 79ba48b commit 8e9c1db

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

compiler/rustc_resolve/src/late.rs

+25-11
Original file line numberDiff line numberDiff line change
@@ -2227,12 +2227,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
22272227
let mut parameter_info = Vec::new();
22282228
let mut all_candidates = Vec::new();
22292229

2230+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
22302231
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
22312232
for (index, (pat, ty)) in inputs.enumerate() {
22322233
debug!(?pat, ?ty);
22332234
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
22342235
if let Some(pat) = pat {
2235-
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
2236+
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
22362237
}
22372238
});
22382239

@@ -3490,6 +3491,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
34903491
Ident::new(kw::SelfLower, span),
34913492
delegation.id,
34923493
PatternSource::FnParam,
3494+
this.ribs[ValueNS].len() - 1,
34933495
&mut bindings,
34943496
);
34953497
this.visit_block(body);
@@ -3498,10 +3500,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
34983500
}
34993501

35003502
fn resolve_params(&mut self, params: &'ast [Param]) {
3503+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
35013504
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
35023505
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
35033506
for Param { pat, .. } in params {
3504-
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
3507+
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
35053508
}
35063509
});
35073510
for Param { ty, .. } in params {
@@ -3719,20 +3722,22 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37193722
/// Arising from `source`, resolve a top level pattern.
37203723
fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
37213724
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3722-
self.resolve_pattern(pat, pat_src, &mut bindings);
3725+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
3726+
self.resolve_pattern(pat, pat_src, top_rib_idx, &mut bindings);
37233727
}
37243728

37253729
fn resolve_pattern(
37263730
&mut self,
37273731
pat: &'ast Pat,
37283732
pat_src: PatternSource,
3733+
top_rib_idx: usize,
37293734
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
37303735
) {
37313736
// We walk the pattern before declaring the pattern's inner bindings,
37323737
// so that we avoid resolving a literal expression to a binding defined
37333738
// by the pattern.
37343739
visit::walk_pat(self, pat);
3735-
self.resolve_pattern_inner(pat, pat_src, bindings);
3740+
self.resolve_pattern_inner(pat, pat_src, top_rib_idx, bindings);
37363741
// This has to happen *after* we determine which pat_idents are variants:
37373742
self.check_consistent_bindings(pat);
37383743
}
@@ -3760,6 +3765,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37603765
&mut self,
37613766
pat: &'ast Pat,
37623767
pat_src: PatternSource,
3768+
top_rib_idx: usize,
37633769
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
37643770
) {
37653771
// Visit all direct subpatterns of this pattern.
@@ -3772,7 +3778,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37723778
let has_sub = sub.is_some();
37733779
let res = self
37743780
.try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
3775-
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
3781+
.unwrap_or_else(|| {
3782+
self.fresh_binding(ident, pat.id, pat_src, top_rib_idx, bindings)
3783+
});
37763784
self.r.record_partial_res(pat.id, PartialRes::new(res));
37773785
self.r.record_pat_span(pat.id, pat.span);
37783786
}
@@ -3803,7 +3811,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38033811
// part of the or-pattern internally rejects already bound names.
38043812
// For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
38053813
bindings.push((PatBoundCtx::Product, Default::default()));
3806-
self.resolve_pattern_inner(p, pat_src, bindings);
3814+
self.resolve_pattern_inner(p, pat_src, top_rib_idx, bindings);
38073815
// Move up the non-overlapping bindings to the or-pattern.
38083816
// Existing bindings just get "merged".
38093817
let collected = bindings.pop().unwrap().1;
@@ -3820,7 +3828,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38203828
}
38213829
PatKind::Guard(ref subpat, ref cond) => {
38223830
self.with_rib(ValueNS, RibKind::Normal, |this| {
3823-
this.resolve_pattern_inner(subpat, pat_src, bindings);
3831+
this.resolve_pattern_inner(subpat, pat_src, top_rib_idx, bindings);
38243832
this.resolve_expr(cond, None);
38253833
});
38263834

@@ -3838,6 +3846,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38383846
ident: Ident,
38393847
pat_id: NodeId,
38403848
pat_src: PatternSource,
3849+
top_rib_idx: usize,
38413850
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
38423851
) -> Res {
38433852
// Add the binding to the local ribs, if it doesn't already exist in the bindings map.
@@ -3870,18 +3879,23 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38703879
bindings.last_mut().unwrap().1.insert(ident);
38713880
}
38723881

3873-
if already_bound_or {
3882+
let res = if already_bound_or {
38743883
// `Variant1(a) | Variant2(a)`, ok
38753884
// Reuse definition from the first `a`.
3876-
self.innermost_rib_bindings(ValueNS)[&ident]
3885+
self.ribs[ValueNS][top_rib_idx].bindings[&ident]
38773886
} else {
38783887
let res = Res::Local(pat_id);
38793888
if ident_valid {
38803889
// A completely fresh binding add to the set if it's valid.
3881-
self.innermost_rib_bindings(ValueNS).insert(ident, res);
3890+
self.ribs[ValueNS][top_rib_idx].bindings.insert(ident, res);
38823891
}
38833892
res
3884-
}
3893+
};
3894+
3895+
// Record the binding in the innermost rib so guard expressions can use it.
3896+
self.innermost_rib_bindings(ValueNS).insert(ident, res);
3897+
3898+
res
38853899
}
38863900

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

0 commit comments

Comments
 (0)