diff options
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index e7235c1a1..4d372c97b 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -329,6 +329,43 @@ impl Expr { | |||
329 | pub struct PatId(RawId); | 329 | pub struct PatId(RawId); |
330 | impl_arena_id!(PatId); | 330 | impl_arena_id!(PatId); |
331 | 331 | ||
332 | // copied verbatim from librustc::hir | ||
333 | |||
334 | /// Explicit binding annotations given in the HIR for a binding. Note | ||
335 | /// that this is not the final binding *mode* that we infer after type | ||
336 | /// inference. | ||
337 | #[derive(Clone, PartialEq, Eq, Debug, Copy)] | ||
338 | pub enum BindingAnnotation { | ||
339 | /// No binding annotation given: this means that the final binding mode | ||
340 | /// will depend on whether we have skipped through a `&` reference | ||
341 | /// when matching. For example, the `x` in `Some(x)` will have binding | ||
342 | /// mode `None`; if you do `let Some(x) = &Some(22)`, it will | ||
343 | /// ultimately be inferred to be by-reference. | ||
344 | /// | ||
345 | /// Note that implicit reference skipping is not implemented yet (#42640). | ||
346 | Unannotated, | ||
347 | |||
348 | /// Annotated with `mut x` -- could be either ref or not, similar to `None`. | ||
349 | Mutable, | ||
350 | |||
351 | /// Annotated as `ref`, like `ref x` | ||
352 | Ref, | ||
353 | |||
354 | /// Annotated as `ref mut x`. | ||
355 | RefMut, | ||
356 | } | ||
357 | |||
358 | impl BindingAnnotation { | ||
359 | fn new(is_mutable: bool, is_ref: bool) -> Self { | ||
360 | match (is_mutable, is_ref) { | ||
361 | (true, true) => BindingAnnotation::RefMut, | ||
362 | (false, true) => BindingAnnotation::Ref, | ||
363 | (true, false) => BindingAnnotation::Mutable, | ||
364 | (false, false) => BindingAnnotation::Unannotated, | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | |||
332 | #[derive(Debug, Clone, Eq, PartialEq)] | 369 | #[derive(Debug, Clone, Eq, PartialEq)] |
333 | pub struct FieldPat { | 370 | pub struct FieldPat { |
334 | pub(crate) name: Name, | 371 | pub(crate) name: Name, |
@@ -359,7 +396,9 @@ pub enum Pat { | |||
359 | Path(Path), | 396 | Path(Path), |
360 | Lit(ExprId), | 397 | Lit(ExprId), |
361 | Bind { | 398 | Bind { |
399 | mode: BindingAnnotation, | ||
362 | name: Name, | 400 | name: Name, |
401 | sub_pat: Option<PatId>, | ||
363 | }, | 402 | }, |
364 | TupleStruct { | 403 | TupleStruct { |
365 | path: Option<Path>, | 404 | path: Option<Path>, |
@@ -793,7 +832,13 @@ impl ExprCollector { | |||
793 | .name() | 832 | .name() |
794 | .map(|nr| nr.as_name()) | 833 | .map(|nr| nr.as_name()) |
795 | .unwrap_or_else(Name::missing); | 834 | .unwrap_or_else(Name::missing); |
796 | Pat::Bind { name } | 835 | let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref()); |
836 | let sub_pat = bp.pat().map(|subpat| self.collect_pat(subpat)); | ||
837 | Pat::Bind { | ||
838 | name, | ||
839 | mode: annotation, | ||
840 | sub_pat, | ||
841 | } | ||
797 | } | 842 | } |
798 | ast::PatKind::TupleStructPat(p) => { | 843 | ast::PatKind::TupleStructPat(p) => { |
799 | let path = p.path().and_then(Path::from_ast); | 844 | let path = p.path().and_then(Path::from_ast); |
@@ -882,6 +927,8 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { | |||
882 | let param = collector.alloc_pat( | 927 | let param = collector.alloc_pat( |
883 | Pat::Bind { | 928 | Pat::Bind { |
884 | name: Name::self_param(), | 929 | name: Name::self_param(), |
930 | mode: BindingAnnotation::Unannotated, | ||
931 | sub_pat: None, | ||
885 | }, | 932 | }, |
886 | self_param, | 933 | self_param, |
887 | ); | 934 | ); |