aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ty.rs34
-rw-r--r--crates/ra_hir/src/ty/infer.rs22
-rw-r--r--crates/ra_hir/src/ty/lower.rs4
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
169impl Ty { 178impl 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};
41use super::{Ty, TypableDef, Substs, primitive, op}; 41use super::{Ty, TypableDef, Substs, primitive, op, FnSig};
42 42
43/// The entry point of type inference. 43/// The entry point of type inference.
44pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { 44pub 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,