diff options
Diffstat (limited to 'crates/ra_hir_ty/src/infer')
-rw-r--r-- | crates/ra_hir_ty/src/infer/pat.rs | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index 4006f595d..23de2bd6b 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -4,7 +4,7 @@ use std::iter::repeat; | |||
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | expr::{BindingAnnotation, Pat, PatId, RecordFieldPat}, | 7 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, |
8 | path::Path, | 8 | path::Path, |
9 | type_ref::Mutability, | 9 | type_ref::Mutability, |
10 | FieldId, | 10 | FieldId, |
@@ -90,18 +90,7 @@ impl<'a> InferenceContext<'a> { | |||
90 | ) -> Ty { | 90 | ) -> Ty { |
91 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 91 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
92 | 92 | ||
93 | let is_non_ref_pat = match &body[pat] { | 93 | if is_non_ref_pat(&body, pat) { |
94 | Pat::Tuple { .. } | ||
95 | | Pat::Or(..) | ||
96 | | Pat::TupleStruct { .. } | ||
97 | | Pat::Record { .. } | ||
98 | | Pat::Range { .. } | ||
99 | | Pat::Slice { .. } => true, | ||
100 | // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented. | ||
101 | Pat::Path(..) | Pat::Lit(..) => true, | ||
102 | Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false, | ||
103 | }; | ||
104 | if is_non_ref_pat { | ||
105 | while let Some((inner, mutability)) = expected.as_reference() { | 94 | while let Some((inner, mutability)) = expected.as_reference() { |
106 | expected = inner; | 95 | expected = inner; |
107 | default_bm = match default_bm { | 96 | default_bm = match default_bm { |
@@ -227,3 +216,21 @@ impl<'a> InferenceContext<'a> { | |||
227 | ty | 216 | ty |
228 | } | 217 | } |
229 | } | 218 | } |
219 | |||
220 | fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool { | ||
221 | match &body[pat] { | ||
222 | Pat::Tuple { .. } | ||
223 | | Pat::TupleStruct { .. } | ||
224 | | Pat::Record { .. } | ||
225 | | Pat::Range { .. } | ||
226 | | Pat::Slice { .. } => true, | ||
227 | Pat::Or(pats) => pats.iter().all(|p| is_non_ref_pat(body, *p)), | ||
228 | // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented. | ||
229 | Pat::Path(..) => true, | ||
230 | Pat::Lit(expr) => match body[*expr] { | ||
231 | Expr::Literal(Literal::String(..)) => false, | ||
232 | _ => true, | ||
233 | }, | ||
234 | Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false, | ||
235 | } | ||
236 | } | ||