Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor with {ast, hir, hair::pattern}::Binding #67620

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ pub trait Visitor<'v>: Sized {
fn visit_pat(&mut self, p: &'v Pat) {
walk_pat(self, p)
}
fn visit_binding(&mut self, b: &'v Binding) {
walk_binding(self, b)
}
fn visit_anon_const(&mut self, c: &'v AnonConst) {
walk_anon_const(self, c)
}
Expand Down Expand Up @@ -709,8 +712,8 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) => {
visitor.visit_pat(subpattern)
}
PatKind::Binding(_, _hir_id, ident, ref optional_subpattern) => {
visitor.visit_ident(ident);
PatKind::Binding(ref binding, ref optional_subpattern) => {
visitor.visit_binding(binding);
walk_list!(visitor, visit_pat, optional_subpattern);
}
PatKind::Lit(ref expression) => visitor.visit_expr(expression),
Expand All @@ -727,6 +730,13 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
}
}

pub fn walk_binding<'v, V: Visitor<'v>>(
visitor: &mut V,
Binding { ident, annot: _, hir_id: _ }: &'v Binding,
) {
visitor.visit_ident(*ident);
}

pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
visitor.visit_id(foreign_item.hir_id);
visitor.visit_vis(&foreign_item.vis);
Expand Down
67 changes: 34 additions & 33 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2065,7 +2065,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
inputs
.iter()
.map(|param| match param.pat.kind {
PatKind::Ident(_, ident, _) => ident,
PatKind::Binding(Binding { ident, mode: _ }, _) => ident,
_ => Ident::new(kw::Invalid, param.pat.span),
})
.collect()
Expand Down Expand Up @@ -2155,8 +2155,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
c_variadic,
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
let is_mutable_pat = match arg.pat.kind {
PatKind::Ident(BindingMode::ByValue(mt), _, _)
| PatKind::Ident(BindingMode::ByRef(mt), _, _) => mt == Mutability::Mut,
PatKind::Binding(Binding { mode: BindingMode::ByValue(mt), ident: _ }, _)
| PatKind::Binding(Binding { mode: BindingMode::ByRef(mt), ident: _ }, _) => {
mt == Mutability::Mut
}
_ => false,
};

Expand Down Expand Up @@ -2622,9 +2624,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
let node = match p.kind {
PatKind::Wild => hir::PatKind::Wild,
PatKind::Ident(ref binding_mode, ident, ref sub) => {
PatKind::Binding(binding, ref sub) => {
let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
let node = self.lower_pat_binding(p, binding, lower_sub);
node
}
PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
Expand Down Expand Up @@ -2755,10 +2757,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
// Found a sub-slice pattern `$binding_mode $ident @ ..`.
// Record, lower it to `$binding_mode $ident @ _`, and stop here.
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
PatKind::Binding(binding, Some(ref sub)) if sub.is_rest() => {
prev_rest_span = Some(sub.span);
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
let node = self.lower_pat_binding(pat, binding, lower_sub);
slice = Some(self.pat_with_node_id_of(pat, node));
break;
}
Expand All @@ -2772,7 +2774,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// There was a previous subslice pattern; make sure we don't allow more.
let rest_span = match pat.kind {
PatKind::Rest => Some(pat.span),
PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
PatKind::Binding(_, Some(ref sub)) if sub.is_rest() => {
// The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
after.push(self.pat_wild_with_node_id_of(pat));
Some(sub.span)
Expand All @@ -2791,11 +2793,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::PatKind::Slice(before.into(), slice, after.into())
}

fn lower_pat_ident(
fn lower_binding(
&mut self,
Binding { mode, ident }: Binding,
canonical_id: NodeId,
) -> hir::Binding {
let annot = self.lower_binding_mode(&mode);
let hir_id = self.lower_node_id(canonical_id);
hir::Binding { annot, hir_id, ident }
}

fn lower_pat_binding(
&mut self,
p: &Pat,
binding_mode: &BindingMode,
ident: Ident,
binding: Binding,
lower_sub: impl FnOnce(&mut Self) -> Option<P<hir::Pat>>,
) -> hir::PatKind {
match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
Expand All @@ -2805,22 +2816,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Some(Res::Local(id)) => id,
_ => p.id,
};

hir::PatKind::Binding(
self.lower_binding_mode(binding_mode),
self.lower_node_id(canonical_id),
ident,
lower_sub(self),
)
let binding = self.lower_binding(binding, canonical_id);
hir::PatKind::Binding(binding, lower_sub(self))
}
Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
None,
P(hir::Path {
Some(res) => {
let Binding { ident, mode: _ } = binding;
let path = hir::Path {
span: ident.span,
res: self.lower_res(res),
segments: hir_vec![hir::PathSegment::from_ident(ident)],
}),
)),
};
hir::PatKind::Path(hir::QPath::Resolved(None, P(path)))
}
}
}

Expand Down Expand Up @@ -3030,18 +3037,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
annot: hir::BindingAnnotation,
) -> (P<hir::Pat>, hir::HirId) {
let hir_id = self.next_id();

(
P(hir::Pat {
hir_id,
kind: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None),
span,
}),
hir_id,
)
let binding = hir::Binding { annot, hir_id, ident: ident.with_span_pos(span) };
let kind = hir::PatKind::Binding(binding, None);
(P(hir::Pat { hir_id, kind, span }), hir_id)
}

fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/hir/lowering/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,9 +1104,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Check if this is a binding pattern, if so, we can optimize and avoid adding a
// `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
let (ident, is_simple_parameter) = match parameter.pat.kind {
hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) => {
(ident, true)
}
hir::PatKind::Binding(
hir::Binding { annot: hir::BindingAnnotation::Unannotated, ident, .. },
_,
) => (ident, true),
_ => {
// Replace the ident for bindings that aren't simple.
let name = format!("__arg{}", index);
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,9 @@ impl<'hir> Map<'hir> {
Node::Field(f) => f.ident.name,
Node::Lifetime(lt) => lt.name.ident().name,
Node::GenericParam(param) => param.name.ident().name,
Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name,
Node::Binding(&Pat { kind: PatKind::Binding(Binding { ident, .. }, _), .. }) => {
ident.name
}
Node::Ctor(..) => self.name(self.get_parent_item(id)),
_ => return None,
})
Expand Down
25 changes: 20 additions & 5 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,10 @@ pub struct Block {
pub targeted_by_break: bool,
}

// `Pat` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(Pat, 80);

#[derive(RustcEncodable, RustcDecodable, HashStable)]
pub struct Pat {
#[stable_hasher(ignore)]
Expand Down Expand Up @@ -951,6 +955,20 @@ pub struct FieldPat {
pub span: Span,
}

/// A fresh binding `{ref mut?}? $ident`.
///
/// The `HirId` is the canonical ID for the variable being bound,
/// (e.g., in `Ok(x) | Err(x)`, both `x` use the same canonical ID),
/// which is the pattern ID of the first `x`.
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub struct Binding {
/// The optional `ref mut?` annotation on this binding.
pub annot: BindingAnnotation,
pub hir_id: HirId,
/// The introduced binding name.
pub ident: Ident,
}

/// Explicit binding annotations given in the HIR for a binding. Note
/// that this is not the final binding *mode* that we infer after type
/// inference.
Expand Down Expand Up @@ -995,11 +1013,8 @@ pub enum PatKind {
/// Represents a wildcard pattern (i.e., `_`).
Wild,

/// A fresh binding `ref mut binding @ OPT_SUBPATTERN`.
/// The `HirId` is the canonical ID for the variable being bound,
/// (e.g., in `Ok(x) | Err(x)`, both `x` use the same canonical ID),
/// which is the pattern ID of the first `x`.
Binding(BindingAnnotation, HirId, Ident, Option<P<Pat>>),
/// A fresh binding pattern `binding {@ PAT}?`.
Binding(Binding, Option<P<Pat>>),

/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
/// The `bool` is `true` in the presence of a `..`.
Expand Down
31 changes: 18 additions & 13 deletions src/librustc/hir/pat_util.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::hir::def::{CtorOf, DefKind, Res};
use crate::hir::def_id::DefId;
use crate::hir::{self, HirId, PatKind};
use crate::hir::{self, Binding, BindingAnnotation, PatKind};
use syntax::ast;
use syntax_pos::Span;

Expand Down Expand Up @@ -78,10 +78,11 @@ impl hir::Pat {

/// Call `f` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident)) {
pub fn each_binding(&self, mut f: impl FnMut(&Binding, Span)) {
self.walk_always(|p| {
if let PatKind::Binding(binding_mode, _, ident, _) = p.kind {
f(binding_mode, p.hir_id, p.span, ident);
if let PatKind::Binding(binding, _) = &p.kind {
// FIXME(Centril): compute and use span of binding.
f(binding, p.span);
}
});
}
Expand All @@ -90,17 +91,15 @@ impl hir::Pat {
/// `match foo() { Some(a) => (), None => () }`.
///
/// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited.
pub fn each_binding_or_first(
&self,
f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident),
) {
pub fn each_binding_or_first(&self, f: &mut impl FnMut(&Binding, Span)) {
self.walk(|p| match &p.kind {
PatKind::Or(ps) => {
ps[0].each_binding_or_first(f);
false
}
PatKind::Binding(bm, _, ident, _) => {
f(*bm, p.hir_id, p.span, *ident);
PatKind::Binding(binding, _) => {
// FIXME(Centril): compute and use span of binding.
f(binding, p.span);
true
}
_ => true,
Expand Down Expand Up @@ -141,8 +140,14 @@ impl hir::Pat {

pub fn simple_ident(&self) -> Option<ast::Ident> {
match self.kind {
PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, None)
| PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, None) => Some(ident),
PatKind::Binding(
Binding { annot: BindingAnnotation::Unannotated, ident, hir_id: _ },
None,
)
| PatKind::Binding(
Binding { annot: BindingAnnotation::Mutable, ident, hir_id: _ },
None,
) => Some(ident),
_ => None,
}
}
Expand Down Expand Up @@ -176,7 +181,7 @@ impl hir::Pat {
// ref bindings are be implicit after #42640 (default match binding modes). See issue #44848.
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
let mut result = None;
self.each_binding(|annotation, _, _, _| match annotation {
self.each_binding(|hir::Binding { annot, ident: _, hir_id: _ }, _| match annot {
hir::BindingAnnotation::Ref => match result {
None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
_ => {}
Expand Down
34 changes: 18 additions & 16 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1599,29 +1599,31 @@ impl<'a> State<'a> {
}
}

fn print_binding(&mut self, hir::Binding { annot, ident, hir_id: _ }: &hir::Binding) {
match annot {
hir::BindingAnnotation::Ref => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Not, false);
}
hir::BindingAnnotation::RefMut => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Mut, false);
}
hir::BindingAnnotation::Unannotated => {}
hir::BindingAnnotation::Mutable => self.word_nbsp("mut"),
}
self.print_ident(*ident);
}

pub fn print_pat(&mut self, pat: &hir::Pat) {
self.maybe_print_comment(pat.span.lo());
self.ann.pre(self, AnnNode::Pat(pat));
// Pat isn't normalized, but the beauty of it
// is that it doesn't matter
match pat.kind {
PatKind::Wild => self.s.word("_"),
PatKind::Binding(binding_mode, _, ident, ref sub) => {
match binding_mode {
hir::BindingAnnotation::Ref => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Not, false);
}
hir::BindingAnnotation::RefMut => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Mut, false);
}
hir::BindingAnnotation::Unannotated => {}
hir::BindingAnnotation::Mutable => {
self.word_nbsp("mut");
}
}
self.print_ident(ident);
PatKind::Binding(ref binding, ref sub) => {
self.print_binding(binding);
if let Some(ref p) = *sub {
self.s.word("@");
self.print_pat(&p);
Expand Down
8 changes: 3 additions & 5 deletions src/librustc/hir/upvars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,9 @@ impl Visitor<'tcx> for LocalCollector {
NestedVisitorMap::None
}

fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
if let hir::PatKind::Binding(_, hir_id, ..) = pat.kind {
self.locals.insert(hir_id);
}
intravisit::walk_pat(self, pat);
fn visit_binding(&mut self, binding: &'tcx hir::Binding) {
self.locals.insert(binding.hir_id);
intravisit::walk_binding(self, binding);
}
}

Expand Down
Loading