]> git.lizzy.rs Git - rust.git/blob - src/librustc_ast_lowering/pat.rs
Add `is_const_impl_raw` query
[rust.git] / src / librustc_ast_lowering / pat.rs
1 use super::{ImplTraitContext, LoweringContext, ParamMode};
2
3 use rustc_hir as hir;
4 use rustc_hir::def::Res;
5 use rustc_span::{source_map::Spanned, Span};
6 use syntax::ast::*;
7 use syntax::ptr::P;
8
9 impl<'a, 'hir> LoweringContext<'a, 'hir> {
10     crate fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
11         let node = match p.kind {
12             PatKind::Wild => hir::PatKind::Wild,
13             PatKind::Ident(ref binding_mode, ident, ref sub) => {
14                 let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
15                 let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
16                 node
17             }
18             PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
19             PatKind::TupleStruct(ref path, ref pats) => {
20                 let qpath = self.lower_qpath(
21                     p.id,
22                     &None,
23                     path,
24                     ParamMode::Optional,
25                     ImplTraitContext::disallowed(),
26                 );
27                 let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
28                 hir::PatKind::TupleStruct(qpath, pats, ddpos)
29             }
30             PatKind::Or(ref pats) => {
31                 hir::PatKind::Or(self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))))
32             }
33             PatKind::Path(ref qself, ref path) => {
34                 let qpath = self.lower_qpath(
35                     p.id,
36                     qself,
37                     path,
38                     ParamMode::Optional,
39                     ImplTraitContext::disallowed(),
40                 );
41                 hir::PatKind::Path(qpath)
42             }
43             PatKind::Struct(ref path, ref fields, etc) => {
44                 let qpath = self.lower_qpath(
45                     p.id,
46                     &None,
47                     path,
48                     ParamMode::Optional,
49                     ImplTraitContext::disallowed(),
50                 );
51
52                 let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat {
53                     hir_id: self.next_id(),
54                     ident: f.ident,
55                     pat: self.lower_pat(&f.pat),
56                     is_shorthand: f.is_shorthand,
57                     span: f.span,
58                 }));
59                 hir::PatKind::Struct(qpath, fs, etc)
60             }
61             PatKind::Tuple(ref pats) => {
62                 let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
63                 hir::PatKind::Tuple(pats, ddpos)
64             }
65             PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
66             PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
67             PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
68                 e1.as_deref().map(|e| self.lower_expr(e)),
69                 e2.as_deref().map(|e| self.lower_expr(e)),
70                 self.lower_range_end(end, e2.is_some()),
71             ),
72             PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
73             PatKind::Rest => {
74                 // If we reach here the `..` pattern is not semantically allowed.
75                 self.ban_illegal_rest_pat(p.span)
76             }
77             PatKind::Paren(ref inner) => return self.lower_pat(inner),
78             PatKind::Mac(_) => panic!("Shouldn't exist here"),
79         };
80
81         self.pat_with_node_id_of(p, node)
82     }
83
84     fn lower_pat_tuple(
85         &mut self,
86         pats: &[P<Pat>],
87         ctx: &str,
88     ) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
89         let mut elems = Vec::with_capacity(pats.len());
90         let mut rest = None;
91
92         let mut iter = pats.iter().enumerate();
93         for (idx, pat) in iter.by_ref() {
94             // Interpret the first `..` pattern as a sub-tuple pattern.
95             // Note that unlike for slice patterns,
96             // where `xs @ ..` is a legal sub-slice pattern,
97             // it is not a legal sub-tuple pattern.
98             if pat.is_rest() {
99                 rest = Some((idx, pat.span));
100                 break;
101             }
102             // It was not a sub-tuple pattern so lower it normally.
103             elems.push(self.lower_pat(pat));
104         }
105
106         for (_, pat) in iter {
107             // There was a previous sub-tuple pattern; make sure we don't allow more...
108             if pat.is_rest() {
109                 // ...but there was one again, so error.
110                 self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
111             } else {
112                 elems.push(self.lower_pat(pat));
113             }
114         }
115
116         (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
117     }
118
119     /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
120     /// `hir::PatKind::Slice(before, slice, after)`.
121     ///
122     /// When encountering `($binding_mode $ident @)? ..` (`slice`),
123     /// this is interpreted as a sub-slice pattern semantically.
124     /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
125     fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
126         let mut before = Vec::new();
127         let mut after = Vec::new();
128         let mut slice = None;
129         let mut prev_rest_span = None;
130
131         // Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
132         let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| {
133             let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
134             let node = this.lower_pat_ident(pat, bm, ident, lower_sub);
135             this.pat_with_node_id_of(pat, node)
136         };
137
138         let mut iter = pats.iter();
139         // Lower all the patterns until the first occurrence of a sub-slice pattern.
140         for pat in iter.by_ref() {
141             match pat.kind {
142                 // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
143                 PatKind::Rest => {
144                     prev_rest_span = Some(pat.span);
145                     slice = Some(self.pat_wild_with_node_id_of(pat));
146                     break;
147                 }
148                 // Found a sub-slice pattern `$binding_mode $ident @ ..`.
149                 // Record, lower it to `$binding_mode $ident @ _`, and stop here.
150                 PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
151                     prev_rest_span = Some(sub.span);
152                     slice = Some(lower_rest_sub(self, pat, bm, ident, sub));
153                     break;
154                 }
155                 // It was not a subslice pattern so lower it normally.
156                 _ => before.push(self.lower_pat(pat)),
157             }
158         }
159
160         // Lower all the patterns after the first sub-slice pattern.
161         for pat in iter {
162             // There was a previous subslice pattern; make sure we don't allow more.
163             let rest_span = match pat.kind {
164                 PatKind::Rest => Some(pat.span),
165                 PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
166                     // #69103: Lower into `binding @ _` as above to avoid ICEs.
167                     after.push(lower_rest_sub(self, pat, bm, ident, sub));
168                     Some(sub.span)
169                 }
170                 _ => None,
171             };
172             if let Some(rest_span) = rest_span {
173                 // We have e.g., `[a, .., b, ..]`. That's no good, error!
174                 self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
175             } else {
176                 // Lower the pattern normally.
177                 after.push(self.lower_pat(pat));
178             }
179         }
180
181         hir::PatKind::Slice(
182             self.arena.alloc_from_iter(before),
183             slice,
184             self.arena.alloc_from_iter(after),
185         )
186     }
187
188     fn lower_pat_ident(
189         &mut self,
190         p: &Pat,
191         binding_mode: &BindingMode,
192         ident: Ident,
193         lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
194     ) -> hir::PatKind<'hir> {
195         match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
196             // `None` can occur in body-less function signatures
197             res @ None | res @ Some(Res::Local(_)) => {
198                 let canonical_id = match res {
199                     Some(Res::Local(id)) => id,
200                     _ => p.id,
201                 };
202
203                 hir::PatKind::Binding(
204                     self.lower_binding_mode(binding_mode),
205                     self.lower_node_id(canonical_id),
206                     ident,
207                     lower_sub(self),
208                 )
209             }
210             Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
211                 None,
212                 self.arena.alloc(hir::Path {
213                     span: ident.span,
214                     res: self.lower_res(res),
215                     segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
216                 }),
217             )),
218         }
219     }
220
221     fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
222         match *b {
223             BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
224             BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
225             BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
226             BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
227         }
228     }
229
230     fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
231         self.pat_with_node_id_of(p, hir::PatKind::Wild)
232     }
233
234     /// Construct a `Pat` with the `HirId` of `p.id` lowered.
235     fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
236         self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
237     }
238
239     /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
240     fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
241         self.diagnostic()
242             .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
243             .span_label(sp, &format!("can only be used once per {} pattern", ctx))
244             .span_label(prev_sp, "previously used here")
245             .emit();
246     }
247
248     /// Used to ban the `..` pattern in places it shouldn't be semantically.
249     fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
250         self.diagnostic()
251             .struct_span_err(sp, "`..` patterns are not allowed here")
252             .note("only allowed in tuple, tuple struct, and slice patterns")
253             .emit();
254
255         // We're not in a list context so `..` can be reasonably treated
256         // as `_` because it should always be valid and roughly matches the
257         // intent of `..` (notice that the rest of a single slot is that slot).
258         hir::PatKind::Wild
259     }
260
261     fn lower_range_end(&mut self, e: &RangeEnd, has_end: bool) -> hir::RangeEnd {
262         match *e {
263             RangeEnd::Excluded if has_end => hir::RangeEnd::Excluded,
264             // No end; so `X..` behaves like `RangeFrom`.
265             RangeEnd::Excluded | RangeEnd::Included(_) => hir::RangeEnd::Included,
266         }
267     }
268 }