From bc7752e5279f274887cd92ac76779f227264ae13 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 16 Mar 2019 18:14:41 +0100 Subject: [PATCH] Represent FnPtr and Tuple using Substs --- crates/ra_hir/src/ty.rs | 34 +++++++++++++++++++--------------- crates/ra_hir/src/ty/infer.rs | 22 ++++++++++++---------- 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 2ea3b341fc6..e659f903c40 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -89,13 +89,13 @@ pub enum Ty { /// fn foo() -> i32 { 1 } /// let bar: fn() -> i32 = foo; /// ``` - FnPtr(FnSig), + FnPtr(Substs), /// The never type `!`. Never, /// A tuple type. For example, `(i32, bool)`. - Tuple(Arc<[Ty]>), + Tuple(Substs), /// A type parameter; for example, `T` in `fn f(x: T) {} Param { @@ -127,6 +127,10 @@ impl Substs { Substs(Arc::new([])) } + pub fn iter(&self) -> impl Iterator { + self.0.iter() + } + pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { // Without an Arc::make_mut_slice, we can't avoid the clone here: let mut v: Vec<_> = self.0.iter().cloned().collect(); @@ -148,6 +152,11 @@ impl FnSig { params.push(ret); FnSig { params_and_return: params.into() } } + + pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig { + FnSig { params_and_return: Arc::clone(&substs.0) } + } + pub fn params(&self) -> &[Ty] { &self.params_and_return[0..self.params_and_return.len() - 1] } @@ -168,7 +177,7 @@ impl FnSig { impl Ty { pub fn unit() -> Self { - Ty::Tuple(Arc::new([])) + Ty::Tuple(Substs::empty()) } pub fn walk(&self, f: &mut impl FnMut(&Ty)) { @@ -182,10 +191,9 @@ impl Ty { } } Ty::FnPtr(sig) => { - for input in sig.params() { - input.walk(f); + for t in sig.iter() { + t.walk(f); } - sig.ret().walk(f); } Ty::FnDef { substs, .. } => { for t in substs.0.iter() { @@ -216,12 +224,7 @@ impl Ty { Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), Ty::Tuple(ts) => { - // Without an Arc::make_mut_slice, we can't avoid the clone here: - let mut v: Vec<_> = ts.iter().cloned().collect(); - for t in &mut v { - t.walk_mut(f); - } - *ts = v.into(); + ts.walk_mut(f); } Ty::FnPtr(sig) => { sig.walk_mut(f); @@ -324,15 +327,16 @@ impl HirDisplay for Ty { } Ty::Never => write!(f, "!")?, Ty::Tuple(ts) => { - if ts.len() == 1 { - write!(f, "({},)", ts[0].display(f.db))?; + if ts.0.len() == 1 { + write!(f, "({},)", ts.0[0].display(f.db))?; } else { write!(f, "(")?; - f.write_joined(&**ts, ", ")?; + f.write_joined(&*ts.0, ", ")?; write!(f, ")")?; } } Ty::FnPtr(sig) => { + let sig = FnSig::from_fn_ptr_substs(sig); write!(f, "fn(")?; f.write_joined(sig.params(), ", ")?; 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 735cdecb910..69af8fb923a 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -38,7 +38,7 @@ use crate::{ resolve::{Resolver, Resolution}, nameres::Namespace }; -use super::{Ty, TypableDef, Substs, primitive, op}; +use super::{Ty, TypableDef, Substs, primitive, op, FnSig}; /// The entry point of type inference. pub fn infer(db: &impl HirDatabase, func: Function) -> Arc { @@ -257,10 +257,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.unify_inner(t1, t2, depth + 1) } (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1), - (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, - (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => { - ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1)) - } + (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) => self.unify_substs(sig1, sig2, depth + 1), + (Ty::Tuple(ts1), Ty::Tuple(ts2)) => self.unify_substs(ts1, ts2, depth + 1), (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { @@ -632,7 +630,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = match &body[pat] { Pat::Tuple(ref args) => { let expectations = match *expected { - Ty::Tuple(ref tuple_args) => &**tuple_args, + Ty::Tuple(ref tuple_args) => &*tuple_args.0, _ => &[], }; let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); @@ -644,7 +642,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .collect::>() .into(); - Ty::Tuple(inner_tys) + Ty::Tuple(Substs(inner_tys)) } Pat::Ref { pat, mutability } => { let expectation = match *expected { @@ -789,7 +787,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::Call { callee, args } => { let callee_ty = self.infer_expr(*callee, &Expectation::none()); let (param_tys, ret_ty) = match &callee_ty { - Ty::FnPtr(sig) => (sig.params().to_vec(), sig.ret().clone()), + Ty::FnPtr(sig) => { + let sig = FnSig::from_fn_ptr_substs(sig); + (sig.params().to_vec(), sig.ret().clone()) + } Ty::FnDef { substs, def, .. } => { let sig = self.db.callable_item_signature(*def); let ret_ty = sig.ret().clone().subst(&substs); @@ -828,6 +829,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let method_ty = self.insert_type_vars(method_ty); let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { Ty::FnPtr(sig) => { + let sig = FnSig::from_fn_ptr_substs(sig); if !sig.params().is_empty() { (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) } else { @@ -923,7 +925,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .find_map(|derefed_ty| match derefed_ty { Ty::Tuple(fields) => { let i = name.to_string().parse::().ok(); - i.and_then(|i| fields.get(i).cloned()) + i.and_then(|i| fields.0.get(i).cloned()) } Ty::Adt { def_id: AdtDef::Struct(s), ref substs, .. } => { s.field(self.db, name).map(|field| { @@ -1016,7 +1018,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty_vec.push(self.infer_expr(*arg, &Expectation::none())); } - Ty::Tuple(Arc::from(ty_vec)) + Ty::Tuple(Substs(ty_vec.into())) } Expr::Array { exprs } => { 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 389a2fc68a5..20e6273a6ea 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -30,7 +30,7 @@ impl Ty { TypeRef::Tuple(inner) => { let inner_tys = inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::>(); - Ty::Tuple(inner_tys.into()) + Ty::Tuple(Substs(inner_tys.into())) } TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), TypeRef::RawPtr(inner, mutability) => { @@ -53,7 +53,7 @@ impl Ty { TypeRef::Fn(params) => { let inner_tys = params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::>(); - let sig = FnSig { params_and_return: inner_tys.into() }; + let sig = Substs(inner_tys.into()); Ty::FnPtr(sig) } TypeRef::Error => Ty::Unknown,