Skip to content

Commit

Permalink
resolve idents bound by guard patterns outside of their guards
Browse files Browse the repository at this point in the history
  • Loading branch information
max-niederman committed Sep 15, 2024
1 parent 9148483 commit cb2e54e
Showing 1 changed file with 25 additions and 11 deletions.
36 changes: 25 additions & 11 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2122,12 +2122,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let mut parameter_info = Vec::new();
let mut all_candidates = Vec::new();

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

Expand Down Expand Up @@ -3384,6 +3385,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
Ident::new(kw::SelfLower, span),
delegation.id,
PatternSource::FnParam,
this.ribs[ValueNS].len() - 1,
&mut bindings,
);
this.visit_block(body);
Expand All @@ -3392,10 +3394,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}

fn resolve_params(&mut self, params: &'ast [Param]) {
let top_rib_idx = self.ribs[ValueNS].len() - 1;
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
for Param { pat, .. } in params {
this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
this.resolve_pattern(pat, PatternSource::FnParam, top_rib_idx, &mut bindings);
}
});
for Param { ty, .. } in params {
Expand Down Expand Up @@ -3613,20 +3616,22 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
/// Arising from `source`, resolve a top level pattern.
fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
self.resolve_pattern(pat, pat_src, &mut bindings);
let top_rib_idx = self.ribs[ValueNS].len() - 1;
self.resolve_pattern(pat, pat_src, top_rib_idx, &mut bindings);
}

fn resolve_pattern(
&mut self,
pat: &'ast Pat,
pat_src: PatternSource,
top_rib_idx: usize,
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
) {
// We walk the pattern before declaring the pattern's inner bindings,
// so that we avoid resolving a literal expression to a binding defined
// by the pattern.
visit::walk_pat(self, pat);
self.resolve_pattern_inner(pat, pat_src, bindings);
self.resolve_pattern_inner(pat, pat_src, top_rib_idx, bindings);
// This has to happen *after* we determine which pat_idents are variants:
self.check_consistent_bindings(pat);
}
Expand Down Expand Up @@ -3654,6 +3659,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
&mut self,
pat: &'ast Pat,
pat_src: PatternSource,
top_rib_idx: usize,
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
) {
// Visit all direct subpatterns of this pattern.
Expand All @@ -3666,7 +3672,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let has_sub = sub.is_some();
let res = self
.try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
.unwrap_or_else(|| {
self.fresh_binding(ident, pat.id, pat_src, top_rib_idx, bindings)
});
self.r.record_partial_res(pat.id, PartialRes::new(res));
self.r.record_pat_span(pat.id, pat.span);
}
Expand Down Expand Up @@ -3697,7 +3705,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// part of the or-pattern internally rejects already bound names.
// For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
bindings.push((PatBoundCtx::Product, Default::default()));
self.resolve_pattern_inner(p, pat_src, bindings);
self.resolve_pattern_inner(p, pat_src, top_rib_idx, bindings);
// Move up the non-overlapping bindings to the or-pattern.
// Existing bindings just get "merged".
let collected = bindings.pop().unwrap().1;
Expand All @@ -3714,7 +3722,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
PatKind::Guard(ref subpat, ref cond) => {
self.with_rib(ValueNS, RibKind::Normal, |this| {
this.resolve_pattern_inner(subpat, pat_src, bindings);
this.resolve_pattern_inner(subpat, pat_src, top_rib_idx, bindings);
this.resolve_expr(cond, None);
});

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

if already_bound_or {
let res = if already_bound_or {
// `Variant1(a) | Variant2(a)`, ok
// Reuse definition from the first `a`.
self.innermost_rib_bindings(ValueNS)[&ident]
self.ribs[ValueNS][top_rib_idx].bindings[&ident]
} else {
let res = Res::Local(pat_id);
if ident_valid {
// A completely fresh binding add to the set if it's valid.
self.innermost_rib_bindings(ValueNS).insert(ident, res);
self.ribs[ValueNS][top_rib_idx].bindings.insert(ident, res);
}
res
}
};

// Record the binding in the innermost rib so guard expressions can use it.
self.innermost_rib_bindings(ValueNS).insert(ident, res);

res
}

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

0 comments on commit cb2e54e

Please sign in to comment.