Skip to content

Commit ecbe6c0

Browse files
committed
resolve idents bound by guard patterns outside of their guards
1 parent 302bd85 commit ecbe6c0

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
@@ -2207,12 +2207,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
22072207
let mut parameter_info = Vec::new();
22082208
let mut all_candidates = Vec::new();
22092209

2210+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
22102211
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
22112212
for (index, (pat, ty)) in inputs.enumerate() {
22122213
debug!(?pat, ?ty);
22132214
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
22142215
if let Some(pat) = pat {
2215-
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
2216+
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
22162217
}
22172218
});
22182219

@@ -3476,6 +3477,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
34763477
Ident::new(kw::SelfLower, span),
34773478
delegation.id,
34783479
PatternSource::FnParam,
3480+
this.ribs[ValueNS].len() - 1,
34793481
&mut bindings,
34803482
);
34813483
this.visit_block(body);
@@ -3484,10 +3486,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
34843486
}
34853487

34863488
fn resolve_params(&mut self, params: &'ast [Param]) {
3489+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
34873490
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
34883491
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
34893492
for Param { pat, .. } in params {
3490-
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
3493+
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
34913494
}
34923495
});
34933496
for Param { ty, .. } in params {
@@ -3705,20 +3708,22 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37053708
/// Arising from `source`, resolve a top level pattern.
37063709
fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
37073710
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3708-
self.resolve_pattern(pat, pat_src, &mut bindings);
3711+
let top_rib_idx = self.ribs[ValueNS].len() - 1;
3712+
self.resolve_pattern(pat, pat_src, top_rib_idx, &mut bindings);
37093713
}
37103714

37113715
fn resolve_pattern(
37123716
&mut self,
37133717
pat: &'ast Pat,
37143718
pat_src: PatternSource,
3719+
top_rib_idx: usize,
37153720
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
37163721
) {
37173722
// We walk the pattern before declaring the pattern's inner bindings,
37183723
// so that we avoid resolving a literal expression to a binding defined
37193724
// by the pattern.
37203725
visit::walk_pat(self, pat);
3721-
self.resolve_pattern_inner(pat, pat_src, bindings);
3726+
self.resolve_pattern_inner(pat, pat_src, top_rib_idx, bindings);
37223727
// This has to happen *after* we determine which pat_idents are variants:
37233728
self.check_consistent_bindings(pat);
37243729
}
@@ -3746,6 +3751,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37463751
&mut self,
37473752
pat: &'ast Pat,
37483753
pat_src: PatternSource,
3754+
top_rib_idx: usize,
37493755
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
37503756
) {
37513757
// Visit all direct subpatterns of this pattern.
@@ -3758,7 +3764,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37583764
let has_sub = sub.is_some();
37593765
let res = self
37603766
.try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
3761-
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
3767+
.unwrap_or_else(|| {
3768+
self.fresh_binding(ident, pat.id, pat_src, top_rib_idx, bindings)
3769+
});
37623770
self.r.record_partial_res(pat.id, PartialRes::new(res));
37633771
self.r.record_pat_span(pat.id, pat.span);
37643772
}
@@ -3789,7 +3797,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37893797
// part of the or-pattern internally rejects already bound names.
37903798
// For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
37913799
bindings.push((PatBoundCtx::Product, Default::default()));
3792-
self.resolve_pattern_inner(p, pat_src, bindings);
3800+
self.resolve_pattern_inner(p, pat_src, top_rib_idx, bindings);
37933801
// Move up the non-overlapping bindings to the or-pattern.
37943802
// Existing bindings just get "merged".
37953803
let collected = bindings.pop().unwrap().1;
@@ -3806,7 +3814,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38063814
}
38073815
PatKind::Guard(ref subpat, ref cond) => {
38083816
self.with_rib(ValueNS, RibKind::Normal, |this| {
3809-
this.resolve_pattern_inner(subpat, pat_src, bindings);
3817+
this.resolve_pattern_inner(subpat, pat_src, top_rib_idx, bindings);
38103818
this.resolve_expr(cond, None);
38113819
});
38123820

@@ -3824,6 +3832,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38243832
ident: Ident,
38253833
pat_id: NodeId,
38263834
pat_src: PatternSource,
3835+
top_rib_idx: usize,
38273836
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
38283837
) -> Res {
38293838
// Add the binding to the local ribs, if it doesn't already exist in the bindings map.
@@ -3856,18 +3865,23 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38563865
bindings.last_mut().unwrap().1.insert(ident);
38573866
}
38583867

3859-
if already_bound_or {
3868+
let res = if already_bound_or {
38603869
// `Variant1(a) | Variant2(a)`, ok
38613870
// Reuse definition from the first `a`.
3862-
self.innermost_rib_bindings(ValueNS)[&ident]
3871+
self.ribs[ValueNS][top_rib_idx].bindings[&ident]
38633872
} else {
38643873
let res = Res::Local(pat_id);
38653874
if ident_valid {
38663875
// A completely fresh binding add to the set if it's valid.
3867-
self.innermost_rib_bindings(ValueNS).insert(ident, res);
3876+
self.ribs[ValueNS][top_rib_idx].bindings.insert(ident, res);
38683877
}
38693878
res
3870-
}
3879+
};
3880+
3881+
// Record the binding in the innermost rib so guard expressions can use it.
3882+
self.innermost_rib_bindings(ValueNS).insert(ident, res);
3883+
3884+
res
38713885
}
38723886

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

0 commit comments

Comments
 (0)