aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer/pat.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer/pat.rs')
-rw-r--r--crates/ra_hir/src/ty/infer/pat.rs189
1 files changed, 0 insertions, 189 deletions
diff --git a/crates/ra_hir/src/ty/infer/pat.rs b/crates/ra_hir/src/ty/infer/pat.rs
deleted file mode 100644
index a14774607..000000000
--- a/crates/ra_hir/src/ty/infer/pat.rs
+++ /dev/null
@@ -1,189 +0,0 @@
1//! Type inference for patterns.
2
3use std::iter::repeat;
4use std::sync::Arc;
5
6use hir_def::{
7 expr::{BindingAnnotation, Pat, PatId, RecordFieldPat},
8 path::Path,
9 type_ref::Mutability,
10};
11use hir_expand::name::Name;
12use test_utils::tested_by;
13
14use super::{BindingMode, InferenceContext};
15use crate::{
16 db::HirDatabase,
17 ty::{utils::variant_data, Substs, Ty, TypeCtor, TypeWalk},
18};
19
20impl<'a, D: HirDatabase> InferenceContext<'a, D> {
21 fn infer_tuple_struct_pat(
22 &mut self,
23 path: Option<&Path>,
24 subpats: &[PatId],
25 expected: &Ty,
26 default_bm: BindingMode,
27 ) -> Ty {
28 let (ty, def) = self.resolve_variant(path);
29 let var_data = def.map(|it| variant_data(self.db, it));
30 self.unify(&ty, expected);
31
32 let substs = ty.substs().unwrap_or_else(Substs::empty);
33
34 let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default();
35
36 for (i, &subpat) in subpats.iter().enumerate() {
37 let expected_ty = var_data
38 .as_ref()
39 .and_then(|d| d.field(&Name::new_tuple_field(i)))
40 .map_or(Ty::Unknown, |field| field_tys[field].clone())
41 .subst(&substs);
42 let expected_ty = self.normalize_associated_types_in(expected_ty);
43 self.infer_pat(subpat, &expected_ty, default_bm);
44 }
45
46 ty
47 }
48
49 fn infer_record_pat(
50 &mut self,
51 path: Option<&Path>,
52 subpats: &[RecordFieldPat],
53 expected: &Ty,
54 default_bm: BindingMode,
55 id: PatId,
56 ) -> Ty {
57 let (ty, def) = self.resolve_variant(path);
58 let var_data = def.map(|it| variant_data(self.db, it));
59 if let Some(variant) = def {
60 self.write_variant_resolution(id.into(), variant);
61 }
62
63 self.unify(&ty, expected);
64
65 let substs = ty.substs().unwrap_or_else(Substs::empty);
66
67 let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default();
68 for subpat in subpats {
69 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
70 let expected_ty =
71 matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs);
72 let expected_ty = self.normalize_associated_types_in(expected_ty);
73 self.infer_pat(subpat.pat, &expected_ty, default_bm);
74 }
75
76 ty
77 }
78
79 pub(super) fn infer_pat(
80 &mut self,
81 pat: PatId,
82 mut expected: &Ty,
83 mut default_bm: BindingMode,
84 ) -> Ty {
85 let body = Arc::clone(&self.body); // avoid borrow checker problem
86
87 let is_non_ref_pat = match &body[pat] {
88 Pat::Tuple(..)
89 | Pat::TupleStruct { .. }
90 | Pat::Record { .. }
91 | Pat::Range { .. }
92 | Pat::Slice { .. } => true,
93 // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
94 Pat::Path(..) | Pat::Lit(..) => true,
95 Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false,
96 };
97 if is_non_ref_pat {
98 while let Some((inner, mutability)) = expected.as_reference() {
99 expected = inner;
100 default_bm = match default_bm {
101 BindingMode::Move => BindingMode::Ref(mutability),
102 BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared),
103 BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability),
104 }
105 }
106 } else if let Pat::Ref { .. } = &body[pat] {
107 tested_by!(match_ergonomics_ref);
108 // When you encounter a `&pat` pattern, reset to Move.
109 // This is so that `w` is by value: `let (_, &w) = &(1, &2);`
110 default_bm = BindingMode::Move;
111 }
112
113 // Lose mutability.
114 let default_bm = default_bm;
115 let expected = expected;
116
117 let ty = match &body[pat] {
118 Pat::Tuple(ref args) => {
119 let expectations = match expected.as_tuple() {
120 Some(parameters) => &*parameters.0,
121 _ => &[],
122 };
123 let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
124
125 let inner_tys = args
126 .iter()
127 .zip(expectations_iter)
128 .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm))
129 .collect();
130
131 Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys))
132 }
133 Pat::Ref { pat, mutability } => {
134 let expectation = match expected.as_reference() {
135 Some((inner_ty, exp_mut)) => {
136 if *mutability != exp_mut {
137 // FIXME: emit type error?
138 }
139 inner_ty
140 }
141 _ => &Ty::Unknown,
142 };
143 let subty = self.infer_pat(*pat, expectation, default_bm);
144 Ty::apply_one(TypeCtor::Ref(*mutability), subty)
145 }
146 Pat::TupleStruct { path: p, args: subpats } => {
147 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm)
148 }
149 Pat::Record { path: p, args: fields } => {
150 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat)
151 }
152 Pat::Path(path) => {
153 // FIXME use correct resolver for the surrounding expression
154 let resolver = self.resolver.clone();
155 self.infer_path(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown)
156 }
157 Pat::Bind { mode, name: _, subpat } => {
158 let mode = if mode == &BindingAnnotation::Unannotated {
159 default_bm
160 } else {
161 BindingMode::convert(*mode)
162 };
163 let inner_ty = if let Some(subpat) = subpat {
164 self.infer_pat(*subpat, expected, default_bm)
165 } else {
166 expected.clone()
167 };
168 let inner_ty = self.insert_type_vars_shallow(inner_ty);
169
170 let bound_ty = match mode {
171 BindingMode::Ref(mutability) => {
172 Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone())
173 }
174 BindingMode::Move => inner_ty.clone(),
175 };
176 let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty);
177 self.write_pat_ty(pat, bound_ty);
178 return inner_ty;
179 }
180 _ => Ty::Unknown,
181 };
182 // use a new type variable if we got Ty::Unknown here
183 let ty = self.insert_type_vars_shallow(ty);
184 self.unify(&ty, expected);
185 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
186 self.write_pat_ty(pat, ty.clone());
187 ty
188 }
189}