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