Skip to content

Commit f75ccde

Browse files
committed
extract pattern lowering -> pat.rs
1 parent 956265d commit f75ccde

File tree

2 files changed

+256
-246
lines changed

2 files changed

+256
-246
lines changed

src/librustc_ast_lowering/lib.rs

Lines changed: 3 additions & 246 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
//! in the HIR, especially for multiple identifiers.
3434
3535
#![feature(array_value_iter)]
36+
#![feature(crate_visibility_modifier)]
3637

3738
use rustc::arena::Arena;
3839
use rustc::dep_graph::DepGraph;
@@ -58,14 +59,13 @@ use rustc_session::config::nightly_options;
5859
use rustc_session::node_id::NodeMap;
5960
use rustc_session::Session;
6061
use rustc_span::hygiene::ExpnId;
61-
use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind, Spanned};
62+
use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind};
6263
use rustc_span::symbol::{kw, sym, Symbol};
6364
use rustc_span::Span;
6465
use syntax::ast;
6566
use syntax::ast::*;
6667
use syntax::attr;
6768
use syntax::print::pprust;
68-
use syntax::ptr::P as AstP;
6969
use syntax::sess::ParseSess;
7070
use syntax::token::{self, Nonterminal, Token};
7171
use syntax::tokenstream::{TokenStream, TokenTree};
@@ -86,6 +86,7 @@ macro_rules! arena_vec {
8686

8787
mod expr;
8888
mod item;
89+
mod pat;
8990

9091
const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
9192

@@ -2636,250 +2637,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
26362637
self.expr_block(block, AttrVec::new())
26372638
}
26382639

2639-
fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
2640-
let node = match p.kind {
2641-
PatKind::Wild => hir::PatKind::Wild,
2642-
PatKind::Ident(ref binding_mode, ident, ref sub) => {
2643-
let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
2644-
let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
2645-
node
2646-
}
2647-
PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
2648-
PatKind::TupleStruct(ref path, ref pats) => {
2649-
let qpath = self.lower_qpath(
2650-
p.id,
2651-
&None,
2652-
path,
2653-
ParamMode::Optional,
2654-
ImplTraitContext::disallowed(),
2655-
);
2656-
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
2657-
hir::PatKind::TupleStruct(qpath, pats, ddpos)
2658-
}
2659-
PatKind::Or(ref pats) => {
2660-
hir::PatKind::Or(self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))))
2661-
}
2662-
PatKind::Path(ref qself, ref path) => {
2663-
let qpath = self.lower_qpath(
2664-
p.id,
2665-
qself,
2666-
path,
2667-
ParamMode::Optional,
2668-
ImplTraitContext::disallowed(),
2669-
);
2670-
hir::PatKind::Path(qpath)
2671-
}
2672-
PatKind::Struct(ref path, ref fields, etc) => {
2673-
let qpath = self.lower_qpath(
2674-
p.id,
2675-
&None,
2676-
path,
2677-
ParamMode::Optional,
2678-
ImplTraitContext::disallowed(),
2679-
);
2680-
2681-
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat {
2682-
hir_id: self.next_id(),
2683-
ident: f.ident,
2684-
pat: self.lower_pat(&f.pat),
2685-
is_shorthand: f.is_shorthand,
2686-
span: f.span,
2687-
}));
2688-
hir::PatKind::Struct(qpath, fs, etc)
2689-
}
2690-
PatKind::Tuple(ref pats) => {
2691-
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
2692-
hir::PatKind::Tuple(pats, ddpos)
2693-
}
2694-
PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
2695-
PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
2696-
PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
2697-
self.lower_expr(e1),
2698-
self.lower_expr(e2),
2699-
self.lower_range_end(end),
2700-
),
2701-
PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
2702-
PatKind::Rest => {
2703-
// If we reach here the `..` pattern is not semantically allowed.
2704-
self.ban_illegal_rest_pat(p.span)
2705-
}
2706-
PatKind::Paren(ref inner) => return self.lower_pat(inner),
2707-
PatKind::Mac(_) => panic!("Shouldn't exist here"),
2708-
};
2709-
2710-
self.pat_with_node_id_of(p, node)
2711-
}
2712-
2713-
fn lower_pat_tuple(
2714-
&mut self,
2715-
pats: &[AstP<Pat>],
2716-
ctx: &str,
2717-
) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
2718-
let mut elems = Vec::with_capacity(pats.len());
2719-
let mut rest = None;
2720-
2721-
let mut iter = pats.iter().enumerate();
2722-
for (idx, pat) in iter.by_ref() {
2723-
// Interpret the first `..` pattern as a sub-tuple pattern.
2724-
// Note that unlike for slice patterns,
2725-
// where `xs @ ..` is a legal sub-slice pattern,
2726-
// it is not a legal sub-tuple pattern.
2727-
if pat.is_rest() {
2728-
rest = Some((idx, pat.span));
2729-
break;
2730-
}
2731-
// It was not a sub-tuple pattern so lower it normally.
2732-
elems.push(self.lower_pat(pat));
2733-
}
2734-
2735-
for (_, pat) in iter {
2736-
// There was a previous sub-tuple pattern; make sure we don't allow more...
2737-
if pat.is_rest() {
2738-
// ...but there was one again, so error.
2739-
self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
2740-
} else {
2741-
elems.push(self.lower_pat(pat));
2742-
}
2743-
}
2744-
2745-
(self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
2746-
}
2747-
2748-
/// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
2749-
/// `hir::PatKind::Slice(before, slice, after)`.
2750-
///
2751-
/// When encountering `($binding_mode $ident @)? ..` (`slice`),
2752-
/// this is interpreted as a sub-slice pattern semantically.
2753-
/// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
2754-
fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind<'hir> {
2755-
let mut before = Vec::new();
2756-
let mut after = Vec::new();
2757-
let mut slice = None;
2758-
let mut prev_rest_span = None;
2759-
2760-
let mut iter = pats.iter();
2761-
// Lower all the patterns until the first occurence of a sub-slice pattern.
2762-
for pat in iter.by_ref() {
2763-
match pat.kind {
2764-
// Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
2765-
PatKind::Rest => {
2766-
prev_rest_span = Some(pat.span);
2767-
slice = Some(self.pat_wild_with_node_id_of(pat));
2768-
break;
2769-
}
2770-
// Found a sub-slice pattern `$binding_mode $ident @ ..`.
2771-
// Record, lower it to `$binding_mode $ident @ _`, and stop here.
2772-
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
2773-
prev_rest_span = Some(sub.span);
2774-
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
2775-
let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
2776-
slice = Some(self.pat_with_node_id_of(pat, node));
2777-
break;
2778-
}
2779-
// It was not a subslice pattern so lower it normally.
2780-
_ => before.push(self.lower_pat(pat)),
2781-
}
2782-
}
2783-
2784-
// Lower all the patterns after the first sub-slice pattern.
2785-
for pat in iter {
2786-
// There was a previous subslice pattern; make sure we don't allow more.
2787-
let rest_span = match pat.kind {
2788-
PatKind::Rest => Some(pat.span),
2789-
PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
2790-
// The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
2791-
after.push(self.pat_wild_with_node_id_of(pat));
2792-
Some(sub.span)
2793-
}
2794-
_ => None,
2795-
};
2796-
if let Some(rest_span) = rest_span {
2797-
// We have e.g., `[a, .., b, ..]`. That's no good, error!
2798-
self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
2799-
} else {
2800-
// Lower the pattern normally.
2801-
after.push(self.lower_pat(pat));
2802-
}
2803-
}
2804-
2805-
hir::PatKind::Slice(
2806-
self.arena.alloc_from_iter(before),
2807-
slice,
2808-
self.arena.alloc_from_iter(after),
2809-
)
2810-
}
2811-
2812-
fn lower_pat_ident(
2813-
&mut self,
2814-
p: &Pat,
2815-
binding_mode: &BindingMode,
2816-
ident: Ident,
2817-
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
2818-
) -> hir::PatKind<'hir> {
2819-
match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
2820-
// `None` can occur in body-less function signatures
2821-
res @ None | res @ Some(Res::Local(_)) => {
2822-
let canonical_id = match res {
2823-
Some(Res::Local(id)) => id,
2824-
_ => p.id,
2825-
};
2826-
2827-
hir::PatKind::Binding(
2828-
self.lower_binding_mode(binding_mode),
2829-
self.lower_node_id(canonical_id),
2830-
ident,
2831-
lower_sub(self),
2832-
)
2833-
}
2834-
Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
2835-
None,
2836-
self.arena.alloc(hir::Path {
2837-
span: ident.span,
2838-
res: self.lower_res(res),
2839-
segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
2840-
}),
2841-
)),
2842-
}
2843-
}
2844-
2845-
fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
2846-
self.pat_with_node_id_of(p, hir::PatKind::Wild)
2847-
}
2848-
2849-
/// Construct a `Pat` with the `HirId` of `p.id` lowered.
2850-
fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
2851-
self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
2852-
}
2853-
2854-
/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
2855-
fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
2856-
self.diagnostic()
2857-
.struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
2858-
.span_label(sp, &format!("can only be used once per {} pattern", ctx))
2859-
.span_label(prev_sp, "previously used here")
2860-
.emit();
2861-
}
2862-
2863-
/// Used to ban the `..` pattern in places it shouldn't be semantically.
2864-
fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
2865-
self.diagnostic()
2866-
.struct_span_err(sp, "`..` patterns are not allowed here")
2867-
.note("only allowed in tuple, tuple struct, and slice patterns")
2868-
.emit();
2869-
2870-
// We're not in a list context so `..` can be reasonably treated
2871-
// as `_` because it should always be valid and roughly matches the
2872-
// intent of `..` (notice that the rest of a single slot is that slot).
2873-
hir::PatKind::Wild
2874-
}
2875-
2876-
fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
2877-
match *e {
2878-
RangeEnd::Included(_) => hir::RangeEnd::Included,
2879-
RangeEnd::Excluded => hir::RangeEnd::Excluded,
2880-
}
2881-
}
2882-
28832640
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
28842641
self.with_new_scopes(|this| hir::AnonConst {
28852642
hir_id: this.lower_node_id(c.id),

0 commit comments

Comments
 (0)