diff options
-rw-r--r-- | crates/ra_hir/src/ty.rs | 34 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 4 |
3 files changed, 33 insertions, 27 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 2ea3b341f..e659f903c 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -89,13 +89,13 @@ pub enum Ty { | |||
89 | /// fn foo() -> i32 { 1 } | 89 | /// fn foo() -> i32 { 1 } |
90 | /// let bar: fn() -> i32 = foo; | 90 | /// let bar: fn() -> i32 = foo; |
91 | /// ``` | 91 | /// ``` |
92 | FnPtr(FnSig), | 92 | FnPtr(Substs), |
93 | 93 | ||
94 | /// The never type `!`. | 94 | /// The never type `!`. |
95 | Never, | 95 | Never, |
96 | 96 | ||
97 | /// A tuple type. For example, `(i32, bool)`. | 97 | /// A tuple type. For example, `(i32, bool)`. |
98 | Tuple(Arc<[Ty]>), | 98 | Tuple(Substs), |
99 | 99 | ||
100 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | 100 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} |
101 | Param { | 101 | Param { |
@@ -127,6 +127,10 @@ impl Substs { | |||
127 | Substs(Arc::new([])) | 127 | Substs(Arc::new([])) |
128 | } | 128 | } |
129 | 129 | ||
130 | pub fn iter(&self) -> impl Iterator<Item = &Ty> { | ||
131 | self.0.iter() | ||
132 | } | ||
133 | |||
130 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 134 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
131 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 135 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
132 | let mut v: Vec<_> = self.0.iter().cloned().collect(); | 136 | let mut v: Vec<_> = self.0.iter().cloned().collect(); |
@@ -148,6 +152,11 @@ impl FnSig { | |||
148 | params.push(ret); | 152 | params.push(ret); |
149 | FnSig { params_and_return: params.into() } | 153 | FnSig { params_and_return: params.into() } |
150 | } | 154 | } |
155 | |||
156 | pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig { | ||
157 | FnSig { params_and_return: Arc::clone(&substs.0) } | ||
158 | } | ||
159 | |||
151 | pub fn params(&self) -> &[Ty] { | 160 | pub fn params(&self) -> &[Ty] { |
152 | &self.params_and_return[0..self.params_and_return.len() - 1] | 161 | &self.params_and_return[0..self.params_and_return.len() - 1] |
153 | } | 162 | } |
@@ -168,7 +177,7 @@ impl FnSig { | |||
168 | 177 | ||
169 | impl Ty { | 178 | impl Ty { |
170 | pub fn unit() -> Self { | 179 | pub fn unit() -> Self { |
171 | Ty::Tuple(Arc::new([])) | 180 | Ty::Tuple(Substs::empty()) |
172 | } | 181 | } |
173 | 182 | ||
174 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | 183 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { |
@@ -182,10 +191,9 @@ impl Ty { | |||
182 | } | 191 | } |
183 | } | 192 | } |
184 | Ty::FnPtr(sig) => { | 193 | Ty::FnPtr(sig) => { |
185 | for input in sig.params() { | 194 | for t in sig.iter() { |
186 | input.walk(f); | 195 | t.walk(f); |
187 | } | 196 | } |
188 | sig.ret().walk(f); | ||
189 | } | 197 | } |
190 | Ty::FnDef { substs, .. } => { | 198 | Ty::FnDef { substs, .. } => { |
191 | for t in substs.0.iter() { | 199 | for t in substs.0.iter() { |
@@ -216,12 +224,7 @@ impl Ty { | |||
216 | Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), | 224 | Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), |
217 | Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), | 225 | Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), |
218 | Ty::Tuple(ts) => { | 226 | Ty::Tuple(ts) => { |
219 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 227 | ts.walk_mut(f); |
220 | let mut v: Vec<_> = ts.iter().cloned().collect(); | ||
221 | for t in &mut v { | ||
222 | t.walk_mut(f); | ||
223 | } | ||
224 | *ts = v.into(); | ||
225 | } | 228 | } |
226 | Ty::FnPtr(sig) => { | 229 | Ty::FnPtr(sig) => { |
227 | sig.walk_mut(f); | 230 | sig.walk_mut(f); |
@@ -324,15 +327,16 @@ impl HirDisplay for Ty { | |||
324 | } | 327 | } |
325 | Ty::Never => write!(f, "!")?, | 328 | Ty::Never => write!(f, "!")?, |
326 | Ty::Tuple(ts) => { | 329 | Ty::Tuple(ts) => { |
327 | if ts.len() == 1 { | 330 | if ts.0.len() == 1 { |
328 | write!(f, "({},)", ts[0].display(f.db))?; | 331 | write!(f, "({},)", ts.0[0].display(f.db))?; |
329 | } else { | 332 | } else { |
330 | write!(f, "(")?; | 333 | write!(f, "(")?; |
331 | f.write_joined(&**ts, ", ")?; | 334 | f.write_joined(&*ts.0, ", ")?; |
332 | write!(f, ")")?; | 335 | write!(f, ")")?; |
333 | } | 336 | } |
334 | } | 337 | } |
335 | Ty::FnPtr(sig) => { | 338 | Ty::FnPtr(sig) => { |
339 | let sig = FnSig::from_fn_ptr_substs(sig); | ||
336 | write!(f, "fn(")?; | 340 | write!(f, "fn(")?; |
337 | f.write_joined(sig.params(), ", ")?; | 341 | f.write_joined(sig.params(), ", ")?; |
338 | write!(f, ") -> {}", sig.ret().display(f.db))?; | 342 | write!(f, ") -> {}", sig.ret().display(f.db))?; |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 735cdecb9..69af8fb92 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -38,7 +38,7 @@ use crate::{ | |||
38 | resolve::{Resolver, Resolution}, | 38 | resolve::{Resolver, Resolution}, |
39 | nameres::Namespace | 39 | nameres::Namespace |
40 | }; | 40 | }; |
41 | use super::{Ty, TypableDef, Substs, primitive, op}; | 41 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig}; |
42 | 42 | ||
43 | /// The entry point of type inference. | 43 | /// The entry point of type inference. |
44 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { | 44 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { |
@@ -257,10 +257,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
257 | self.unify_inner(t1, t2, depth + 1) | 257 | self.unify_inner(t1, t2, depth + 1) |
258 | } | 258 | } |
259 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1), | 259 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1), |
260 | (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, | 260 | (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) => self.unify_substs(sig1, sig2, depth + 1), |
261 | (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => { | 261 | (Ty::Tuple(ts1), Ty::Tuple(ts2)) => self.unify_substs(ts1, ts2, depth + 1), |
262 | ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1)) | ||
263 | } | ||
264 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | 262 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) |
265 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | 263 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) |
266 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { | 264 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { |
@@ -632,7 +630,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
632 | let ty = match &body[pat] { | 630 | let ty = match &body[pat] { |
633 | Pat::Tuple(ref args) => { | 631 | Pat::Tuple(ref args) => { |
634 | let expectations = match *expected { | 632 | let expectations = match *expected { |
635 | Ty::Tuple(ref tuple_args) => &**tuple_args, | 633 | Ty::Tuple(ref tuple_args) => &*tuple_args.0, |
636 | _ => &[], | 634 | _ => &[], |
637 | }; | 635 | }; |
638 | let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); | 636 | let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); |
@@ -644,7 +642,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
644 | .collect::<Vec<_>>() | 642 | .collect::<Vec<_>>() |
645 | .into(); | 643 | .into(); |
646 | 644 | ||
647 | Ty::Tuple(inner_tys) | 645 | Ty::Tuple(Substs(inner_tys)) |
648 | } | 646 | } |
649 | Pat::Ref { pat, mutability } => { | 647 | Pat::Ref { pat, mutability } => { |
650 | let expectation = match *expected { | 648 | let expectation = match *expected { |
@@ -789,7 +787,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
789 | Expr::Call { callee, args } => { | 787 | Expr::Call { callee, args } => { |
790 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); | 788 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); |
791 | let (param_tys, ret_ty) = match &callee_ty { | 789 | let (param_tys, ret_ty) = match &callee_ty { |
792 | Ty::FnPtr(sig) => (sig.params().to_vec(), sig.ret().clone()), | 790 | Ty::FnPtr(sig) => { |
791 | let sig = FnSig::from_fn_ptr_substs(sig); | ||
792 | (sig.params().to_vec(), sig.ret().clone()) | ||
793 | } | ||
793 | Ty::FnDef { substs, def, .. } => { | 794 | Ty::FnDef { substs, def, .. } => { |
794 | let sig = self.db.callable_item_signature(*def); | 795 | let sig = self.db.callable_item_signature(*def); |
795 | let ret_ty = sig.ret().clone().subst(&substs); | 796 | let ret_ty = sig.ret().clone().subst(&substs); |
@@ -828,6 +829,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
828 | let method_ty = self.insert_type_vars(method_ty); | 829 | let method_ty = self.insert_type_vars(method_ty); |
829 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | 830 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { |
830 | Ty::FnPtr(sig) => { | 831 | Ty::FnPtr(sig) => { |
832 | let sig = FnSig::from_fn_ptr_substs(sig); | ||
831 | if !sig.params().is_empty() { | 833 | if !sig.params().is_empty() { |
832 | (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) | 834 | (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) |
833 | } else { | 835 | } else { |
@@ -923,7 +925,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
923 | .find_map(|derefed_ty| match derefed_ty { | 925 | .find_map(|derefed_ty| match derefed_ty { |
924 | Ty::Tuple(fields) => { | 926 | Ty::Tuple(fields) => { |
925 | let i = name.to_string().parse::<usize>().ok(); | 927 | let i = name.to_string().parse::<usize>().ok(); |
926 | i.and_then(|i| fields.get(i).cloned()) | 928 | i.and_then(|i| fields.0.get(i).cloned()) |
927 | } | 929 | } |
928 | Ty::Adt { def_id: AdtDef::Struct(s), ref substs, .. } => { | 930 | Ty::Adt { def_id: AdtDef::Struct(s), ref substs, .. } => { |
929 | s.field(self.db, name).map(|field| { | 931 | s.field(self.db, name).map(|field| { |
@@ -1016,7 +1018,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1016 | ty_vec.push(self.infer_expr(*arg, &Expectation::none())); | 1018 | ty_vec.push(self.infer_expr(*arg, &Expectation::none())); |
1017 | } | 1019 | } |
1018 | 1020 | ||
1019 | Ty::Tuple(Arc::from(ty_vec)) | 1021 | Ty::Tuple(Substs(ty_vec.into())) |
1020 | } | 1022 | } |
1021 | Expr::Array { exprs } => { | 1023 | Expr::Array { exprs } => { |
1022 | let elem_ty = match &expected.ty { | 1024 | let elem_ty = match &expected.ty { |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 389a2fc68..20e6273a6 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -30,7 +30,7 @@ impl Ty { | |||
30 | TypeRef::Tuple(inner) => { | 30 | TypeRef::Tuple(inner) => { |
31 | let inner_tys = | 31 | let inner_tys = |
32 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); | 32 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); |
33 | Ty::Tuple(inner_tys.into()) | 33 | Ty::Tuple(Substs(inner_tys.into())) |
34 | } | 34 | } |
35 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), | 35 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), |
36 | TypeRef::RawPtr(inner, mutability) => { | 36 | TypeRef::RawPtr(inner, mutability) => { |
@@ -53,7 +53,7 @@ impl Ty { | |||
53 | TypeRef::Fn(params) => { | 53 | TypeRef::Fn(params) => { |
54 | let inner_tys = | 54 | let inner_tys = |
55 | params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); | 55 | params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); |
56 | let sig = FnSig { params_and_return: inner_tys.into() }; | 56 | let sig = Substs(inner_tys.into()); |
57 | Ty::FnPtr(sig) | 57 | Ty::FnPtr(sig) |
58 | } | 58 | } |
59 | TypeRef::Error => Ty::Unknown, | 59 | TypeRef::Error => Ty::Unknown, |