From bc7752e5279f274887cd92ac76779f227264ae13 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 16 Mar 2019 18:14:41 +0100 Subject: 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 2ea3b341f..e659f903c 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 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::{ 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 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 { 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, -- cgit v1.2.3 From 7a8ba535422a4e3d2b649acde75b5c400ef5e7c6 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 17 Mar 2019 18:20:51 +0100 Subject: Add Ty::Apply --- crates/ra_hir/src/ty.rs | 178 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index e659f903c..e63775f03 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -20,11 +20,84 @@ pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, ca pub(crate) use infer::{infer, InferenceResult, InferTy}; use display::{HirDisplay, HirFormatter}; +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum TypeName { + /// The primitive boolean type. Written as `bool`. + Bool, + + /// The primitive character type; holds a Unicode scalar value + /// (a non-surrogate code point). Written as `char`. + Char, + + /// A primitive integer type. For example, `i32`. + Int(primitive::UncertainIntTy), + + /// A primitive floating-point type. For example, `f64`. + Float(primitive::UncertainFloatTy), + + /// Structures, enumerations and unions. + Adt(AdtDef), + + /// The pointee of a string slice. Written as `str`. + Str, + + /// The pointee of an array slice. Written as `[T]`. + Slice, + + /// An array with the given length. Written as `[T; n]`. + Array, + + /// A raw pointer. Written as `*mut T` or `*const T` + RawPtr(Mutability), + + /// A reference; a pointer with an associated lifetime. Written as + /// `&'a mut T` or `&'a T`. + Ref(Mutability), + + /// The anonymous type of a function declaration/definition. Each + /// function has a unique type, which is output (for a function + /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. + /// + /// This includes tuple struct / enum variant constructors as well. + /// + /// For example the type of `bar` here: + /// + /// ```rust + /// fn foo() -> i32 { 1 } + /// let bar = foo; // bar: fn() -> i32 {foo} + /// ``` + FnDef(CallableDef), + + /// A pointer to a function. Written as `fn() -> i32`. + /// + /// For example the type of `bar` here: + /// + /// ```rust + /// fn foo() -> i32 { 1 } + /// let bar: fn() -> i32 = foo; + /// ``` + FnPtr, + + /// The never type `!`. + Never, + + /// A tuple type. For example, `(i32, bool)`. + Tuple, +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ApplicationTy { + pub name: TypeName, + pub parameters: Substs, +} + /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). /// /// This should be cheap to clone. #[derive(Clone, PartialEq, Eq, Debug)] pub enum Ty { + Apply(ApplicationTy), + /// The primitive boolean type. Written as `bool`. Bool, @@ -139,6 +212,13 @@ impl Substs { } self.0 = v.into(); } + + pub fn as_single(&self) -> &Ty { + if self.0.len() != 1 { + panic!("expected substs of len 1, got {:?}", self); + } + &self.0[0] + } } /// A function signature. @@ -176,12 +256,20 @@ impl FnSig { } impl Ty { + pub fn apply(name: TypeName, parameters: Substs) -> Ty { + Ty::Apply(ApplicationTy { name, parameters }) + } pub fn unit() -> Self { - Ty::Tuple(Substs::empty()) + Ty::apply(TypeName::Tuple, Substs::empty()) } pub fn walk(&self, f: &mut impl FnMut(&Ty)) { match self { + Ty::Apply(a_ty) => { + for t in a_ty.parameters.iter() { + t.walk(f); + } + } Ty::Slice(t) | Ty::Array(t) => t.walk(f), Ty::RawPtr(t, _) => t.walk(f), Ty::Ref(t, _) => t.walk(f), @@ -220,6 +308,9 @@ impl Ty { fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { match self { + Ty::Apply(a_ty) => { + a_ty.parameters.walk_mut(f); + } Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f), Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), @@ -258,6 +349,11 @@ impl Ty { fn builtin_deref(&self) -> Option { match self { + Ty::Apply(a_ty) => match a_ty.name { + TypeName::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())), + TypeName::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())), + _ => None, + }, Ty::Ref(t, _) => Some(Ty::clone(t)), Ty::RawPtr(t, _) => Some(Ty::clone(t)), _ => None, @@ -270,6 +366,9 @@ impl Ty { /// `Option` afterwards.) pub fn apply_substs(self, substs: Substs) -> Ty { match self { + Ty::Apply(ApplicationTy { name, .. }) => { + Ty::Apply(ApplicationTy { name, parameters: substs }) + } Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs }, Ty::FnDef { def, .. } => Ty::FnDef { def, substs }, _ => self, @@ -296,6 +395,7 @@ impl Ty { /// or function); so if `self` is `Option`, this returns the `u32`. fn substs(&self) -> Option { match self { + Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()), Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()), _ => None, } @@ -308,9 +408,85 @@ impl HirDisplay for &Ty { } } +impl HirDisplay for ApplicationTy { + fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { + match self.name { + TypeName::Bool => write!(f, "bool")?, + TypeName::Char => write!(f, "char")?, + TypeName::Int(t) => write!(f, "{}", t)?, + TypeName::Float(t) => write!(f, "{}", t)?, + TypeName::Str => write!(f, "str")?, + TypeName::Slice | TypeName::Array => { + let t = self.parameters.as_single(); + write!(f, "[{}]", t.display(f.db))?; + } + TypeName::RawPtr(m) => { + let t = self.parameters.as_single(); + write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?; + } + TypeName::Ref(m) => { + let t = self.parameters.as_single(); + write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?; + } + TypeName::Never => write!(f, "!")?, + TypeName::Tuple => { + let ts = &self.parameters; + if ts.0.len() == 1 { + write!(f, "({},)", ts.0[0].display(f.db))?; + } else { + write!(f, "(")?; + f.write_joined(&*ts.0, ", ")?; + write!(f, ")")?; + } + } + TypeName::FnPtr => { + let sig = FnSig::from_fn_ptr_substs(&self.parameters); + write!(f, "fn(")?; + f.write_joined(sig.params(), ", ")?; + write!(f, ") -> {}", sig.ret().display(f.db))?; + } + TypeName::FnDef(def) => { + let sig = f.db.callable_item_signature(def); + let name = match def { + CallableDef::Function(ff) => ff.name(f.db), + CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing), + CallableDef::EnumVariant(e) => e.name(f.db).unwrap_or_else(Name::missing), + }; + match def { + CallableDef::Function(_) => write!(f, "fn {}", name)?, + CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?, + } + if self.parameters.0.len() > 0 { + write!(f, "<")?; + f.write_joined(&*self.parameters.0, ", ")?; + write!(f, ">")?; + } + write!(f, "(")?; + f.write_joined(sig.params(), ", ")?; + write!(f, ") -> {}", sig.ret().display(f.db))?; + } + TypeName::Adt(def_id) => { + let name = match def_id { + AdtDef::Struct(s) => s.name(f.db), + AdtDef::Enum(e) => e.name(f.db), + } + .unwrap_or_else(Name::missing); + write!(f, "{}", name)?; + if self.parameters.0.len() > 0 { + write!(f, "<")?; + f.write_joined(&*self.parameters.0, ", ")?; + write!(f, ">")?; + } + } + } + Ok(()) + } +} + impl HirDisplay for Ty { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { match self { + Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, Ty::Bool => write!(f, "bool")?, Ty::Char => write!(f, "char")?, Ty::Int(t) => write!(f, "{}", t)?, -- cgit v1.2.3 From 8a5fbf471305894094726834f7701747fce9c961 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 17 Mar 2019 19:37:09 +0100 Subject: Remove the old variants replaced by Ty::Apply --- crates/ra_assists/src/fill_match_arms.rs | 14 +- crates/ra_assists/src/fill_struct_fields.rs | 6 +- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/ty.rs | 238 ++++--------------- crates/ra_hir/src/ty/infer.rs | 264 ++++++++++++--------- crates/ra_hir/src/ty/lower.rs | 38 ++- crates/ra_hir/src/ty/method_resolution.rs | 11 +- crates/ra_hir/src/ty/op.rs | 33 ++- crates/ra_ide_api/src/completion/complete_dot.rs | 27 +-- .../src/completion/complete_struct_literal.rs | 6 +- crates/ra_ide_api/src/goto_definition.rs | 14 +- crates/ra_ide_api/src/hover.rs | 17 +- 12 files changed, 266 insertions(+), 404 deletions(-) diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs index 6a22b0af5..da67ab667 100644 --- a/crates/ra_assists/src/fill_match_arms.rs +++ b/crates/ra_assists/src/fill_match_arms.rs @@ -1,7 +1,7 @@ use std::fmt::Write; use hir::{ - AdtDef, Ty, FieldSource, source_binder, + AdtDef, FieldSource, source_binder, db::HirDatabase, }; use ra_syntax::ast::{self, AstNode}; @@ -26,14 +26,10 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx) -> Option e, - Ty::Ref(adt, _) => match *adt { - Ty::Adt { def_id: AdtDef::Enum(e), .. } => e, - _ => return None, - }, - _ => return None, - }; + let enum_def = match_expr_ty.autoderef(ctx.db).find_map(|ty| match ty.as_adt() { + Some((AdtDef::Enum(e), _)) => Some(e), + _ => None, + })?; let enum_name = enum_def.name(ctx.db)?; let db = ctx.db; diff --git a/crates/ra_assists/src/fill_struct_fields.rs b/crates/ra_assists/src/fill_struct_fields.rs index 6e61a58fc..c7790dc72 100644 --- a/crates/ra_assists/src/fill_struct_fields.rs +++ b/crates/ra_assists/src/fill_struct_fields.rs @@ -1,6 +1,6 @@ use std::fmt::Write; -use hir::{AdtDef, Ty, db::HirDatabase, source_binder::function_from_child_node}; +use hir::{AdtDef, db::HirDatabase, source_binder::function_from_child_node}; use ra_syntax::ast::{self, AstNode}; @@ -60,8 +60,8 @@ where let source_map = function.body_source_map(self.ctx.db); let node_expr = source_map.node_expr(self.struct_lit.into())?; let struct_lit_ty = infer_result[node_expr].clone(); - let struct_def = match struct_lit_ty { - Ty::Adt { def_id: AdtDef::Struct(s), .. } => s, + let struct_def = match struct_lit_ty.as_adt() { + Some((AdtDef::Struct(s), _)) => s, _ => return None, }; self.struct_fields = struct_def diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 75c977d32..6219402d4 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -53,7 +53,7 @@ pub use self::{ name::Name, ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, nameres::{PerNs, Namespace}, - ty::{Ty, Substs, display::HirDisplay}, + ty::{Ty, ApplicationTy, TypeName, Substs, display::HirDisplay}, impl_block::{ImplBlock, ImplItem}, docs::{Docs, Documentation}, adt::AdtDef, diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index e63775f03..0bb716569 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -20,7 +20,7 @@ pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, ca pub(crate) use infer::{infer, InferenceResult, InferTy}; use display::{HirDisplay, HirFormatter}; -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum TypeName { /// The primitive boolean type. Written as `bool`. Bool, @@ -96,80 +96,11 @@ pub struct ApplicationTy { /// This should be cheap to clone. #[derive(Clone, PartialEq, Eq, Debug)] pub enum Ty { + /// A nominal type with (maybe 0) type parameters. This might be a primitive + /// type like `bool`, a struct, tuple, function pointer, reference or + /// several other things. Apply(ApplicationTy), - /// The primitive boolean type. Written as `bool`. - Bool, - - /// The primitive character type; holds a Unicode scalar value - /// (a non-surrogate code point). Written as `char`. - Char, - - /// A primitive integer type. For example, `i32`. - Int(primitive::UncertainIntTy), - - /// A primitive floating-point type. For example, `f64`. - Float(primitive::UncertainFloatTy), - - /// Structures, enumerations and unions. - Adt { - /// The definition of the struct/enum. - def_id: AdtDef, - /// Substitutions for the generic parameters of the type. - substs: Substs, - }, - - /// The pointee of a string slice. Written as `str`. - Str, - - /// The pointee of an array slice. Written as `[T]`. - Slice(Arc), - - /// An array with the given length. Written as `[T; n]`. - Array(Arc), - - /// A raw pointer. Written as `*mut T` or `*const T` - RawPtr(Arc, Mutability), - - /// A reference; a pointer with an associated lifetime. Written as - /// `&'a mut T` or `&'a T`. - Ref(Arc, Mutability), - - /// The anonymous type of a function declaration/definition. Each - /// function has a unique type, which is output (for a function - /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. - /// - /// This includes tuple struct / enum variant constructors as well. - /// - /// For example the type of `bar` here: - /// - /// ```rust - /// fn foo() -> i32 { 1 } - /// let bar = foo; // bar: fn() -> i32 {foo} - /// ``` - FnDef { - /// The definition of the function / constructor. - def: CallableDef, - /// Substitutions for the generic parameters of the type - substs: Substs, - }, - - /// A pointer to a function. Written as `fn() -> i32`. - /// - /// For example the type of `bar` here: - /// - /// ```rust - /// fn foo() -> i32 { 1 } - /// let bar: fn() -> i32 = foo; - /// ``` - FnPtr(Substs), - - /// The never type `!`. - Never, - - /// A tuple type. For example, `(i32, bool)`. - Tuple(Substs), - /// A type parameter; for example, `T` in `fn f(x: T) {} Param { /// The index of the parameter (starting with parameters from the @@ -200,6 +131,10 @@ impl Substs { Substs(Arc::new([])) } + pub fn single(ty: Ty) -> Substs { + Substs(Arc::new([ty])) + } + pub fn iter(&self) -> impl Iterator { self.0.iter() } @@ -256,6 +191,12 @@ impl FnSig { } impl Ty { + pub fn simple(name: TypeName) -> Ty { + Ty::Apply(ApplicationTy { name, parameters: Substs::empty() }) + } + pub fn apply_one(name: TypeName, param: Ty) -> Ty { + Ty::Apply(ApplicationTy { name, parameters: Substs::single(param) }) + } pub fn apply(name: TypeName, parameters: Substs) -> Ty { Ty::Apply(ApplicationTy { name, parameters }) } @@ -270,38 +211,7 @@ impl Ty { t.walk(f); } } - Ty::Slice(t) | Ty::Array(t) => t.walk(f), - Ty::RawPtr(t, _) => t.walk(f), - Ty::Ref(t, _) => t.walk(f), - Ty::Tuple(ts) => { - for t in ts.iter() { - t.walk(f); - } - } - Ty::FnPtr(sig) => { - for t in sig.iter() { - t.walk(f); - } - } - Ty::FnDef { substs, .. } => { - for t in substs.0.iter() { - t.walk(f); - } - } - Ty::Adt { substs, .. } => { - for t in substs.0.iter() { - t.walk(f); - } - } - Ty::Bool - | Ty::Char - | Ty::Int(_) - | Ty::Float(_) - | Ty::Str - | Ty::Never - | Ty::Param { .. } - | Ty::Infer(_) - | Ty::Unknown => {} + Ty::Param { .. } | Ty::Infer(_) | Ty::Unknown => {} } f(self); } @@ -311,30 +221,7 @@ impl Ty { Ty::Apply(a_ty) => { a_ty.parameters.walk_mut(f); } - Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f), - Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), - Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), - Ty::Tuple(ts) => { - ts.walk_mut(f); - } - Ty::FnPtr(sig) => { - sig.walk_mut(f); - } - Ty::FnDef { substs, .. } => { - substs.walk_mut(f); - } - Ty::Adt { substs, .. } => { - substs.walk_mut(f); - } - Ty::Bool - | Ty::Char - | Ty::Int(_) - | Ty::Float(_) - | Ty::Str - | Ty::Never - | Ty::Param { .. } - | Ty::Infer(_) - | Ty::Unknown => {} + Ty::Param { .. } | Ty::Infer(_) | Ty::Unknown => {} } f(self); } @@ -347,6 +234,31 @@ impl Ty { self } + pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { + match self { + Ty::Apply(ApplicationTy { name: TypeName::Ref(mutability), parameters }) => { + Some((parameters.as_single(), *mutability)) + } + _ => None, + } + } + + pub fn as_adt(&self) -> Option<(AdtDef, &Substs)> { + match self { + Ty::Apply(ApplicationTy { name: TypeName::Adt(adt_def), parameters }) => { + Some((*adt_def, parameters)) + } + _ => None, + } + } + + pub fn as_tuple(&self) -> Option<&Substs> { + match self { + Ty::Apply(ApplicationTy { name: TypeName::Tuple, parameters }) => Some(parameters), + _ => None, + } + } + fn builtin_deref(&self) -> Option { match self { Ty::Apply(a_ty) => match a_ty.name { @@ -354,8 +266,6 @@ impl Ty { TypeName::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())), _ => None, }, - Ty::Ref(t, _) => Some(Ty::clone(t)), - Ty::RawPtr(t, _) => Some(Ty::clone(t)), _ => None, } } @@ -369,8 +279,6 @@ impl Ty { Ty::Apply(ApplicationTy { name, .. }) => { Ty::Apply(ApplicationTy { name, parameters: substs }) } - Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs }, - Ty::FnDef { def, .. } => Ty::FnDef { def, substs }, _ => self, } } @@ -396,7 +304,6 @@ impl Ty { fn substs(&self) -> Option { match self { Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()), - Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()), _ => None, } } @@ -487,69 +394,6 @@ impl HirDisplay for Ty { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { match self { Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, - Ty::Bool => write!(f, "bool")?, - Ty::Char => write!(f, "char")?, - Ty::Int(t) => write!(f, "{}", t)?, - Ty::Float(t) => write!(f, "{}", t)?, - Ty::Str => write!(f, "str")?, - Ty::Slice(t) | Ty::Array(t) => { - write!(f, "[{}]", t.display(f.db))?; - } - Ty::RawPtr(t, m) => { - write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?; - } - Ty::Ref(t, m) => { - write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?; - } - Ty::Never => write!(f, "!")?, - Ty::Tuple(ts) => { - if ts.0.len() == 1 { - write!(f, "({},)", ts.0[0].display(f.db))?; - } else { - write!(f, "(")?; - 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))?; - } - Ty::FnDef { def, substs, .. } => { - let sig = f.db.callable_item_signature(*def); - let name = match def { - CallableDef::Function(ff) => ff.name(f.db), - CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing), - CallableDef::EnumVariant(e) => e.name(f.db).unwrap_or_else(Name::missing), - }; - match def { - CallableDef::Function(_) => write!(f, "fn {}", name)?, - CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?, - } - if substs.0.len() > 0 { - write!(f, "<")?; - f.write_joined(&*substs.0, ", ")?; - write!(f, ">")?; - } - write!(f, "(")?; - f.write_joined(sig.params(), ", ")?; - write!(f, ") -> {}", sig.ret().display(f.db))?; - } - Ty::Adt { def_id, substs, .. } => { - let name = match def_id { - AdtDef::Struct(s) => s.name(f.db), - AdtDef::Enum(e) => e.name(f.db), - } - .unwrap_or_else(Name::missing); - write!(f, "{}", name)?; - if substs.0.len() > 0 { - write!(f, "<")?; - f.write_joined(&*substs.0, ", ")?; - write!(f, ">")?; - } - } Ty::Param { name, .. } => write!(f, "{}", name)?, Ty::Unknown => write!(f, "{{unknown}}")?, Ty::Infer(..) => write!(f, "_")?, diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 69af8fb92..0dafd8cbd 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, FnSig}; +use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeName}; /// The entry point of type inference. pub fn infer(db: &impl HirDatabase, func: Function) -> Arc { @@ -237,28 +237,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { match (&*ty1, &*ty2) { (Ty::Unknown, ..) => true, (.., Ty::Unknown) => true, - (Ty::Int(t1), Ty::Int(t2)) => match (t1, t2) { - (primitive::UncertainIntTy::Unknown, _) - | (_, primitive::UncertainIntTy::Unknown) => true, - _ => t1 == t2, - }, - (Ty::Float(t1), Ty::Float(t2)) => match (t1, t2) { - (primitive::UncertainFloatTy::Unknown, _) - | (_, primitive::UncertainFloatTy::Unknown) => true, - _ => t1 == t2, - }, - (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, - ( - Ty::Adt { def_id: def_id1, substs: substs1, .. }, - Ty::Adt { def_id: def_id2, substs: substs2, .. }, - ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2, depth + 1), - (Ty::Slice(t1), Ty::Slice(t2)) => self.unify_inner(t1, t2, depth + 1), - (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => { - self.unify_inner(t1, t2, depth + 1) + (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.name == a_ty2.name => { + self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, 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)) => 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))) => { @@ -296,8 +277,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { match ty { Ty::Unknown => self.new_type_var(), - Ty::Int(primitive::UncertainIntTy::Unknown) => self.new_integer_var(), - Ty::Float(primitive::UncertainFloatTy::Unknown) => self.new_float_var(), + Ty::Apply(ApplicationTy { + name: TypeName::Int(primitive::UncertainIntTy::Unknown), + .. + }) => self.new_integer_var(), + Ty::Apply(ApplicationTy { + name: TypeName::Float(primitive::UncertainFloatTy::Unknown), + .. + }) => self.new_float_var(), _ => ty, } } @@ -608,12 +595,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false, }; if is_non_ref_pat { - while let Ty::Ref(inner, mutability) = expected { + while let Some((inner, mutability)) = expected.as_reference() { expected = inner; default_bm = match default_bm { - BindingMode::Move => BindingMode::Ref(*mutability), + BindingMode::Move => BindingMode::Ref(mutability), BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared), - BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(*mutability), + BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), } } } else if let Pat::Ref { .. } = &body[pat] { @@ -629,8 +616,8 @@ 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.0, + let expectations = match expected.as_tuple() { + Some(parameters) => &*parameters.0, _ => &[], }; let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); @@ -642,20 +629,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .collect::>() .into(); - Ty::Tuple(Substs(inner_tys)) + Ty::apply(TypeName::Tuple, Substs(inner_tys)) } Pat::Ref { pat, mutability } => { - let expectation = match *expected { - Ty::Ref(ref sub_ty, exp_mut) => { + let expectation = match expected.as_reference() { + Some((inner_ty, exp_mut)) => { if *mutability != exp_mut { // TODO: emit type error? } - &**sub_ty + inner_ty } _ => &Ty::Unknown, }; let subty = self.infer_pat(*pat, expectation, default_bm); - Ty::Ref(subty.into(), *mutability) + Ty::apply_one(TypeName::Ref(*mutability), subty.into()) } Pat::TupleStruct { path: ref p, args: ref subpats } => { self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) @@ -682,7 +669,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let inner_ty = self.insert_type_vars_shallow(inner_ty); let bound_ty = match mode { - BindingMode::Ref(mutability) => Ty::Ref(inner_ty.clone().into(), mutability), + BindingMode::Ref(mutability) => { + Ty::apply_one(TypeName::Ref(mutability), inner_ty.clone().into()) + } BindingMode::Move => inner_ty.clone(), }; let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); @@ -736,7 +725,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::Missing => Ty::Unknown, Expr::If { condition, then_branch, else_branch } => { // if let is desugared to match, so this is always simple if - self.infer_expr(*condition, &Expectation::has_type(Ty::Bool)); + self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeName::Bool))); let then_ty = self.infer_expr(*then_branch, expected); match else_branch { Some(else_branch) => { @@ -753,11 +742,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::Loop { body } => { self.infer_expr(*body, &Expectation::has_type(Ty::unit())); // TODO handle break with value - Ty::Never + Ty::simple(TypeName::Never) } Expr::While { condition, body } => { // while let is desugared to a match loop, so this is always simple while - self.infer_expr(*condition, &Expectation::has_type(Ty::Bool)); + self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeName::Bool))); self.infer_expr(*body, &Expectation::has_type(Ty::unit())); Ty::unit() } @@ -787,17 +776,23 @@ 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) => { - 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); - let param_tys = - sig.params().iter().map(|ty| ty.clone().subst(&substs)).collect(); - (param_tys, ret_ty) - } + Ty::Apply(a_ty) => match a_ty.name { + TypeName::FnPtr => { + let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); + (sig.params().to_vec(), sig.ret().clone()) + } + TypeName::FnDef(def) => { + let sig = self.db.callable_item_signature(def); + let ret_ty = sig.ret().clone().subst(&a_ty.parameters); + let param_tys = sig + .params() + .iter() + .map(|ty| ty.clone().subst(&a_ty.parameters)) + .collect(); + (param_tys, ret_ty) + } + _ => (Vec::new(), Ty::Unknown), + }, _ => { // not callable // TODO report an error? @@ -828,32 +823,43 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let method_ty = method_ty.apply_substs(substs); 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 { - (Ty::Unknown, Vec::new(), sig.ret().clone()) + Ty::Apply(a_ty) => match a_ty.name { + TypeName::FnPtr => { + let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); + if !sig.params().is_empty() { + ( + sig.params()[0].clone(), + sig.params()[1..].to_vec(), + sig.ret().clone(), + ) + } else { + (Ty::Unknown, Vec::new(), sig.ret().clone()) + } } - } - Ty::FnDef { substs, def, .. } => { - let sig = self.db.callable_item_signature(*def); - let ret_ty = sig.ret().clone().subst(&substs); - - if !sig.params().is_empty() { - let mut params_iter = - sig.params().iter().map(|ty| ty.clone().subst(&substs)); - let receiver_ty = params_iter.next().unwrap(); - (receiver_ty, params_iter.collect(), ret_ty) - } else { - (Ty::Unknown, Vec::new(), ret_ty) + TypeName::FnDef(def) => { + let sig = self.db.callable_item_signature(def); + let ret_ty = sig.ret().clone().subst(&a_ty.parameters); + + if !sig.params().is_empty() { + let mut params_iter = sig + .params() + .iter() + .map(|ty| ty.clone().subst(&a_ty.parameters)); + let receiver_ty = params_iter.next().unwrap(); + (receiver_ty, params_iter.collect(), ret_ty) + } else { + (Ty::Unknown, Vec::new(), ret_ty) + } } - } + _ => (Ty::Unknown, Vec::new(), Ty::Unknown), + }, _ => (Ty::Unknown, Vec::new(), Ty::Unknown), }; // Apply autoref so the below unification works correctly - let actual_receiver_ty = match expected_receiver_ty { - Ty::Ref(_, mutability) => Ty::Ref(Arc::new(derefed_receiver_ty), mutability), + let actual_receiver_ty = match expected_receiver_ty.as_reference() { + Some((_, mutability)) => { + Ty::apply_one(TypeName::Ref(mutability), derefed_receiver_ty) + } _ => derefed_receiver_ty, }; self.unify(&expected_receiver_ty, &actual_receiver_ty); @@ -877,7 +883,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default()); } if let Some(guard_expr) = arm.guard { - self.infer_expr(guard_expr, &Expectation::has_type(Ty::Bool)); + self.infer_expr( + guard_expr, + &Expectation::has_type(Ty::simple(TypeName::Bool)), + ); } self.infer_expr(arm.expr, &expected); } @@ -889,19 +898,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); self.infer_path_expr(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) } - Expr::Continue => Ty::Never, + Expr::Continue => Ty::simple(TypeName::Never), Expr::Break { expr } => { if let Some(expr) = expr { // TODO handle break with value self.infer_expr(*expr, &Expectation::none()); } - Ty::Never + Ty::simple(TypeName::Never) } Expr::Return { expr } => { if let Some(expr) = expr { self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); } - Ty::Never + Ty::simple(TypeName::Never) } Expr::StructLit { path, fields, spread } => { let (ty, def_id) = self.resolve_variant(path.as_ref()); @@ -923,16 +932,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = receiver_ty .autoderef(self.db) .find_map(|derefed_ty| match derefed_ty { - Ty::Tuple(fields) => { - let i = name.to_string().parse::().ok(); - 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| { - self.write_field_resolution(tgt_expr, field); - field.ty(self.db).subst(substs) - }) - } + Ty::Apply(a_ty) => match a_ty.name { + TypeName::Tuple => { + let i = name.to_string().parse::().ok(); + i.and_then(|i| a_ty.parameters.0.get(i).cloned()) + } + TypeName::Adt(AdtDef::Struct(s)) => { + s.field(self.db, name).map(|field| { + self.write_field_resolution(tgt_expr, field); + field.ty(self.db).subst(&a_ty.parameters) + }) + } + _ => None, + }, _ => None, }) .unwrap_or(Ty::Unknown); @@ -949,18 +961,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { cast_ty } Expr::Ref { expr, mutability } => { - let expectation = if let Ty::Ref(ref subty, expected_mutability) = expected.ty { - if expected_mutability == Mutability::Mut && *mutability == Mutability::Shared { - // TODO: throw type error - expected mut reference but found shared ref, - // which cannot be coerced - } - Expectation::has_type((**subty).clone()) - } else { - Expectation::none() - }; + let expectation = + if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() { + if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { + // TODO: throw type error - expected mut reference but found shared ref, + // which cannot be coerced + } + Expectation::has_type(Ty::clone(exp_inner)) + } else { + Expectation::none() + }; // TODO reference coercions etc. let inner_ty = self.infer_expr(*expr, &expectation); - Ty::Ref(Arc::new(inner_ty), *mutability) + Ty::apply_one(TypeName::Ref(*mutability), inner_ty) } Expr::UnaryOp { expr, op } => { let inner_ty = self.infer_expr(*expr, &Expectation::none()); @@ -974,19 +987,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } UnaryOp::Neg => { - match inner_ty { - Ty::Int(primitive::UncertainIntTy::Unknown) - | Ty::Int(primitive::UncertainIntTy::Signed(..)) - | Ty::Infer(InferTy::IntVar(..)) - | Ty::Infer(InferTy::FloatVar(..)) - | Ty::Float(..) => inner_ty, + match &inner_ty { + Ty::Apply(a_ty) => match a_ty.name { + TypeName::Int(primitive::UncertainIntTy::Unknown) + | TypeName::Int(primitive::UncertainIntTy::Signed(..)) + | TypeName::Float(..) => inner_ty, + _ => Ty::Unknown, + }, + Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => { + inner_ty + } // TODO: resolve ops::Neg trait _ => Ty::Unknown, } } UnaryOp::Not => { - match inner_ty { - Ty::Bool | Ty::Int(_) | Ty::Infer(InferTy::IntVar(..)) => inner_ty, + match &inner_ty { + Ty::Apply(a_ty) => match a_ty.name { + TypeName::Bool | TypeName::Int(_) => inner_ty, + _ => Ty::Unknown, + }, + Ty::Infer(InferTy::IntVar(..)) => inner_ty, // TODO: resolve ops::Not trait for inner_ty _ => Ty::Unknown, } @@ -997,7 +1018,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Some(op) => { let lhs_expectation = match op { BinaryOp::BooleanAnd | BinaryOp::BooleanOr => { - Expectation::has_type(Ty::Bool) + Expectation::has_type(Ty::simple(TypeName::Bool)) } _ => Expectation::none(), }; @@ -1018,11 +1039,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty_vec.push(self.infer_expr(*arg, &Expectation::none())); } - Ty::Tuple(Substs(ty_vec.into())) + Ty::apply(TypeName::Tuple, Substs(ty_vec.into())) } Expr::Array { exprs } => { let elem_ty = match &expected.ty { - Ty::Slice(inner) | Ty::Array(inner) => Ty::clone(&inner), + Ty::Apply(a_ty) => match a_ty.name { + TypeName::Slice | TypeName::Array => { + Ty::clone(&a_ty.parameters.as_single()) + } + _ => self.new_type_var(), + }, _ => self.new_type_var(), }; @@ -1030,21 +1056,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.infer_expr(*expr, &Expectation::has_type(elem_ty.clone())); } - Ty::Array(Arc::new(elem_ty)) + Ty::apply_one(TypeName::Array, elem_ty) } Expr::Literal(lit) => match lit { - Literal::Bool(..) => Ty::Bool, - Literal::String(..) => Ty::Ref(Arc::new(Ty::Str), Mutability::Shared), + Literal::Bool(..) => Ty::simple(TypeName::Bool), + Literal::String(..) => { + Ty::apply_one(TypeName::Ref(Mutability::Shared), Ty::simple(TypeName::Str)) + } Literal::ByteString(..) => { - let byte_type = Arc::new(Ty::Int(primitive::UncertainIntTy::Unsigned( + let byte_type = Ty::simple(TypeName::Int(primitive::UncertainIntTy::Unsigned( primitive::UintTy::U8, ))); - let slice_type = Arc::new(Ty::Slice(byte_type)); - Ty::Ref(slice_type, Mutability::Shared) + let slice_type = Ty::apply_one(TypeName::Slice, byte_type); + Ty::apply_one(TypeName::Ref(Mutability::Shared), slice_type) } - Literal::Char(..) => Ty::Char, - Literal::Int(_v, ty) => Ty::Int(*ty), - Literal::Float(_v, ty) => Ty::Float(*ty), + Literal::Char(..) => Ty::simple(TypeName::Char), + Literal::Int(_v, ty) => Ty::simple(TypeName::Int(*ty)), + Literal::Float(_v, ty) => Ty::simple(TypeName::Float(*ty)), }, }; // use a new type variable if we got Ty::Unknown here @@ -1180,11 +1208,11 @@ impl InferTy { match self { InferTy::TypeVar(..) => Ty::Unknown, InferTy::IntVar(..) => { - Ty::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32)) - } - InferTy::FloatVar(..) => { - Ty::Float(primitive::UncertainFloatTy::Known(primitive::FloatTy::F64)) + Ty::simple(TypeName::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32))) } + InferTy::FloatVar(..) => Ty::simple(TypeName::Float( + primitive::UncertainFloatTy::Known(primitive::FloatTy::F64), + )), } } } diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 20e6273a6..a346879d8 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -6,8 +6,6 @@ //! //! This usually involves resolving names, collecting generic arguments etc. -use std::sync::Arc; - use crate::{ Function, Struct, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, @@ -21,40 +19,40 @@ use crate::{ generics::GenericParams, adt::VariantDef, }; -use super::{Ty, primitive, FnSig, Substs}; +use super::{Ty, primitive, FnSig, Substs, TypeName}; impl Ty { pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { match type_ref { - TypeRef::Never => Ty::Never, + TypeRef::Never => Ty::simple(TypeName::Never), TypeRef::Tuple(inner) => { let inner_tys = inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::>(); - Ty::Tuple(Substs(inner_tys.into())) + Ty::apply(TypeName::Tuple, Substs(inner_tys.into())) } TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), TypeRef::RawPtr(inner, mutability) => { let inner_ty = Ty::from_hir(db, resolver, inner); - Ty::RawPtr(Arc::new(inner_ty), *mutability) + Ty::apply_one(TypeName::RawPtr(*mutability), inner_ty) } TypeRef::Array(inner) => { let inner_ty = Ty::from_hir(db, resolver, inner); - Ty::Array(Arc::new(inner_ty)) + Ty::apply_one(TypeName::Array, inner_ty) } TypeRef::Slice(inner) => { let inner_ty = Ty::from_hir(db, resolver, inner); - Ty::Slice(Arc::new(inner_ty)) + Ty::apply_one(TypeName::Slice, inner_ty) } TypeRef::Reference(inner, mutability) => { let inner_ty = Ty::from_hir(db, resolver, inner); - Ty::Ref(Arc::new(inner_ty), *mutability) + Ty::apply_one(TypeName::Ref(*mutability), inner_ty) } TypeRef::Placeholder => Ty::Unknown, TypeRef::Fn(params) => { let inner_tys = params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::>(); let sig = Substs(inner_tys.into()); - Ty::FnPtr(sig) + Ty::apply(TypeName::FnPtr, sig) } TypeRef::Error => Ty::Unknown, } @@ -64,14 +62,14 @@ impl Ty { if let Some(name) = path.as_ident() { // TODO handle primitive type names in resolver as well? if let Some(int_ty) = primitive::UncertainIntTy::from_type_name(name) { - return Ty::Int(int_ty); + return Ty::simple(TypeName::Int(int_ty)); } else if let Some(float_ty) = primitive::UncertainFloatTy::from_type_name(name) { - return Ty::Float(float_ty); + return Ty::simple(TypeName::Float(float_ty)); } else if let Some(known) = name.as_known_name() { match known { - KnownName::Bool => return Ty::Bool, - KnownName::Char => return Ty::Char, - KnownName::Str => return Ty::Str, + KnownName::Bool => return Ty::simple(TypeName::Bool), + KnownName::Char => return Ty::simple(TypeName::Char), + KnownName::Str => return Ty::simple(TypeName::Str), _ => {} } } @@ -247,7 +245,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { let generics = def.generic_params(db); let substs = make_substs(&generics); - Ty::FnDef { def: def.into(), substs } + Ty::apply(TypeName::FnDef(def.into()), substs) } /// Build the declared type of a const. @@ -289,7 +287,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { } let generics = def.generic_params(db); let substs = make_substs(&generics); - Ty::FnDef { def: def.into(), substs } + Ty::apply(TypeName::FnDef(def.into()), substs) } fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { @@ -317,7 +315,7 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> } let generics = def.parent_enum(db).generic_params(db); let substs = make_substs(&generics); - Ty::FnDef { def: def.into(), substs } + Ty::apply(TypeName::FnDef(def.into()), substs) } fn make_substs(generics: &GenericParams) -> Substs { @@ -333,12 +331,12 @@ fn make_substs(generics: &GenericParams) -> Substs { fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { let generics = s.generic_params(db); - Ty::Adt { def_id: s.into(), substs: make_substs(&generics) } + Ty::apply(TypeName::Adt(s.into()), make_substs(&generics)) } fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { let generics = s.generic_params(db); - Ty::Adt { def_id: s.into(), substs: make_substs(&generics) } + Ty::apply(TypeName::Adt(s.into()), make_substs(&generics)) } fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 804824868..06bfe85cd 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -10,7 +10,7 @@ use crate::{ HirDatabase, Module, Crate, Name, Function, Trait, ids::TraitId, impl_block::{ImplId, ImplBlock, ImplItem}, - ty::{AdtDef, Ty}, + ty::{Ty, TypeName}, nameres::CrateModuleId, }; @@ -18,7 +18,7 @@ use crate::{ /// This is used as a key for indexing impls. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TyFingerprint { - Adt(AdtDef), // we'll also want to index impls for primitive types etc. + Apply(TypeName), } impl TyFingerprint { @@ -27,7 +27,7 @@ impl TyFingerprint { /// `impl &S`. Hence, this will return `None` for reference types and such. fn for_impl(ty: &Ty) -> Option { match ty { - Ty::Adt { def_id, .. } => Some(TyFingerprint::Adt(*def_id)), + Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.name)), _ => None, } } @@ -111,7 +111,10 @@ impl CrateImplBlocks { fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option { match ty { - Ty::Adt { def_id, .. } => def_id.krate(db), + Ty::Apply(a_ty) => match a_ty.name { + TypeName::Adt(def_id) => def_id.krate(db), + _ => None, + }, _ => None, } } diff --git a/crates/ra_hir/src/ty/op.rs b/crates/ra_hir/src/ty/op.rs index 8703cf236..f581004d2 100644 --- a/crates/ra_hir/src/ty/op.rs +++ b/crates/ra_hir/src/ty/op.rs @@ -1,5 +1,5 @@ -use crate::expr::BinaryOp; -use super::{Ty, InferTy}; +use crate::{ ty::ApplicationTy, expr::BinaryOp}; +use super::{Ty, TypeName, InferTy}; pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { match op { @@ -10,7 +10,7 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | BinaryOp::LesserEqualTest | BinaryOp::GreaterEqualTest | BinaryOp::LesserTest - | BinaryOp::GreaterTest => Ty::Bool, + | BinaryOp::GreaterTest => Ty::simple(TypeName::Bool), BinaryOp::Assignment | BinaryOp::AddAssign | BinaryOp::SubAssign @@ -32,10 +32,11 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | BinaryOp::BitwiseAnd | BinaryOp::BitwiseOr | BinaryOp::BitwiseXor => match rhs_ty { - Ty::Int(..) - | Ty::Float(..) - | Ty::Infer(InferTy::IntVar(..)) - | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, + Ty::Apply(ApplicationTy { name, .. }) => match name { + TypeName::Int(..) | TypeName::Float(..) => rhs_ty, + _ => Ty::Unknown, + }, + Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, _ => Ty::Unknown, }, BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, @@ -44,9 +45,17 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { match op { - BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool, + BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::simple(TypeName::Bool), BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { - Ty::Int(..) | Ty::Float(..) | Ty::Str | Ty::Char | Ty::Bool => lhs_ty, + Ty::Apply(ApplicationTy { name, .. }) => match name { + TypeName::Int(..) + | TypeName::Float(..) + | TypeName::Str + | TypeName::Char + | TypeName::Bool => lhs_ty, + _ => Ty::Unknown, + }, + Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, _ => Ty::Unknown, }, BinaryOp::LesserEqualTest @@ -73,7 +82,11 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | BinaryOp::BitwiseAnd | BinaryOp::BitwiseOr | BinaryOp::BitwiseXor => match lhs_ty { - Ty::Int(..) | Ty::Float(..) => lhs_ty, + Ty::Apply(ApplicationTy { name, .. }) => match name { + TypeName::Int(..) | TypeName::Float(..) => lhs_ty, + _ => Ty::Unknown, + }, + Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, _ => Ty::Unknown, }, _ => Ty::Unknown, diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 94c66be31..dc5206a64 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -1,4 +1,4 @@ -use hir::{Ty, AdtDef}; +use hir::{Ty, AdtDef, TypeName}; use crate::completion::{CompletionContext, Completions}; @@ -24,23 +24,20 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { for receiver in receiver.autoderef(ctx.db) { match receiver { - Ty::Adt { def_id, ref substs, .. } => { - match def_id { - AdtDef::Struct(s) => { - for field in s.fields(ctx.db) { - acc.add_field(ctx, field, substs); - } + Ty::Apply(a_ty) => match a_ty.name { + TypeName::Adt(AdtDef::Struct(s)) => { + for field in s.fields(ctx.db) { + acc.add_field(ctx, field, &a_ty.parameters); } - - // TODO unions - AdtDef::Enum(_) => (), } - } - Ty::Tuple(fields) => { - for (i, ty) in fields.iter().enumerate() { - acc.add_pos_field(ctx, i, ty); + // TODO unions + TypeName::Tuple => { + for (i, ty) in a_ty.parameters.iter().enumerate() { + acc.add_pos_field(ctx, i, ty); + } } - } + _ => {} + }, _ => {} }; } diff --git a/crates/ra_ide_api/src/completion/complete_struct_literal.rs b/crates/ra_ide_api/src/completion/complete_struct_literal.rs index 6bef9624e..b75526282 100644 --- a/crates/ra_ide_api/src/completion/complete_struct_literal.rs +++ b/crates/ra_ide_api/src/completion/complete_struct_literal.rs @@ -1,4 +1,4 @@ -use hir::{Ty, AdtDef}; +use hir::AdtDef; use crate::completion::{CompletionContext, Completions}; @@ -15,8 +15,8 @@ pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionCon None => return, }; let ty = infer_result[expr].clone(); - let (adt, substs) = match ty { - Ty::Adt { def_id, ref substs, .. } => (def_id, substs), + let (adt, substs) = match ty.as_adt() { + Some(res) => res, _ => return, }; match adt { diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index d4e10b69c..f94487d94 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -87,14 +87,12 @@ pub(crate) fn reference_definition( if let Some(expr) = struct_lit.and_then(|lit| source_map.node_expr(lit.into())) { let ty = infer_result[expr].clone(); - if let hir::Ty::Adt { def_id, .. } = ty { - if let hir::AdtDef::Struct(s) = def_id { - let hir_path = hir::Path::from_name_ref(name_ref); - let hir_name = hir_path.as_ident().unwrap(); + if let Some((hir::AdtDef::Struct(s), _)) = ty.as_adt() { + let hir_path = hir::Path::from_name_ref(name_ref); + let hir_name = hir_path.as_ident().unwrap(); - if let Some(field) = s.field(db, hir_name) { - return Exact(NavigationTarget::from_field(db, field)); - } + if let Some(field) = s.field(db, hir_name) { + return Exact(NavigationTarget::from_field(db, field)); } } } @@ -124,7 +122,7 @@ pub(crate) fn reference_definition( Some(Resolution::SelfType(impl_block)) => { let ty = impl_block.target_ty(db); - if let hir::Ty::Adt { def_id, .. } = ty { + if let Some((def_id, _)) = ty.as_adt() { return Exact(NavigationTarget::from_adt_def(db, def_id)); } } diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index f6a83dd93..f6443580d 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -517,23 +517,8 @@ The Some variant assert_eq!("u32", &type_name); } - // FIXME: improve type_of to make this work #[test] - fn test_type_of_for_expr_1() { - let (analysis, range) = single_file_with_range( - " - fn main() { - let foo = <|>1 + foo_test<|>; - } - ", - ); - - let type_name = analysis.type_of(range).unwrap().unwrap(); - assert_eq!("{unknown}", &type_name); - } - - #[test] - fn test_type_of_for_expr_2() { + fn test_type_of_for_expr() { let (analysis, range) = single_file_with_range( " fn main() { -- cgit v1.2.3 From f10f5a81b326d161d9ed1fba263de972b89de2bf Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 21 Mar 2019 22:20:03 +0100 Subject: TypeName => TypeCtor --- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/ty.rs | 48 +++++++-------- crates/ra_hir/src/ty/infer.rs | 78 ++++++++++++------------ crates/ra_hir/src/ty/lower.rs | 36 +++++------ crates/ra_hir/src/ty/method_resolution.rs | 6 +- crates/ra_hir/src/ty/op.rs | 20 +++--- crates/ra_ide_api/src/completion/complete_dot.rs | 6 +- 7 files changed, 98 insertions(+), 98 deletions(-) diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 6219402d4..5926b5758 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -53,7 +53,7 @@ pub use self::{ name::Name, ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, nameres::{PerNs, Namespace}, - ty::{Ty, ApplicationTy, TypeName, Substs, display::HirDisplay}, + ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, impl_block::{ImplBlock, ImplItem}, docs::{Docs, Documentation}, adt::AdtDef, diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 0bb716569..1d9e7b76c 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -21,7 +21,7 @@ pub(crate) use infer::{infer, InferenceResult, InferTy}; use display::{HirDisplay, HirFormatter}; #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] -pub enum TypeName { +pub enum TypeCtor { /// The primitive boolean type. Written as `bool`. Bool, @@ -87,7 +87,7 @@ pub enum TypeName { #[derive(Clone, PartialEq, Eq, Debug)] pub struct ApplicationTy { - pub name: TypeName, + pub name: TypeCtor, pub parameters: Substs, } @@ -191,17 +191,17 @@ impl FnSig { } impl Ty { - pub fn simple(name: TypeName) -> Ty { + pub fn simple(name: TypeCtor) -> Ty { Ty::Apply(ApplicationTy { name, parameters: Substs::empty() }) } - pub fn apply_one(name: TypeName, param: Ty) -> Ty { + pub fn apply_one(name: TypeCtor, param: Ty) -> Ty { Ty::Apply(ApplicationTy { name, parameters: Substs::single(param) }) } - pub fn apply(name: TypeName, parameters: Substs) -> Ty { + pub fn apply(name: TypeCtor, parameters: Substs) -> Ty { Ty::Apply(ApplicationTy { name, parameters }) } pub fn unit() -> Self { - Ty::apply(TypeName::Tuple, Substs::empty()) + Ty::apply(TypeCtor::Tuple, Substs::empty()) } pub fn walk(&self, f: &mut impl FnMut(&Ty)) { @@ -236,7 +236,7 @@ impl Ty { pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { match self { - Ty::Apply(ApplicationTy { name: TypeName::Ref(mutability), parameters }) => { + Ty::Apply(ApplicationTy { name: TypeCtor::Ref(mutability), parameters }) => { Some((parameters.as_single(), *mutability)) } _ => None, @@ -245,7 +245,7 @@ impl Ty { pub fn as_adt(&self) -> Option<(AdtDef, &Substs)> { match self { - Ty::Apply(ApplicationTy { name: TypeName::Adt(adt_def), parameters }) => { + Ty::Apply(ApplicationTy { name: TypeCtor::Adt(adt_def), parameters }) => { Some((*adt_def, parameters)) } _ => None, @@ -254,7 +254,7 @@ impl Ty { pub fn as_tuple(&self) -> Option<&Substs> { match self { - Ty::Apply(ApplicationTy { name: TypeName::Tuple, parameters }) => Some(parameters), + Ty::Apply(ApplicationTy { name: TypeCtor::Tuple, parameters }) => Some(parameters), _ => None, } } @@ -262,8 +262,8 @@ impl Ty { fn builtin_deref(&self) -> Option { match self { Ty::Apply(a_ty) => match a_ty.name { - TypeName::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())), - TypeName::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())), + TypeCtor::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())), + TypeCtor::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())), _ => None, }, _ => None, @@ -318,25 +318,25 @@ impl HirDisplay for &Ty { impl HirDisplay for ApplicationTy { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { match self.name { - TypeName::Bool => write!(f, "bool")?, - TypeName::Char => write!(f, "char")?, - TypeName::Int(t) => write!(f, "{}", t)?, - TypeName::Float(t) => write!(f, "{}", t)?, - TypeName::Str => write!(f, "str")?, - TypeName::Slice | TypeName::Array => { + TypeCtor::Bool => write!(f, "bool")?, + TypeCtor::Char => write!(f, "char")?, + TypeCtor::Int(t) => write!(f, "{}", t)?, + TypeCtor::Float(t) => write!(f, "{}", t)?, + TypeCtor::Str => write!(f, "str")?, + TypeCtor::Slice | TypeCtor::Array => { let t = self.parameters.as_single(); write!(f, "[{}]", t.display(f.db))?; } - TypeName::RawPtr(m) => { + TypeCtor::RawPtr(m) => { let t = self.parameters.as_single(); write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?; } - TypeName::Ref(m) => { + TypeCtor::Ref(m) => { let t = self.parameters.as_single(); write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?; } - TypeName::Never => write!(f, "!")?, - TypeName::Tuple => { + TypeCtor::Never => write!(f, "!")?, + TypeCtor::Tuple => { let ts = &self.parameters; if ts.0.len() == 1 { write!(f, "({},)", ts.0[0].display(f.db))?; @@ -346,13 +346,13 @@ impl HirDisplay for ApplicationTy { write!(f, ")")?; } } - TypeName::FnPtr => { + TypeCtor::FnPtr => { let sig = FnSig::from_fn_ptr_substs(&self.parameters); write!(f, "fn(")?; f.write_joined(sig.params(), ", ")?; write!(f, ") -> {}", sig.ret().display(f.db))?; } - TypeName::FnDef(def) => { + TypeCtor::FnDef(def) => { let sig = f.db.callable_item_signature(def); let name = match def { CallableDef::Function(ff) => ff.name(f.db), @@ -372,7 +372,7 @@ impl HirDisplay for ApplicationTy { f.write_joined(sig.params(), ", ")?; write!(f, ") -> {}", sig.ret().display(f.db))?; } - TypeName::Adt(def_id) => { + TypeCtor::Adt(def_id) => { let name = match def_id { AdtDef::Struct(s) => s.name(f.db), AdtDef::Enum(e) => e.name(f.db), diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 0dafd8cbd..e975f9217 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, FnSig, ApplicationTy, TypeName}; +use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; /// The entry point of type inference. pub fn infer(db: &impl HirDatabase, func: Function) -> Arc { @@ -278,11 +278,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { match ty { Ty::Unknown => self.new_type_var(), Ty::Apply(ApplicationTy { - name: TypeName::Int(primitive::UncertainIntTy::Unknown), + name: TypeCtor::Int(primitive::UncertainIntTy::Unknown), .. }) => self.new_integer_var(), Ty::Apply(ApplicationTy { - name: TypeName::Float(primitive::UncertainFloatTy::Unknown), + name: TypeCtor::Float(primitive::UncertainFloatTy::Unknown), .. }) => self.new_float_var(), _ => ty, @@ -629,7 +629,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .collect::>() .into(); - Ty::apply(TypeName::Tuple, Substs(inner_tys)) + Ty::apply(TypeCtor::Tuple, Substs(inner_tys)) } Pat::Ref { pat, mutability } => { let expectation = match expected.as_reference() { @@ -642,7 +642,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { _ => &Ty::Unknown, }; let subty = self.infer_pat(*pat, expectation, default_bm); - Ty::apply_one(TypeName::Ref(*mutability), subty.into()) + Ty::apply_one(TypeCtor::Ref(*mutability), subty.into()) } Pat::TupleStruct { path: ref p, args: ref subpats } => { self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) @@ -670,7 +670,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let bound_ty = match mode { BindingMode::Ref(mutability) => { - Ty::apply_one(TypeName::Ref(mutability), inner_ty.clone().into()) + Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone().into()) } BindingMode::Move => inner_ty.clone(), }; @@ -725,7 +725,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::Missing => Ty::Unknown, Expr::If { condition, then_branch, else_branch } => { // if let is desugared to match, so this is always simple if - self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeName::Bool))); + self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); let then_ty = self.infer_expr(*then_branch, expected); match else_branch { Some(else_branch) => { @@ -742,11 +742,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::Loop { body } => { self.infer_expr(*body, &Expectation::has_type(Ty::unit())); // TODO handle break with value - Ty::simple(TypeName::Never) + Ty::simple(TypeCtor::Never) } Expr::While { condition, body } => { // while let is desugared to a match loop, so this is always simple while - self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeName::Bool))); + self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); self.infer_expr(*body, &Expectation::has_type(Ty::unit())); Ty::unit() } @@ -777,11 +777,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let callee_ty = self.infer_expr(*callee, &Expectation::none()); let (param_tys, ret_ty) = match &callee_ty { Ty::Apply(a_ty) => match a_ty.name { - TypeName::FnPtr => { + TypeCtor::FnPtr => { let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); (sig.params().to_vec(), sig.ret().clone()) } - TypeName::FnDef(def) => { + TypeCtor::FnDef(def) => { let sig = self.db.callable_item_signature(def); let ret_ty = sig.ret().clone().subst(&a_ty.parameters); let param_tys = sig @@ -824,7 +824,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::Apply(a_ty) => match a_ty.name { - TypeName::FnPtr => { + TypeCtor::FnPtr => { let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); if !sig.params().is_empty() { ( @@ -836,7 +836,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { (Ty::Unknown, Vec::new(), sig.ret().clone()) } } - TypeName::FnDef(def) => { + TypeCtor::FnDef(def) => { let sig = self.db.callable_item_signature(def); let ret_ty = sig.ret().clone().subst(&a_ty.parameters); @@ -858,7 +858,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // Apply autoref so the below unification works correctly let actual_receiver_ty = match expected_receiver_ty.as_reference() { Some((_, mutability)) => { - Ty::apply_one(TypeName::Ref(mutability), derefed_receiver_ty) + Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty) } _ => derefed_receiver_ty, }; @@ -885,7 +885,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { if let Some(guard_expr) = arm.guard { self.infer_expr( guard_expr, - &Expectation::has_type(Ty::simple(TypeName::Bool)), + &Expectation::has_type(Ty::simple(TypeCtor::Bool)), ); } self.infer_expr(arm.expr, &expected); @@ -898,19 +898,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); self.infer_path_expr(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) } - Expr::Continue => Ty::simple(TypeName::Never), + Expr::Continue => Ty::simple(TypeCtor::Never), Expr::Break { expr } => { if let Some(expr) = expr { // TODO handle break with value self.infer_expr(*expr, &Expectation::none()); } - Ty::simple(TypeName::Never) + Ty::simple(TypeCtor::Never) } Expr::Return { expr } => { if let Some(expr) = expr { self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); } - Ty::simple(TypeName::Never) + Ty::simple(TypeCtor::Never) } Expr::StructLit { path, fields, spread } => { let (ty, def_id) = self.resolve_variant(path.as_ref()); @@ -933,11 +933,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .autoderef(self.db) .find_map(|derefed_ty| match derefed_ty { Ty::Apply(a_ty) => match a_ty.name { - TypeName::Tuple => { + TypeCtor::Tuple => { let i = name.to_string().parse::().ok(); i.and_then(|i| a_ty.parameters.0.get(i).cloned()) } - TypeName::Adt(AdtDef::Struct(s)) => { + TypeCtor::Adt(AdtDef::Struct(s)) => { s.field(self.db, name).map(|field| { self.write_field_resolution(tgt_expr, field); field.ty(self.db).subst(&a_ty.parameters) @@ -973,7 +973,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; // TODO reference coercions etc. let inner_ty = self.infer_expr(*expr, &expectation); - Ty::apply_one(TypeName::Ref(*mutability), inner_ty) + Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) } Expr::UnaryOp { expr, op } => { let inner_ty = self.infer_expr(*expr, &Expectation::none()); @@ -989,9 +989,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { UnaryOp::Neg => { match &inner_ty { Ty::Apply(a_ty) => match a_ty.name { - TypeName::Int(primitive::UncertainIntTy::Unknown) - | TypeName::Int(primitive::UncertainIntTy::Signed(..)) - | TypeName::Float(..) => inner_ty, + TypeCtor::Int(primitive::UncertainIntTy::Unknown) + | TypeCtor::Int(primitive::UncertainIntTy::Signed(..)) + | TypeCtor::Float(..) => inner_ty, _ => Ty::Unknown, }, Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => { @@ -1004,7 +1004,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { UnaryOp::Not => { match &inner_ty { Ty::Apply(a_ty) => match a_ty.name { - TypeName::Bool | TypeName::Int(_) => inner_ty, + TypeCtor::Bool | TypeCtor::Int(_) => inner_ty, _ => Ty::Unknown, }, Ty::Infer(InferTy::IntVar(..)) => inner_ty, @@ -1018,7 +1018,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Some(op) => { let lhs_expectation = match op { BinaryOp::BooleanAnd | BinaryOp::BooleanOr => { - Expectation::has_type(Ty::simple(TypeName::Bool)) + Expectation::has_type(Ty::simple(TypeCtor::Bool)) } _ => Expectation::none(), }; @@ -1039,12 +1039,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty_vec.push(self.infer_expr(*arg, &Expectation::none())); } - Ty::apply(TypeName::Tuple, Substs(ty_vec.into())) + Ty::apply(TypeCtor::Tuple, Substs(ty_vec.into())) } Expr::Array { exprs } => { let elem_ty = match &expected.ty { Ty::Apply(a_ty) => match a_ty.name { - TypeName::Slice | TypeName::Array => { + TypeCtor::Slice | TypeCtor::Array => { Ty::clone(&a_ty.parameters.as_single()) } _ => self.new_type_var(), @@ -1056,23 +1056,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.infer_expr(*expr, &Expectation::has_type(elem_ty.clone())); } - Ty::apply_one(TypeName::Array, elem_ty) + Ty::apply_one(TypeCtor::Array, elem_ty) } Expr::Literal(lit) => match lit { - Literal::Bool(..) => Ty::simple(TypeName::Bool), + Literal::Bool(..) => Ty::simple(TypeCtor::Bool), Literal::String(..) => { - Ty::apply_one(TypeName::Ref(Mutability::Shared), Ty::simple(TypeName::Str)) + Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str)) } Literal::ByteString(..) => { - let byte_type = Ty::simple(TypeName::Int(primitive::UncertainIntTy::Unsigned( + let byte_type = Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Unsigned( primitive::UintTy::U8, ))); - let slice_type = Ty::apply_one(TypeName::Slice, byte_type); - Ty::apply_one(TypeName::Ref(Mutability::Shared), slice_type) + let slice_type = Ty::apply_one(TypeCtor::Slice, byte_type); + Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type) } - Literal::Char(..) => Ty::simple(TypeName::Char), - Literal::Int(_v, ty) => Ty::simple(TypeName::Int(*ty)), - Literal::Float(_v, ty) => Ty::simple(TypeName::Float(*ty)), + Literal::Char(..) => Ty::simple(TypeCtor::Char), + Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int(*ty)), + Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float(*ty)), }, }; // use a new type variable if we got Ty::Unknown here @@ -1208,9 +1208,9 @@ impl InferTy { match self { InferTy::TypeVar(..) => Ty::Unknown, InferTy::IntVar(..) => { - Ty::simple(TypeName::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32))) + Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32))) } - InferTy::FloatVar(..) => Ty::simple(TypeName::Float( + InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float( primitive::UncertainFloatTy::Known(primitive::FloatTy::F64), )), } diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index a346879d8..72b1234bf 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -19,40 +19,40 @@ use crate::{ generics::GenericParams, adt::VariantDef, }; -use super::{Ty, primitive, FnSig, Substs, TypeName}; +use super::{Ty, primitive, FnSig, Substs, TypeCtor}; impl Ty { pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { match type_ref { - TypeRef::Never => Ty::simple(TypeName::Never), + TypeRef::Never => Ty::simple(TypeCtor::Never), TypeRef::Tuple(inner) => { let inner_tys = inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::>(); - Ty::apply(TypeName::Tuple, Substs(inner_tys.into())) + Ty::apply(TypeCtor::Tuple, Substs(inner_tys.into())) } TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), TypeRef::RawPtr(inner, mutability) => { let inner_ty = Ty::from_hir(db, resolver, inner); - Ty::apply_one(TypeName::RawPtr(*mutability), inner_ty) + Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) } TypeRef::Array(inner) => { let inner_ty = Ty::from_hir(db, resolver, inner); - Ty::apply_one(TypeName::Array, inner_ty) + Ty::apply_one(TypeCtor::Array, inner_ty) } TypeRef::Slice(inner) => { let inner_ty = Ty::from_hir(db, resolver, inner); - Ty::apply_one(TypeName::Slice, inner_ty) + Ty::apply_one(TypeCtor::Slice, inner_ty) } TypeRef::Reference(inner, mutability) => { let inner_ty = Ty::from_hir(db, resolver, inner); - Ty::apply_one(TypeName::Ref(*mutability), inner_ty) + Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) } TypeRef::Placeholder => Ty::Unknown, TypeRef::Fn(params) => { let inner_tys = params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::>(); let sig = Substs(inner_tys.into()); - Ty::apply(TypeName::FnPtr, sig) + Ty::apply(TypeCtor::FnPtr, sig) } TypeRef::Error => Ty::Unknown, } @@ -62,14 +62,14 @@ impl Ty { if let Some(name) = path.as_ident() { // TODO handle primitive type names in resolver as well? if let Some(int_ty) = primitive::UncertainIntTy::from_type_name(name) { - return Ty::simple(TypeName::Int(int_ty)); + return Ty::simple(TypeCtor::Int(int_ty)); } else if let Some(float_ty) = primitive::UncertainFloatTy::from_type_name(name) { - return Ty::simple(TypeName::Float(float_ty)); + return Ty::simple(TypeCtor::Float(float_ty)); } else if let Some(known) = name.as_known_name() { match known { - KnownName::Bool => return Ty::simple(TypeName::Bool), - KnownName::Char => return Ty::simple(TypeName::Char), - KnownName::Str => return Ty::simple(TypeName::Str), + KnownName::Bool => return Ty::simple(TypeCtor::Bool), + KnownName::Char => return Ty::simple(TypeCtor::Char), + KnownName::Str => return Ty::simple(TypeCtor::Str), _ => {} } } @@ -245,7 +245,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { let generics = def.generic_params(db); let substs = make_substs(&generics); - Ty::apply(TypeName::FnDef(def.into()), substs) + Ty::apply(TypeCtor::FnDef(def.into()), substs) } /// Build the declared type of a const. @@ -287,7 +287,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { } let generics = def.generic_params(db); let substs = make_substs(&generics); - Ty::apply(TypeName::FnDef(def.into()), substs) + Ty::apply(TypeCtor::FnDef(def.into()), substs) } fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { @@ -315,7 +315,7 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> } let generics = def.parent_enum(db).generic_params(db); let substs = make_substs(&generics); - Ty::apply(TypeName::FnDef(def.into()), substs) + Ty::apply(TypeCtor::FnDef(def.into()), substs) } fn make_substs(generics: &GenericParams) -> Substs { @@ -331,12 +331,12 @@ fn make_substs(generics: &GenericParams) -> Substs { fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { let generics = s.generic_params(db); - Ty::apply(TypeName::Adt(s.into()), make_substs(&generics)) + Ty::apply(TypeCtor::Adt(s.into()), make_substs(&generics)) } fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { let generics = s.generic_params(db); - Ty::apply(TypeName::Adt(s.into()), make_substs(&generics)) + Ty::apply(TypeCtor::Adt(s.into()), make_substs(&generics)) } fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 06bfe85cd..9422bad84 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -10,7 +10,7 @@ use crate::{ HirDatabase, Module, Crate, Name, Function, Trait, ids::TraitId, impl_block::{ImplId, ImplBlock, ImplItem}, - ty::{Ty, TypeName}, + ty::{Ty, TypeCtor}, nameres::CrateModuleId, }; @@ -18,7 +18,7 @@ use crate::{ /// This is used as a key for indexing impls. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TyFingerprint { - Apply(TypeName), + Apply(TypeCtor), } impl TyFingerprint { @@ -112,7 +112,7 @@ impl CrateImplBlocks { fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option { match ty { Ty::Apply(a_ty) => match a_ty.name { - TypeName::Adt(def_id) => def_id.krate(db), + TypeCtor::Adt(def_id) => def_id.krate(db), _ => None, }, _ => None, diff --git a/crates/ra_hir/src/ty/op.rs b/crates/ra_hir/src/ty/op.rs index f581004d2..1d230140b 100644 --- a/crates/ra_hir/src/ty/op.rs +++ b/crates/ra_hir/src/ty/op.rs @@ -1,5 +1,5 @@ use crate::{ ty::ApplicationTy, expr::BinaryOp}; -use super::{Ty, TypeName, InferTy}; +use super::{Ty, TypeCtor, InferTy}; pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { match op { @@ -10,7 +10,7 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | BinaryOp::LesserEqualTest | BinaryOp::GreaterEqualTest | BinaryOp::LesserTest - | BinaryOp::GreaterTest => Ty::simple(TypeName::Bool), + | BinaryOp::GreaterTest => Ty::simple(TypeCtor::Bool), BinaryOp::Assignment | BinaryOp::AddAssign | BinaryOp::SubAssign @@ -33,7 +33,7 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | BinaryOp::BitwiseOr | BinaryOp::BitwiseXor => match rhs_ty { Ty::Apply(ApplicationTy { name, .. }) => match name { - TypeName::Int(..) | TypeName::Float(..) => rhs_ty, + TypeCtor::Int(..) | TypeCtor::Float(..) => rhs_ty, _ => Ty::Unknown, }, Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, @@ -45,14 +45,14 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { match op { - BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::simple(TypeName::Bool), + BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::simple(TypeCtor::Bool), BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { Ty::Apply(ApplicationTy { name, .. }) => match name { - TypeName::Int(..) - | TypeName::Float(..) - | TypeName::Str - | TypeName::Char - | TypeName::Bool => lhs_ty, + TypeCtor::Int(..) + | TypeCtor::Float(..) + | TypeCtor::Str + | TypeCtor::Char + | TypeCtor::Bool => lhs_ty, _ => Ty::Unknown, }, Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, @@ -83,7 +83,7 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | BinaryOp::BitwiseOr | BinaryOp::BitwiseXor => match lhs_ty { Ty::Apply(ApplicationTy { name, .. }) => match name { - TypeName::Int(..) | TypeName::Float(..) => lhs_ty, + TypeCtor::Int(..) | TypeCtor::Float(..) => lhs_ty, _ => Ty::Unknown, }, Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index dc5206a64..f975214e9 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -1,4 +1,4 @@ -use hir::{Ty, AdtDef, TypeName}; +use hir::{Ty, AdtDef, TypeCtor}; use crate::completion::{CompletionContext, Completions}; @@ -25,13 +25,13 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) for receiver in receiver.autoderef(ctx.db) { match receiver { Ty::Apply(a_ty) => match a_ty.name { - TypeName::Adt(AdtDef::Struct(s)) => { + TypeCtor::Adt(AdtDef::Struct(s)) => { for field in s.fields(ctx.db) { acc.add_field(ctx, field, &a_ty.parameters); } } // TODO unions - TypeName::Tuple => { + TypeCtor::Tuple => { for (i, ty) in a_ty.parameters.iter().enumerate() { acc.add_pos_field(ctx, i, ty); } -- cgit v1.2.3 From 97be0e6c46196552607aa0121b32a41a3515873d Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 21 Mar 2019 22:23:52 +0100 Subject: Some more doc comments --- crates/ra_hir/src/ty.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 1d9e7b76c..fc1f054dc 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -20,6 +20,9 @@ pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, ca pub(crate) use infer::{infer, InferenceResult, InferTy}; use display::{HirDisplay, HirFormatter}; +/// A type constructor or type name: this might be something like the primitive +/// type `bool`, a struct like `Vec`, or things like function pointers or +/// tuples. #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum TypeCtor { /// The primitive boolean type. Written as `bool`. @@ -85,13 +88,19 @@ pub enum TypeCtor { Tuple, } +/// A nominal type with (maybe 0) type parameters. This might be a primitive +/// type like `bool`, a struct, tuple, function pointer, reference or +/// several other things. #[derive(Clone, PartialEq, Eq, Debug)] pub struct ApplicationTy { pub name: TypeCtor, pub parameters: Substs, } -/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). +/// A type. +/// +/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents +/// the same thing (but in a different way). /// /// This should be cheap to clone. #[derive(Clone, PartialEq, Eq, Debug)] @@ -156,7 +165,8 @@ impl Substs { } } -/// A function signature. +/// A function signature as seen by type inference: Several parameter types and +/// one return type. #[derive(Clone, PartialEq, Eq, Debug)] pub struct FnSig { params_and_return: Arc<[Ty]>, -- cgit v1.2.3 From cbb418ebb87309a798ca16408c1dfb09cd638a9b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 21 Mar 2019 22:29:12 +0100 Subject: Rename name field to ctor as well --- crates/ra_hir/src/ty.rs | 28 ++++++++++++------------ crates/ra_hir/src/ty/infer.rs | 18 +++++++-------- crates/ra_hir/src/ty/method_resolution.rs | 4 ++-- crates/ra_hir/src/ty/op.rs | 6 ++--- crates/ra_ide_api/src/completion/complete_dot.rs | 2 +- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index fc1f054dc..5cd766b85 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -93,7 +93,7 @@ pub enum TypeCtor { /// several other things. #[derive(Clone, PartialEq, Eq, Debug)] pub struct ApplicationTy { - pub name: TypeCtor, + pub ctor: TypeCtor, pub parameters: Substs, } @@ -201,14 +201,14 @@ impl FnSig { } impl Ty { - pub fn simple(name: TypeCtor) -> Ty { - Ty::Apply(ApplicationTy { name, parameters: Substs::empty() }) + pub fn simple(ctor: TypeCtor) -> Ty { + Ty::Apply(ApplicationTy { ctor, parameters: Substs::empty() }) } - pub fn apply_one(name: TypeCtor, param: Ty) -> Ty { - Ty::Apply(ApplicationTy { name, parameters: Substs::single(param) }) + pub fn apply_one(ctor: TypeCtor, param: Ty) -> Ty { + Ty::Apply(ApplicationTy { ctor, parameters: Substs::single(param) }) } - pub fn apply(name: TypeCtor, parameters: Substs) -> Ty { - Ty::Apply(ApplicationTy { name, parameters }) + pub fn apply(ctor: TypeCtor, parameters: Substs) -> Ty { + Ty::Apply(ApplicationTy { ctor, parameters }) } pub fn unit() -> Self { Ty::apply(TypeCtor::Tuple, Substs::empty()) @@ -246,7 +246,7 @@ impl Ty { pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { match self { - Ty::Apply(ApplicationTy { name: TypeCtor::Ref(mutability), parameters }) => { + Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { Some((parameters.as_single(), *mutability)) } _ => None, @@ -255,7 +255,7 @@ impl Ty { pub fn as_adt(&self) -> Option<(AdtDef, &Substs)> { match self { - Ty::Apply(ApplicationTy { name: TypeCtor::Adt(adt_def), parameters }) => { + Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => { Some((*adt_def, parameters)) } _ => None, @@ -264,14 +264,14 @@ impl Ty { pub fn as_tuple(&self) -> Option<&Substs> { match self { - Ty::Apply(ApplicationTy { name: TypeCtor::Tuple, parameters }) => Some(parameters), + Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple, parameters }) => Some(parameters), _ => None, } } fn builtin_deref(&self) -> Option { match self { - Ty::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())), TypeCtor::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())), _ => None, @@ -286,8 +286,8 @@ impl Ty { /// `Option` afterwards.) pub fn apply_substs(self, substs: Substs) -> Ty { match self { - Ty::Apply(ApplicationTy { name, .. }) => { - Ty::Apply(ApplicationTy { name, parameters: substs }) + Ty::Apply(ApplicationTy { ctor, .. }) => { + Ty::Apply(ApplicationTy { ctor, parameters: substs }) } _ => self, } @@ -327,7 +327,7 @@ impl HirDisplay for &Ty { impl HirDisplay for ApplicationTy { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { - match self.name { + match self.ctor { TypeCtor::Bool => write!(f, "bool")?, TypeCtor::Char => write!(f, "char")?, TypeCtor::Int(t) => write!(f, "{}", t)?, diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index e975f9217..be74b9fa6 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -237,7 +237,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { match (&*ty1, &*ty2) { (Ty::Unknown, ..) => true, (.., Ty::Unknown) => true, - (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.name == a_ty2.name => { + (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) } (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) @@ -278,11 +278,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { match ty { Ty::Unknown => self.new_type_var(), Ty::Apply(ApplicationTy { - name: TypeCtor::Int(primitive::UncertainIntTy::Unknown), + ctor: TypeCtor::Int(primitive::UncertainIntTy::Unknown), .. }) => self.new_integer_var(), Ty::Apply(ApplicationTy { - name: TypeCtor::Float(primitive::UncertainFloatTy::Unknown), + ctor: TypeCtor::Float(primitive::UncertainFloatTy::Unknown), .. }) => self.new_float_var(), _ => ty, @@ -776,7 +776,7 @@ 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::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::FnPtr => { let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); (sig.params().to_vec(), sig.ret().clone()) @@ -823,7 +823,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let method_ty = method_ty.apply_substs(substs); let method_ty = self.insert_type_vars(method_ty); let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { - Ty::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::FnPtr => { let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); if !sig.params().is_empty() { @@ -932,7 +932,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = receiver_ty .autoderef(self.db) .find_map(|derefed_ty| match derefed_ty { - Ty::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Tuple => { let i = name.to_string().parse::().ok(); i.and_then(|i| a_ty.parameters.0.get(i).cloned()) @@ -988,7 +988,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } UnaryOp::Neg => { match &inner_ty { - Ty::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Int(primitive::UncertainIntTy::Unknown) | TypeCtor::Int(primitive::UncertainIntTy::Signed(..)) | TypeCtor::Float(..) => inner_ty, @@ -1003,7 +1003,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } UnaryOp::Not => { match &inner_ty { - Ty::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Bool | TypeCtor::Int(_) => inner_ty, _ => Ty::Unknown, }, @@ -1043,7 +1043,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Expr::Array { exprs } => { let elem_ty = match &expected.ty { - Ty::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Slice | TypeCtor::Array => { Ty::clone(&a_ty.parameters.as_single()) } diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 9422bad84..ed75bfaee 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -27,7 +27,7 @@ impl TyFingerprint { /// `impl &S`. Hence, this will return `None` for reference types and such. fn for_impl(ty: &Ty) -> Option { match ty { - Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.name)), + Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), _ => None, } } @@ -111,7 +111,7 @@ impl CrateImplBlocks { fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option { match ty { - Ty::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Adt(def_id) => def_id.krate(db), _ => None, }, diff --git a/crates/ra_hir/src/ty/op.rs b/crates/ra_hir/src/ty/op.rs index 1d230140b..235661a5d 100644 --- a/crates/ra_hir/src/ty/op.rs +++ b/crates/ra_hir/src/ty/op.rs @@ -32,7 +32,7 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | BinaryOp::BitwiseAnd | BinaryOp::BitwiseOr | BinaryOp::BitwiseXor => match rhs_ty { - Ty::Apply(ApplicationTy { name, .. }) => match name { + Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { TypeCtor::Int(..) | TypeCtor::Float(..) => rhs_ty, _ => Ty::Unknown, }, @@ -47,7 +47,7 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { match op { BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::simple(TypeCtor::Bool), BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { - Ty::Apply(ApplicationTy { name, .. }) => match name { + Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { TypeCtor::Int(..) | TypeCtor::Float(..) | TypeCtor::Str @@ -82,7 +82,7 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | BinaryOp::BitwiseAnd | BinaryOp::BitwiseOr | BinaryOp::BitwiseXor => match lhs_ty { - Ty::Apply(ApplicationTy { name, .. }) => match name { + Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { TypeCtor::Int(..) | TypeCtor::Float(..) => lhs_ty, _ => Ty::Unknown, }, diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index f975214e9..31d5374ba 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -24,7 +24,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { for receiver in receiver.autoderef(ctx.db) { match receiver { - Ty::Apply(a_ty) => match a_ty.name { + Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Adt(AdtDef::Struct(s)) => { for field in s.fields(ctx.db) { acc.add_field(ctx, field, &a_ty.parameters); -- cgit v1.2.3 From 1ee779d1f74f48d9f3098001c63108b794dbc0b5 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 21 Mar 2019 22:39:31 +0100 Subject: Assert in apply_substs that the number of parameters doesn't change ... and fix a small bug revealed by that. --- crates/ra_hir/src/ty.rs | 7 ++++++- crates/ra_hir/src/ty/infer.rs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 5cd766b85..7d25ade47 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -148,6 +148,10 @@ impl Substs { self.0.iter() } + pub fn len(&self) -> usize { + self.0.len() + } + 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(); @@ -286,7 +290,8 @@ impl Ty { /// `Option` afterwards.) pub fn apply_substs(self, substs: Substs) -> Ty { match self { - Ty::Apply(ApplicationTy { ctor, .. }) => { + Ty::Apply(ApplicationTy { ctor, parameters: previous_substs }) => { + assert_eq!(previous_substs.len(), substs.len()); Ty::Apply(ApplicationTy { ctor, parameters: substs }) } _ => self, diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index be74b9fa6..bf42befbb 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -817,7 +817,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Some(func.generic_params(self.db)), ) } - None => (Ty::Unknown, receiver_ty, None), + None => (receiver_ty, Ty::Unknown, None), }; let substs = self.substs_for_method_call(def_generics, generic_args); let method_ty = method_ty.apply_substs(substs); -- cgit v1.2.3