From 3bd47c0285433b5eb258196a81b95141d2a70505 Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Fri, 25 Jan 2019 21:16:02 +0100 Subject: First attempt at generic type inference for fns --- crates/ra_hir/src/code_model_api.rs | 6 +-- crates/ra_hir/src/code_model_impl/function.rs | 8 +-- crates/ra_hir/src/generics.rs | 3 +- crates/ra_hir/src/ty.rs | 61 +++++++++++++++++----- crates/ra_hir/src/ty/tests.rs | 22 ++++++++ .../ra_ide_api/src/completion/completion_item.rs | 2 +- 6 files changed, 81 insertions(+), 21 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 191104890..82ebb275a 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -388,7 +388,7 @@ pub use crate::code_model_impl::function::ScopeEntryWithSyntax; #[derive(Debug, Clone, PartialEq, Eq)] pub struct FnSignature { pub(crate) name: Name, - pub(crate) params: Vec, + pub(crate) args: Vec, pub(crate) ret_type: TypeRef, /// True if the first param is `self`. This is relevant to decide whether this /// can be called as a method. @@ -400,8 +400,8 @@ impl FnSignature { &self.name } - pub fn params(&self) -> &[TypeRef] { - &self.params + pub fn args(&self) -> &[TypeRef] { + &self.args } pub fn ret_type(&self) -> &TypeRef { diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index e0dd4d629..b4aa18540 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -32,7 +32,7 @@ impl FnSignature { .name() .map(|n| n.as_name()) .unwrap_or_else(Name::missing); - let mut params = Vec::new(); + let mut args = Vec::new(); let mut has_self_param = false; if let Some(param_list) = node.param_list() { if let Some(self_param) = param_list.self_param() { @@ -50,12 +50,12 @@ impl FnSignature { } } }; - params.push(self_type); + args.push(self_type); has_self_param = true; } for param in param_list.params() { let type_ref = TypeRef::from_ast_opt(param.type_ref()); - params.push(type_ref); + args.push(type_ref); } } let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { @@ -66,7 +66,7 @@ impl FnSignature { let sig = FnSignature { name, - params, + args, ret_type, has_self_param, }; diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 64c20a462..a5501d543 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -49,7 +49,8 @@ impl GenericParams { Arc::new(generics) } - fn fill(&mut self, node: &impl TypeParamsOwner) { + // FIXME: probably shouldnt be pub(crate) + pub(crate) fn fill(&mut self, node: &impl TypeParamsOwner) { if let Some(params) = node.type_param_list() { self.fill_params(params) } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 31ea45706..95de916ee 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -209,6 +209,18 @@ pub enum Ty { /// `&'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}`. + /// + /// For example the type of `bar` here: + /// + /// ```rust + /// fn foo() -> i32 { 1 } + /// let bar = foo; // bar: fn() -> i32 {foo} + /// ``` + FnDef(Function, Substs), + /// A pointer to a function. Written as `fn() -> i32`. /// /// For example the type of `bar` here: @@ -485,7 +497,7 @@ impl Ty { } sig_mut.output.walk_mut(f); } - Ty::Adt { substs, .. } => { + Ty::FnDef(_, substs) | Ty::Adt { substs, .. } => { // Without an Arc::make_mut_slice, we can't avoid the clone here: let mut v: Vec<_> = substs.0.iter().cloned().collect(); for t in &mut v { @@ -524,6 +536,7 @@ impl Ty { name, substs, }, + Ty::FnDef(func, _) => Ty::FnDef(func, substs), _ => self, } } @@ -579,6 +592,7 @@ impl fmt::Display for Ty { .to_fmt(f) } } + Ty::FnDef(_func, _substs) => write!(f, "FNDEF-IMPLEMENT-ME"), Ty::FnPtr(sig) => { join(sig.input.iter()) .surround_with("fn(", ")") @@ -608,12 +622,18 @@ impl fmt::Display for Ty { /// Compute the declared type of a function. This should not need to look at the /// function body. fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { + let generics = f.generic_params(db); + let substs = make_substs(&generics); + Ty::FnDef(f.into(), substs) +} + +fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig { let signature = f.signature(db); let module = f.module(db); let impl_block = f.impl_block(db); let generics = f.generic_params(db); let input = signature - .params() + .args() .iter() .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) .collect::>(); @@ -624,8 +644,7 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { &generics, signature.ret_type(), ); - let sig = FnSig { input, output }; - Ty::FnPtr(Arc::new(sig)) + FnSig { input, output } } fn make_substs(generics: &GenericParams) -> Substs { @@ -1142,7 +1161,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = self.insert_type_vars(ty.apply_substs(substs)); (ty, Some(var.into())) } - TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None), + TypableDef::Function(func) => { + let ty = type_for_fn(self.db, func); + let ty = self.insert_type_vars(ty.apply_substs(substs)); + // FIXME: is this right? + (ty, None) + } + TypableDef::Enum(_) => (Ty::Unknown, None), } } @@ -1331,12 +1356,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Expr::Call { callee, args } => { let callee_ty = self.infer_expr(*callee, &Expectation::none()); + // FIXME: so manu unnecessary clones let (param_tys, ret_ty) = match &callee_ty { - Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), + Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), + Ty::FnDef(func, substs) => { + let fn_sig = func.signature(self.db); + // TODO: get input and return types from the fn_sig. + // it contains typerefs which we can make into proper tys + + let sig = get_func_sig(self.db, *func); + ( + sig.input + .iter() + .map(|ty| ty.clone().subst(&substs)) + .collect(), + sig.output.clone().subst(&substs), + ) + } _ => { // not callable // TODO report an error? - (&[][..], Ty::Unknown) + (Vec::new(), Ty::Unknown) } }; for (i, arg) in args.iter().enumerate() { @@ -1604,15 +1644,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn collect_fn_signature(&mut self, signature: &FnSignature) { let body = Arc::clone(&self.body); // avoid borrow checker problem - for (type_ref, pat) in signature.params().iter().zip(body.params()) { + for (type_ref, pat) in signature.args().iter().zip(body.params()) { let ty = self.make_ty(type_ref); self.infer_pat(*pat, &ty); } - self.return_ty = { - let ty = self.make_ty(signature.ret_type()); - ty - }; + self.return_ty = self.make_ty(signature.ret_type()); } fn infer_body(&mut self) { diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index f74d6f5ea..40913b164 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -594,6 +594,28 @@ fn test() { ); } +#[test] +fn infer_type_param() { + check_inference( + "generic_fn", + r#" +fn id(x: T) -> T { + x +} + +fn clone(x: &T) -> T { + x +} + +fn test() { + let y = 10u32; + id(y); + let x: bool = clone(z); +} +"#, + ); +} + fn infer(content: &str) -> String { let (db, _, file_id) = MockDatabase::with_single_file(content); let source_file = db.parse(file_id); diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index b16ac2b28..6e9a68e40 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -240,7 +240,7 @@ impl Builder { if ctx.use_item_syntax.is_none() && !ctx.is_call { tested_by!(inserts_parens_for_function_calls); let sig = function.signature(ctx.db); - if sig.params().is_empty() || sig.has_self_param() && sig.params().len() == 1 { + if sig.args().is_empty() || sig.has_self_param() && sig.args().len() == 1 { self.insert_text = Some(format!("{}()$0", self.label)); } else { self.insert_text = Some(format!("{}($0)", self.label)); -- cgit v1.2.3 From 67e40e431aa966a76b6a247b19505e22b620a0c7 Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Fri, 25 Jan 2019 22:18:13 +0100 Subject: Initial implementation of generics for method calls --- crates/ra_hir/src/code_model_api.rs | 4 ++ crates/ra_hir/src/ty.rs | 81 +++++++++++++++++++++++++++++++------ 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 82ebb275a..defb9fd0a 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -424,6 +424,10 @@ impl Function { self.id.module(db) } + pub fn name(&self, db: &impl HirDatabase) -> Name { + self.signature(db).name.clone() + } + pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc { db.body_syntax_mapping(*self) } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 95de916ee..9b08b9c97 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -185,7 +185,7 @@ pub enum Ty { /// Structures, enumerations and unions. Adt { - /// The DefId of the struct/enum. + /// The definition of the struct/enum. def_id: AdtDef, /// The name, for displaying. name: Name, @@ -219,7 +219,14 @@ pub enum Ty { /// fn foo() -> i32 { 1 } /// let bar = foo; // bar: fn() -> i32 {foo} /// ``` - FnDef(Function, Substs), + FnDef { + // Function definition + def: Function, + /// For display + name: Name, + /// Substitutions for the generic parameters of the type + substs: Substs + }, /// A pointer to a function. Written as `fn() -> i32`. /// @@ -497,7 +504,7 @@ impl Ty { } sig_mut.output.walk_mut(f); } - Ty::FnDef(_, substs) | Ty::Adt { substs, .. } => { + Ty::FnDef { substs, .. } | Ty::Adt { substs, .. } => { // Without an Arc::make_mut_slice, we can't avoid the clone here: let mut v: Vec<_> = substs.0.iter().cloned().collect(); for t in &mut v { @@ -536,7 +543,11 @@ impl Ty { name, substs, }, - Ty::FnDef(func, _) => Ty::FnDef(func, substs), + Ty::FnDef { def, name, .. } => Ty::FnDef { + def, + name, + substs, + }, _ => self, } } @@ -592,7 +603,6 @@ impl fmt::Display for Ty { .to_fmt(f) } } - Ty::FnDef(_func, _substs) => write!(f, "FNDEF-IMPLEMENT-ME"), Ty::FnPtr(sig) => { join(sig.input.iter()) .surround_with("fn(", ")") @@ -600,6 +610,19 @@ impl fmt::Display for Ty { .to_fmt(f)?; write!(f, " -> {}", sig.output) } + Ty::FnDef { name, substs, .. } => { + // don't have access to the param types here :-( + // we could store them in the def, but not sure if it + // is worth it + write!(f, "fn {}", name)?; + if substs.0.len() > 0 { + join(substs.0.iter()) + .surround_with("<", ">") + .separator(", ") + .to_fmt(f)?; + } + Ok(()) + } Ty::Adt { name, substs, .. } => { write!(f, "{}", name)?; if substs.0.len() > 0 { @@ -624,7 +647,12 @@ impl fmt::Display for Ty { fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { let generics = f.generic_params(db); let substs = make_substs(&generics); - Ty::FnDef(f.into(), substs) + let name = f.name(db); + Ty::FnDef { + def: f.into(), + name, + substs + } } fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig { @@ -1355,16 +1383,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Ty::Unknown } Expr::Call { callee, args } => { + // TODO: we should use turbofish hints like this: + // f::(x) let callee_ty = self.infer_expr(*callee, &Expectation::none()); // FIXME: so manu unnecessary clones let (param_tys, ret_ty) = match &callee_ty { Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), - Ty::FnDef(func, substs) => { - let fn_sig = func.signature(self.db); + Ty::FnDef { def, substs, .. } => { + let fn_sig = def.signature(self.db); // TODO: get input and return types from the fn_sig. // it contains typerefs which we can make into proper tys - let sig = get_func_sig(self.db, *func); + let sig = get_func_sig(self.db, *def); ( sig.input .iter() @@ -1405,16 +1435,41 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { Ty::FnPtr(sig) => { if sig.input.len() > 0 { - (&sig.input[0], &sig.input[1..], sig.output.clone()) + (sig.input[0].clone(), sig.input[1..].iter().cloned().collect(), sig.output.clone()) + } else { + (Ty::Unknown, Vec::new(), sig.output.clone()) + } + } + Ty::FnDef { def, substs, .. } => { + // TODO: fix deduplication with Expr::Call block above + // TODO: fix the ridiculous number of clones + let fn_sig = def.signature(self.db); + // TODO: get input and return types from the fn_sig. + // it contains typerefs which we can make into proper tys + + // check that len > 0 + let sig = get_func_sig(self.db, *def); + if sig.input.len() > 0 { + ( + sig.input[0].clone().subst(&substs), + sig.input[1..] + .iter() + .map(|ty| ty.clone().subst(&substs)) + .collect(), + sig.output.clone().subst(&substs), + ) } else { - (&Ty::Unknown, &[][..], sig.output.clone()) + (Ty::Unknown, Vec::new(), sig.output.clone()) } } - _ => (&Ty::Unknown, &[][..], Ty::Unknown), + _ => (Ty::Unknown, Vec::new(), Ty::Unknown), }; // TODO we would have to apply the autoderef/autoref steps here // to get the correct receiver type to unify... - self.unify(expected_receiver_ty, &receiver_ty); + // + // TODO: zip param_tys.chain(iter::repeat(Ty::Unknown)) above then its not so bad + // that we clone + self.unify(&expected_receiver_ty, &receiver_ty); for (i, arg) in args.iter().enumerate() { self.infer_expr( *arg, -- cgit v1.2.3 From aa06893a1493770f8009d098a5340f1a9ba13dec Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Sat, 26 Jan 2019 00:30:56 +0100 Subject: Add type params to FnSignature --- crates/ra_hir/src/code_model_api.rs | 5 + crates/ra_hir/src/code_model_impl/function.rs | 2 + crates/ra_hir/src/generics.rs | 3 +- crates/ra_hir/src/ty.rs | 126 ++++++++------------- .../src/ty/snapshots/tests__infer_backwards.snap | 8 +- .../src/ty/snapshots/tests__infer_binary_op.snap | 8 +- .../snapshots/tests__infer_function_generics.snap | 30 ++--- .../ty/snapshots/tests__infer_generic_chain.snap | 52 ++++----- .../src/ty/snapshots/tests__infer_paths.snap | 10 +- 9 files changed, 107 insertions(+), 137 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index defb9fd0a..a13da58d2 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -388,6 +388,7 @@ pub use crate::code_model_impl::function::ScopeEntryWithSyntax; #[derive(Debug, Clone, PartialEq, Eq)] pub struct FnSignature { pub(crate) name: Name, + pub(crate) type_params: Arc, pub(crate) args: Vec, pub(crate) ret_type: TypeRef, /// True if the first param is `self`. This is relevant to decide whether this @@ -413,6 +414,10 @@ impl FnSignature { pub fn has_self_param(&self) -> bool { self.has_self_param } + + pub fn generics(&self) -> &GenericParams { + &self.type_params + } } impl Function { diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index b4aa18540..f4beab6ae 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -58,6 +58,7 @@ impl FnSignature { args.push(type_ref); } } + let type_params = db.generic_params(func.into()); let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { TypeRef::from_ast(type_ref) } else { @@ -66,6 +67,7 @@ impl FnSignature { let sig = FnSignature { name, + type_params, args, ret_type, has_self_param, diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index a5501d543..64c20a462 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -49,8 +49,7 @@ impl GenericParams { Arc::new(generics) } - // FIXME: probably shouldnt be pub(crate) - pub(crate) fn fill(&mut self, node: &impl TypeParamsOwner) { + fn fill(&mut self, node: &impl TypeParamsOwner) { if let Some(params) = node.type_param_list() { self.fill_params(params) } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 9b08b9c97..43181ffc9 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -20,6 +20,7 @@ mod tests; pub(crate) mod method_resolution; use std::borrow::Cow; +use std::iter::repeat; use std::ops::Index; use std::sync::Arc; use std::{fmt, mem}; @@ -225,7 +226,7 @@ pub enum Ty { /// For display name: Name, /// Substitutions for the generic parameters of the type - substs: Substs + substs: Substs, }, /// A pointer to a function. Written as `fn() -> i32`. @@ -543,11 +544,7 @@ impl Ty { name, substs, }, - Ty::FnDef { def, name, .. } => Ty::FnDef { - def, - name, - substs, - }, + Ty::FnDef { def, name, .. } => Ty::FnDef { def, name, substs }, _ => self, } } @@ -651,30 +648,10 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { Ty::FnDef { def: f.into(), name, - substs + substs, } } -fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig { - let signature = f.signature(db); - let module = f.module(db); - let impl_block = f.impl_block(db); - let generics = f.generic_params(db); - let input = signature - .args() - .iter() - .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) - .collect::>(); - let output = Ty::from_hir( - db, - &module, - impl_block.as_ref(), - &generics, - signature.ret_type(), - ); - FnSig { input, output } -} - fn make_substs(generics: &GenericParams) -> Substs { Substs( generics @@ -946,9 +923,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.type_of_pat.insert(pat, ty); } - fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { - // TODO provide generics of function - let generics = GenericParams::default(); + fn make_ty(&mut self, type_ref: &TypeRef, generics: &GenericParams) -> Ty { let ty = Ty::from_hir( self.db, &self.module, @@ -1249,9 +1224,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Ty::Tuple(ref tuple_args) => &**tuple_args, _ => &[], }; - let expectations_iter = expectations - .into_iter() - .chain(std::iter::repeat(&Ty::Unknown)); + let expectations_iter = expectations.into_iter().chain(repeat(&Ty::Unknown)); let inner_tys = args .iter() @@ -1370,7 +1343,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { let expected = if let Some(type_ref) = arg_type { - let ty = self.make_ty(type_ref); + let ty = self.make_ty(type_ref, &GenericParams::default()); ty } else { Ty::Unknown @@ -1386,22 +1359,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // TODO: we should use turbofish hints like this: // f::(x) let callee_ty = self.infer_expr(*callee, &Expectation::none()); - // FIXME: so manu unnecessary clones let (param_tys, ret_ty) = match &callee_ty { Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), Ty::FnDef { def, substs, .. } => { let fn_sig = def.signature(self.db); - // TODO: get input and return types from the fn_sig. - // it contains typerefs which we can make into proper tys - - let sig = get_func_sig(self.db, *def); - ( - sig.input - .iter() - .map(|ty| ty.clone().subst(&substs)) - .collect(), - sig.output.clone().subst(&substs), - ) + let ret_ty = self + .make_ty(fn_sig.ret_type(), fn_sig.generics()) + .subst(&substs); + let param_tys = fn_sig + .args() + .iter() + .map(|type_ref| { + self.make_ty(type_ref, fn_sig.generics()).subst(&substs) + }) + .collect(); + (param_tys, ret_ty) } _ => { // not callable @@ -1409,11 +1381,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { (Vec::new(), Ty::Unknown) } }; - for (i, arg) in args.iter().enumerate() { - self.infer_expr( - *arg, - &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), - ); + let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); + for (arg, param) in args.iter().zip(param_iter) { + self.infer_expr(*arg, &Expectation::has_type(param)); } ret_ty } @@ -1435,46 +1405,39 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { Ty::FnPtr(sig) => { if sig.input.len() > 0 { - (sig.input[0].clone(), sig.input[1..].iter().cloned().collect(), sig.output.clone()) + ( + sig.input[0].clone(), + sig.input[1..].iter().cloned().collect(), + sig.output.clone(), + ) } else { (Ty::Unknown, Vec::new(), sig.output.clone()) } } Ty::FnDef { def, substs, .. } => { - // TODO: fix deduplication with Expr::Call block above - // TODO: fix the ridiculous number of clones let fn_sig = def.signature(self.db); - // TODO: get input and return types from the fn_sig. - // it contains typerefs which we can make into proper tys - - // check that len > 0 - let sig = get_func_sig(self.db, *def); - if sig.input.len() > 0 { - ( - sig.input[0].clone().subst(&substs), - sig.input[1..] - .iter() - .map(|ty| ty.clone().subst(&substs)) - .collect(), - sig.output.clone().subst(&substs), - ) + let ret_ty = self + .make_ty(fn_sig.ret_type(), fn_sig.generics()) + .subst(&substs); + + if fn_sig.args().len() > 0 { + let mut arg_iter = fn_sig.args().iter().map(|type_ref| { + self.make_ty(type_ref, fn_sig.generics()).subst(&substs) + }); + let receiver_ty = arg_iter.next().unwrap(); + (receiver_ty, arg_iter.collect(), ret_ty) } else { - (Ty::Unknown, Vec::new(), sig.output.clone()) + (Ty::Unknown, Vec::new(), ret_ty) } } _ => (Ty::Unknown, Vec::new(), Ty::Unknown), }; // TODO we would have to apply the autoderef/autoref steps here // to get the correct receiver type to unify... - // - // TODO: zip param_tys.chain(iter::repeat(Ty::Unknown)) above then its not so bad - // that we clone self.unify(&expected_receiver_ty, &receiver_ty); - for (i, arg) in args.iter().enumerate() { - self.infer_expr( - *arg, - &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), - ); + let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); + for (arg, param) in args.iter().zip(param_iter) { + self.infer_expr(*arg, &Expectation::has_type(param)); } ret_ty } @@ -1558,7 +1521,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Expr::Cast { expr, type_ref } => { let _inner_ty = self.infer_expr(*expr, &Expectation::none()); - let cast_ty = self.make_ty(type_ref); + let cast_ty = self.make_ty(type_ref, &GenericParams::default()); // TODO check the cast... cast_ty } @@ -1672,7 +1635,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } => { let decl_ty = type_ref .as_ref() - .map(|tr| self.make_ty(tr)) + .map(|tr| self.make_ty(tr, &GenericParams::default())) .unwrap_or(Ty::Unknown); let decl_ty = self.insert_type_vars(decl_ty); let ty = if let Some(expr) = initializer { @@ -1699,12 +1662,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn collect_fn_signature(&mut self, signature: &FnSignature) { let body = Arc::clone(&self.body); // avoid borrow checker problem + let generics = signature.generics(); for (type_ref, pat) in signature.args().iter().zip(body.params()) { - let ty = self.make_ty(type_ref); + let ty = self.make_ty(type_ref, generics); self.infer_pat(*pat, &ty); } - self.return_ty = self.make_ty(signature.ret_type()); + self.return_ty = self.make_ty(signature.ret_type(), generics); } fn infer_body(&mut self) { diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap index 5c74bd8c7..e6b39f151 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap @@ -1,8 +1,8 @@ --- -created: "2019-01-22T14:44:59.880187500+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.943309491+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [14; 15) 'x': u32 [22; 24) '{}': () @@ -10,7 +10,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs" [88; 89) 'a': u32 [92; 108) 'unknow...nction': [unknown] [92; 110) 'unknow...tion()': u32 -[116; 125) 'takes_u32': fn(u32) -> () +[116; 125) 'takes_u32': fn takes_u32 [116; 128) 'takes_u32(a)': () [126; 127) 'a': u32 [138; 139) 'b': i32 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap index c506bcadd..895c13ae6 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap @@ -1,8 +1,8 @@ --- -created: "2019-01-22T14:44:59.880187500+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.949540810+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [6; 7) 'x': bool [22; 34) '{ 0i32 }': i32 @@ -28,7 +28,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs" [174; 196) 'minus_...ONST_2': bool [189; 196) 'CONST_2': isize [206; 207) 'c': i32 -[210; 211) 'f': fn(bool) -> i32 +[210; 211) 'f': fn f [210; 219) 'f(z || y)': i32 [210; 223) 'f(z || y) + 5': i32 [212; 213) 'z': bool diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap index 7203ad1e2..efe0e7adf 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap @@ -1,21 +1,21 @@ --- -created: "2019-01-22T14:44:59.954958500+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.962273460+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- -[10; 11) 't': [unknown] -[21; 26) '{ t }': [unknown] -[23; 24) 't': [unknown] +[10; 11) 't': T +[21; 26) '{ t }': T +[23; 24) 't': T [38; 98) '{ ...(1); }': () -[44; 46) 'id': fn(T) -> T -[44; 52) 'id(1u32)': T +[44; 46) 'id': fn id +[44; 52) 'id(1u32)': u32 [47; 51) '1u32': u32 -[58; 68) 'id::': fn(T) -> T -[58; 71) 'id::(1)': T -[69; 70) '1': T -[81; 82) 'x': T -[90; 92) 'id': fn(T) -> T -[90; 95) 'id(1)': T -[93; 94) '1': T +[58; 68) 'id::': fn id +[58; 71) 'id::(1)': i32 +[69; 70) '1': i32 +[81; 82) 'x': u64 +[90; 92) 'id': fn id +[90; 95) 'id(1)': u64 +[93; 94) '1': u64 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap index 4435180a1..aaf8ccea5 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap @@ -1,36 +1,36 @@ --- -created: "2019-01-22T14:44:59.961936900+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.978506051+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [53; 57) 'self': A<[unknown]> [65; 87) '{ ... }': [unknown] [75; 79) 'self': A<[unknown]> [75; 81) 'self.x': [unknown] -[99; 100) 't': [unknown] -[110; 115) '{ t }': [unknown] -[112; 113) 't': [unknown] +[99; 100) 't': T +[110; 115) '{ t }': T +[112; 113) 't': T [135; 261) '{ ....x() }': i128 -[146; 147) 'x': T -[150; 151) '1': T -[162; 163) 'y': T -[166; 168) 'id': fn(T) -> T -[166; 171) 'id(x)': T -[169; 170) 'x': T -[182; 183) 'a': A -[186; 200) 'A { x: id(y) }': A -[193; 195) 'id': fn(T) -> T -[193; 198) 'id(y)': T -[196; 197) 'y': T -[211; 212) 'z': T -[215; 217) 'id': fn(T) -> T -[215; 222) 'id(a.x)': T -[218; 219) 'a': A -[218; 221) 'a.x': T -[233; 234) 'b': A -[237; 247) 'A { x: z }': A -[244; 245) 'z': T -[254; 255) 'b': A +[146; 147) 'x': i32 +[150; 151) '1': i32 +[162; 163) 'y': i32 +[166; 168) 'id': fn id +[166; 171) 'id(x)': i32 +[169; 170) 'x': i32 +[182; 183) 'a': A +[186; 200) 'A { x: id(y) }': A +[193; 195) 'id': fn id +[193; 198) 'id(y)': i32 +[196; 197) 'y': i32 +[211; 212) 'z': i32 +[215; 217) 'id': fn id +[215; 222) 'id(a.x)': i32 +[218; 219) 'a': A +[218; 221) 'a.x': i32 +[233; 234) 'b': A +[237; 247) 'A { x: z }': A +[244; 245) 'z': i32 +[254; 255) 'b': A [254; 259) 'b.x()': i128 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap index 0bceffaef..efca36058 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap @@ -1,16 +1,16 @@ --- -created: "2019-01-22T14:44:59.975899500+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.985011010+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [15; 20) '{ 1 }': u32 [17; 18) '1': u32 [48; 53) '{ 1 }': u32 [50; 51) '1': u32 [67; 91) '{ ...c(); }': () -[73; 74) 'a': fn() -> u32 +[73; 74) 'a': fn a [73; 76) 'a()': u32 -[82; 86) 'b::c': fn() -> u32 +[82; 86) 'b::c': fn c [82; 88) 'b::c()': u32 -- cgit v1.2.3 From 04748a0f16624a1893c1da28a35ca3e220c81fce Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Sat, 26 Jan 2019 00:48:57 +0100 Subject: Add missing ty test snapshot --- .../ra_hir/src/ty/snapshots/tests__generic_fn.snap | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap diff --git a/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap b/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap new file mode 100644 index 000000000..4436dd8aa --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap @@ -0,0 +1,23 @@ +--- +created: "2019-01-25T23:18:55.019197432+00:00" +creator: insta@0.5.2 +expression: "&result" +source: crates/ra_hir/src/ty/tests.rs +--- +[10; 11) 'x': T +[21; 30) '{ x }': T +[27; 28) 'x': T +[44; 45) 'x': &T +[56; 65) '{ x }': &T +[62; 63) 'x': &T +[77; 138) '{ ...(z); }': () +[87; 88) 'y': u32 +[91; 96) '10u32': u32 +[102; 104) 'id': fn id +[102; 107) 'id(y)': u32 +[105; 106) 'y': u32 +[117; 118) 'x': bool +[127; 132) 'clone': fn clone +[127; 135) 'clone(z)': bool +[133; 134) 'z': &bool + -- cgit v1.2.3 From 089b1c57c1774eb1aacec53828ce2d2648adff2d Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Sat, 26 Jan 2019 12:06:41 +0100 Subject: Address some issues flagged in review --- crates/ra_hir/src/code_model_api.rs | 11 ++---- crates/ra_hir/src/code_model_impl/function.rs | 10 ++--- crates/ra_hir/src/ty.rs | 43 +++++++++------------- .../ra_ide_api/src/completion/completion_item.rs | 2 +- 4 files changed, 26 insertions(+), 40 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index a13da58d2..e4008058c 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -388,8 +388,7 @@ pub use crate::code_model_impl::function::ScopeEntryWithSyntax; #[derive(Debug, Clone, PartialEq, Eq)] pub struct FnSignature { pub(crate) name: Name, - pub(crate) type_params: Arc, - pub(crate) args: Vec, + pub(crate) params: Vec, pub(crate) ret_type: TypeRef, /// True if the first param is `self`. This is relevant to decide whether this /// can be called as a method. @@ -401,8 +400,8 @@ impl FnSignature { &self.name } - pub fn args(&self) -> &[TypeRef] { - &self.args + pub fn params(&self) -> &[TypeRef] { + &self.params } pub fn ret_type(&self) -> &TypeRef { @@ -414,10 +413,6 @@ impl FnSignature { pub fn has_self_param(&self) -> bool { self.has_self_param } - - pub fn generics(&self) -> &GenericParams { - &self.type_params - } } impl Function { diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index f4beab6ae..e0dd4d629 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -32,7 +32,7 @@ impl FnSignature { .name() .map(|n| n.as_name()) .unwrap_or_else(Name::missing); - let mut args = Vec::new(); + let mut params = Vec::new(); let mut has_self_param = false; if let Some(param_list) = node.param_list() { if let Some(self_param) = param_list.self_param() { @@ -50,15 +50,14 @@ impl FnSignature { } } }; - args.push(self_type); + params.push(self_type); has_self_param = true; } for param in param_list.params() { let type_ref = TypeRef::from_ast_opt(param.type_ref()); - args.push(type_ref); + params.push(type_ref); } } - let type_params = db.generic_params(func.into()); let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { TypeRef::from_ast(type_ref) } else { @@ -67,8 +66,7 @@ impl FnSignature { let sig = FnSignature { name, - type_params, - args, + params, ret_type, has_self_param, }; diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 43181ffc9..3cf3eaded 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -34,7 +34,7 @@ use test_utils::tested_by; use crate::{ Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, - FnSignature, FnScopes, ModuleDef, AdtDef, + FnScopes, ModuleDef, AdtDef, db::HirDatabase, type_ref::{TypeRef, Mutability}, name::KnownName, @@ -1164,13 +1164,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = self.insert_type_vars(ty.apply_substs(substs)); (ty, Some(var.into())) } - TypableDef::Function(func) => { - let ty = type_for_fn(self.db, func); - let ty = self.insert_type_vars(ty.apply_substs(substs)); - // FIXME: is this right? - (ty, None) - } - TypableDef::Enum(_) => (Ty::Unknown, None), + TypableDef::Function(_) | TypableDef::Enum(_) => (Ty::Unknown, None), } } @@ -1363,15 +1357,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), Ty::FnDef { def, substs, .. } => { let fn_sig = def.signature(self.db); + let generic_params = def.generic_params(self.db); let ret_ty = self - .make_ty(fn_sig.ret_type(), fn_sig.generics()) + .make_ty(fn_sig.ret_type(), &generic_params) .subst(&substs); let param_tys = fn_sig - .args() + .params() .iter() - .map(|type_ref| { - self.make_ty(type_ref, fn_sig.generics()).subst(&substs) - }) + .map(|type_ref| self.make_ty(type_ref, &generic_params).subst(&substs)) .collect(); (param_tys, ret_ty) } @@ -1416,13 +1409,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Ty::FnDef { def, substs, .. } => { let fn_sig = def.signature(self.db); + let generic_params = def.generic_params(self.db); let ret_ty = self - .make_ty(fn_sig.ret_type(), fn_sig.generics()) + .make_ty(fn_sig.ret_type(), &generic_params) .subst(&substs); - if fn_sig.args().len() > 0 { - let mut arg_iter = fn_sig.args().iter().map(|type_ref| { - self.make_ty(type_ref, fn_sig.generics()).subst(&substs) + if fn_sig.params().len() > 0 { + let mut arg_iter = fn_sig.params().iter().map(|type_ref| { + self.make_ty(type_ref, &generic_params).subst(&substs) }); let receiver_ty = arg_iter.next().unwrap(); (receiver_ty, arg_iter.collect(), ret_ty) @@ -1660,15 +1654,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty } - fn collect_fn_signature(&mut self, signature: &FnSignature) { + fn collect_fn_signature(&mut self, func: Function) { let body = Arc::clone(&self.body); // avoid borrow checker problem - let generics = signature.generics(); - for (type_ref, pat) in signature.args().iter().zip(body.params()) { - let ty = self.make_ty(type_ref, generics); + let signature = func.signature(self.db); + let generics = func.generic_params(self.db); + for (type_ref, pat) in signature.params().iter().zip(body.params()) { + let ty = self.make_ty(type_ref, &generics); self.infer_pat(*pat, &ty); } - self.return_ty = self.make_ty(signature.ret_type(), generics); + self.return_ty = self.make_ty(signature.ret_type(), &generics); } fn infer_body(&mut self) { @@ -1687,9 +1682,7 @@ pub fn infer(db: &impl HirDatabase, func: Function) -> Arc { let impl_block = func.impl_block(db); let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); - let signature = func.signature(db); - ctx.collect_fn_signature(&signature); - + ctx.collect_fn_signature(func); ctx.infer_body(); Arc::new(ctx.resolve_all()) diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 6e9a68e40..b16ac2b28 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -240,7 +240,7 @@ impl Builder { if ctx.use_item_syntax.is_none() && !ctx.is_call { tested_by!(inserts_parens_for_function_calls); let sig = function.signature(ctx.db); - if sig.args().is_empty() || sig.has_self_param() && sig.args().len() == 1 { + if sig.params().is_empty() || sig.has_self_param() && sig.params().len() == 1 { self.insert_text = Some(format!("{}()$0", self.label)); } else { self.insert_text = Some(format!("{}($0)", self.label)); -- cgit v1.2.3 From 0da1e8b2f8709cbdb20912664878121d979a5213 Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Sat, 26 Jan 2019 18:47:22 +0100 Subject: Add a FnSig to Ty::FnDef --- crates/ra_hir/src/ty.rs | 102 +++++++++++++-------- .../ra_hir/src/ty/snapshots/tests__generic_fn.snap | 18 ++-- .../src/ty/snapshots/tests__infer_backwards.snap | 4 +- .../src/ty/snapshots/tests__infer_binary_op.snap | 4 +- .../snapshots/tests__infer_function_generics.snap | 14 +-- .../ty/snapshots/tests__infer_generic_chain.snap | 14 +-- .../src/ty/snapshots/tests__infer_paths.snap | 6 +- 7 files changed, 94 insertions(+), 68 deletions(-) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 3cf3eaded..9332aca9a 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -34,7 +34,7 @@ use test_utils::tested_by; use crate::{ Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, - FnScopes, ModuleDef, AdtDef, + FnSignature, FnScopes, ModuleDef, AdtDef, db::HirDatabase, type_ref::{TypeRef, Mutability}, name::KnownName, @@ -225,6 +225,8 @@ pub enum Ty { def: Function, /// For display name: Name, + /// Parameters and return type + sig: Arc, /// Substitutions for the generic parameters of the type substs: Substs, }, @@ -544,7 +546,12 @@ impl Ty { name, substs, }, - Ty::FnDef { def, name, .. } => Ty::FnDef { def, name, substs }, + Ty::FnDef { def, name, sig, .. } => Ty::FnDef { + def, + name, + sig, + substs, + }, _ => self, } } @@ -607,7 +614,9 @@ impl fmt::Display for Ty { .to_fmt(f)?; write!(f, " -> {}", sig.output) } - Ty::FnDef { name, substs, .. } => { + Ty::FnDef { + name, substs, sig, .. + } => { // don't have access to the param types here :-( // we could store them in the def, but not sure if it // is worth it @@ -618,7 +627,11 @@ impl fmt::Display for Ty { .separator(", ") .to_fmt(f)?; } - Ok(()) + join(sig.input.iter()) + .surround_with("(", ")") + .separator(", ") + .to_fmt(f)?; + write!(f, " -> {}", sig.output) } Ty::Adt { name, substs, .. } => { write!(f, "{}", name)?; @@ -641,12 +654,29 @@ impl fmt::Display for Ty { /// Compute the declared type of a function. This should not need to look at the /// function body. -fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { - let generics = f.generic_params(db); +fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { + let signature = def.signature(db); + let module = def.module(db); + let impl_block = def.impl_block(db); + let generics = def.generic_params(db); + let input = signature + .params() + .iter() + .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) + .collect::>(); + let output = Ty::from_hir( + db, + &module, + impl_block.as_ref(), + &generics, + signature.ret_type(), + ); + let sig = Arc::new(FnSig { input, output }); let substs = make_substs(&generics); - let name = f.name(db); + let name = def.name(db); Ty::FnDef { - def: f.into(), + def, + sig, name, substs, } @@ -923,7 +953,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.type_of_pat.insert(pat, ty); } - fn make_ty(&mut self, type_ref: &TypeRef, generics: &GenericParams) -> Ty { + fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { + // TODO provide generics of function + let generics = GenericParams::default(); let ty = Ty::from_hir( self.db, &self.module, @@ -1337,7 +1369,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { let expected = if let Some(type_ref) = arg_type { - let ty = self.make_ty(type_ref, &GenericParams::default()); + let ty = self.make_ty(type_ref); ty } else { Ty::Unknown @@ -1355,16 +1387,14 @@ 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::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), - Ty::FnDef { def, substs, .. } => { - let fn_sig = def.signature(self.db); - let generic_params = def.generic_params(self.db); - let ret_ty = self - .make_ty(fn_sig.ret_type(), &generic_params) - .subst(&substs); - let param_tys = fn_sig - .params() + Ty::FnDef { + def, substs, sig, .. + } => { + let ret_ty = sig.output.clone().subst(&substs); + let param_tys = sig + .input .iter() - .map(|type_ref| self.make_ty(type_ref, &generic_params).subst(&substs)) + .map(|ty| ty.clone().subst(&substs)) .collect(); (param_tys, ret_ty) } @@ -1407,17 +1437,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { (Ty::Unknown, Vec::new(), sig.output.clone()) } } - Ty::FnDef { def, substs, .. } => { - let fn_sig = def.signature(self.db); - let generic_params = def.generic_params(self.db); - let ret_ty = self - .make_ty(fn_sig.ret_type(), &generic_params) - .subst(&substs); - - if fn_sig.params().len() > 0 { - let mut arg_iter = fn_sig.params().iter().map(|type_ref| { - self.make_ty(type_ref, &generic_params).subst(&substs) - }); + Ty::FnDef { + def, substs, sig, .. + } => { + let ret_ty = sig.output.clone().subst(&substs); + + if sig.input.len() > 0 { + let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs)); let receiver_ty = arg_iter.next().unwrap(); (receiver_ty, arg_iter.collect(), ret_ty) } else { @@ -1515,7 +1541,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Expr::Cast { expr, type_ref } => { let _inner_ty = self.infer_expr(*expr, &Expectation::none()); - let cast_ty = self.make_ty(type_ref, &GenericParams::default()); + let cast_ty = self.make_ty(type_ref); // TODO check the cast... cast_ty } @@ -1629,7 +1655,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } => { let decl_ty = type_ref .as_ref() - .map(|tr| self.make_ty(tr, &GenericParams::default())) + .map(|tr| self.make_ty(tr)) .unwrap_or(Ty::Unknown); let decl_ty = self.insert_type_vars(decl_ty); let ty = if let Some(expr) = initializer { @@ -1654,16 +1680,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty } - fn collect_fn_signature(&mut self, func: Function) { + fn collect_fn_signature(&mut self, signature: &FnSignature) { let body = Arc::clone(&self.body); // avoid borrow checker problem - let signature = func.signature(self.db); - let generics = func.generic_params(self.db); for (type_ref, pat) in signature.params().iter().zip(body.params()) { - let ty = self.make_ty(type_ref, &generics); + let ty = self.make_ty(type_ref); self.infer_pat(*pat, &ty); } - self.return_ty = self.make_ty(signature.ret_type(), &generics); + self.return_ty = self.make_ty(signature.ret_type()); } fn infer_body(&mut self) { @@ -1682,7 +1706,9 @@ pub fn infer(db: &impl HirDatabase, func: Function) -> Arc { let impl_block = func.impl_block(db); let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); - ctx.collect_fn_signature(func); + let signature = func.signature(db); + ctx.collect_fn_signature(&signature); + ctx.infer_body(); Arc::new(ctx.resolve_all()) diff --git a/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap b/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap index 4436dd8aa..84fbe6e4c 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap @@ -1,23 +1,23 @@ --- -created: "2019-01-25T23:18:55.019197432+00:00" +created: "2019-01-26T17:46:03.963745056+00:00" creator: insta@0.5.2 expression: "&result" source: crates/ra_hir/src/ty/tests.rs --- -[10; 11) 'x': T -[21; 30) '{ x }': T -[27; 28) 'x': T -[44; 45) 'x': &T -[56; 65) '{ x }': &T -[62; 63) 'x': &T +[10; 11) 'x': [unknown] +[21; 30) '{ x }': [unknown] +[27; 28) 'x': [unknown] +[44; 45) 'x': &[unknown] +[56; 65) '{ x }': &[unknown] +[62; 63) 'x': &[unknown] [77; 138) '{ ...(z); }': () [87; 88) 'y': u32 [91; 96) '10u32': u32 -[102; 104) 'id': fn id +[102; 104) 'id': fn id(T) -> T [102; 107) 'id(y)': u32 [105; 106) 'y': u32 [117; 118) 'x': bool -[127; 132) 'clone': fn clone +[127; 132) 'clone': fn clone(&T) -> T [127; 135) 'clone(z)': bool [133; 134) 'z': &bool diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap index e6b39f151..f5840a934 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap @@ -1,5 +1,5 @@ --- -created: "2019-01-25T23:18:54.943309491+00:00" +created: "2019-01-26T17:46:03.842478456+00:00" creator: insta@0.5.2 expression: "&result" source: crates/ra_hir/src/ty/tests.rs @@ -10,7 +10,7 @@ source: crates/ra_hir/src/ty/tests.rs [88; 89) 'a': u32 [92; 108) 'unknow...nction': [unknown] [92; 110) 'unknow...tion()': u32 -[116; 125) 'takes_u32': fn takes_u32 +[116; 125) 'takes_u32': fn takes_u32(u32) -> () [116; 128) 'takes_u32(a)': () [126; 127) 'a': u32 [138; 139) 'b': i32 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap index 895c13ae6..b9dda2bc0 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap @@ -1,5 +1,5 @@ --- -created: "2019-01-25T23:18:54.949540810+00:00" +created: "2019-01-26T17:46:03.853259898+00:00" creator: insta@0.5.2 expression: "&result" source: crates/ra_hir/src/ty/tests.rs @@ -28,7 +28,7 @@ source: crates/ra_hir/src/ty/tests.rs [174; 196) 'minus_...ONST_2': bool [189; 196) 'CONST_2': isize [206; 207) 'c': i32 -[210; 211) 'f': fn f +[210; 211) 'f': fn f(bool) -> i32 [210; 219) 'f(z || y)': i32 [210; 223) 'f(z || y) + 5': i32 [212; 213) 'z': bool diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap index efe0e7adf..369705f84 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap @@ -1,21 +1,21 @@ --- -created: "2019-01-25T23:18:54.962273460+00:00" +created: "2019-01-26T17:46:03.856278205+00:00" creator: insta@0.5.2 expression: "&result" source: crates/ra_hir/src/ty/tests.rs --- -[10; 11) 't': T -[21; 26) '{ t }': T -[23; 24) 't': T +[10; 11) 't': [unknown] +[21; 26) '{ t }': [unknown] +[23; 24) 't': [unknown] [38; 98) '{ ...(1); }': () -[44; 46) 'id': fn id +[44; 46) 'id': fn id(T) -> T [44; 52) 'id(1u32)': u32 [47; 51) '1u32': u32 -[58; 68) 'id::': fn id +[58; 68) 'id::': fn id(T) -> T [58; 71) 'id::(1)': i32 [69; 70) '1': i32 [81; 82) 'x': u64 -[90; 92) 'id': fn id +[90; 92) 'id': fn id(T) -> T [90; 95) 'id(1)': u64 [93; 94) '1': u64 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap index aaf8ccea5..f21bffa75 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap @@ -1,5 +1,5 @@ --- -created: "2019-01-25T23:18:54.978506051+00:00" +created: "2019-01-26T17:46:03.866825843+00:00" creator: insta@0.5.2 expression: "&result" source: crates/ra_hir/src/ty/tests.rs @@ -8,23 +8,23 @@ source: crates/ra_hir/src/ty/tests.rs [65; 87) '{ ... }': [unknown] [75; 79) 'self': A<[unknown]> [75; 81) 'self.x': [unknown] -[99; 100) 't': T -[110; 115) '{ t }': T -[112; 113) 't': T +[99; 100) 't': [unknown] +[110; 115) '{ t }': [unknown] +[112; 113) 't': [unknown] [135; 261) '{ ....x() }': i128 [146; 147) 'x': i32 [150; 151) '1': i32 [162; 163) 'y': i32 -[166; 168) 'id': fn id +[166; 168) 'id': fn id(T) -> T [166; 171) 'id(x)': i32 [169; 170) 'x': i32 [182; 183) 'a': A [186; 200) 'A { x: id(y) }': A -[193; 195) 'id': fn id +[193; 195) 'id': fn id(T) -> T [193; 198) 'id(y)': i32 [196; 197) 'y': i32 [211; 212) 'z': i32 -[215; 217) 'id': fn id +[215; 217) 'id': fn id(T) -> T [215; 222) 'id(a.x)': i32 [218; 219) 'a': A [218; 221) 'a.x': i32 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap index efca36058..afbe2f747 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap @@ -1,5 +1,5 @@ --- -created: "2019-01-25T23:18:54.985011010+00:00" +created: "2019-01-26T17:46:03.928773630+00:00" creator: insta@0.5.2 expression: "&result" source: crates/ra_hir/src/ty/tests.rs @@ -9,8 +9,8 @@ source: crates/ra_hir/src/ty/tests.rs [48; 53) '{ 1 }': u32 [50; 51) '1': u32 [67; 91) '{ ...c(); }': () -[73; 74) 'a': fn a +[73; 74) 'a': fn a() -> u32 [73; 76) 'a()': u32 -[82; 86) 'b::c': fn c +[82; 86) 'b::c': fn c() -> u32 [82; 88) 'b::c()': u32 -- cgit v1.2.3 From f6eb44cd9e2a27d2004386c71fb6c72f79ba83b3 Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Sat, 26 Jan 2019 19:25:57 +0100 Subject: Use type information from the turbofish --- crates/ra_hir/src/ty.rs | 34 ++++++++++++++++++---- .../ra_hir/src/ty/snapshots/tests__generic_fn.snap | 7 +++-- .../snapshots/tests__infer_function_generics.snap | 8 ++--- crates/ra_hir/src/ty/tests.rs | 3 ++ 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 9332aca9a..00a71a42f 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -1157,6 +1157,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let typable = typable?; let ty = self.db.type_for_def(typable); let ty = self.insert_type_vars(ty); + + // try to get generic parameters from the path and add them to the + // function type substitutions + if let Ty::FnDef { ref def, .. } = ty { + let last_seg_bindings = path + .segments + .last() + .and_then(|segment| segment.args_and_bindings.as_ref()); + if let Some(generic_args) = last_seg_bindings { + let generic_params = def.generic_params(self.db); + if generic_args.args.len() == generic_params.params.len() { + let substs = Ty::substs_from_path( + self.db, + &self.module, + self.impl_block.as_ref(), + &generic_params, + path, + (*def).into(), + ); + return Some(ty.apply_substs(substs)); + } else { + // ERROR: incorrect number of type params + } + } + } + Some(ty) } @@ -1387,9 +1413,7 @@ 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::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), - Ty::FnDef { - def, substs, sig, .. - } => { + Ty::FnDef { substs, sig, .. } => { let ret_ty = sig.output.clone().subst(&substs); let param_tys = sig .input @@ -1437,9 +1461,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { (Ty::Unknown, Vec::new(), sig.output.clone()) } } - Ty::FnDef { - def, substs, sig, .. - } => { + Ty::FnDef { substs, sig, .. } => { let ret_ty = sig.output.clone().subst(&substs); if sig.input.len() > 0 { diff --git a/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap b/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap index 84fbe6e4c..85aeefa0c 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap @@ -1,5 +1,5 @@ --- -created: "2019-01-26T17:46:03.963745056+00:00" +created: "2019-01-26T18:16:16.568375+00:00" creator: insta@0.5.2 expression: "&result" source: crates/ra_hir/src/ty/tests.rs @@ -10,7 +10,7 @@ source: crates/ra_hir/src/ty/tests.rs [44; 45) 'x': &[unknown] [56; 65) '{ x }': &[unknown] [62; 63) 'x': &[unknown] -[77; 138) '{ ...(z); }': () +[77; 197) '{ ...(1); }': () [87; 88) 'y': u32 [91; 96) '10u32': u32 [102; 104) 'id': fn id(T) -> T @@ -20,4 +20,7 @@ source: crates/ra_hir/src/ty/tests.rs [127; 132) 'clone': fn clone(&T) -> T [127; 135) 'clone(z)': bool [133; 134) 'z': &bool +[173; 191) 'id::': fn id(T) -> T +[173; 194) 'id::(1)': i32 +[192; 193) '1': i32 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap index 369705f84..8ff6e55a6 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap @@ -1,5 +1,5 @@ --- -created: "2019-01-26T17:46:03.856278205+00:00" +created: "2019-01-26T18:16:16.530712344+00:00" creator: insta@0.5.2 expression: "&result" source: crates/ra_hir/src/ty/tests.rs @@ -11,9 +11,9 @@ source: crates/ra_hir/src/ty/tests.rs [44; 46) 'id': fn id(T) -> T [44; 52) 'id(1u32)': u32 [47; 51) '1u32': u32 -[58; 68) 'id::': fn id(T) -> T -[58; 71) 'id::(1)': i32 -[69; 70) '1': i32 +[58; 68) 'id::': fn id(T) -> T +[58; 71) 'id::(1)': i128 +[69; 70) '1': i128 [81; 82) 'x': u64 [90; 92) 'id': fn id(T) -> T [90; 95) 'id(1)': u64 diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 40913b164..fac566626 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -611,6 +611,9 @@ fn test() { let y = 10u32; id(y); let x: bool = clone(z); + + // bad turbofish - ignore! + id::(1); } "#, ); -- cgit v1.2.3 From 6249989e6c133792ff457896d4723c0eb0f42137 Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Sun, 27 Jan 2019 17:59:09 +0100 Subject: Process second review --- crates/ra_hir/src/ty.rs | 63 ++++++++++------------ .../ra_hir/src/ty/snapshots/tests__generic_fn.snap | 26 --------- .../src/ty/snapshots/tests__infer_type_param.snap | 26 +++++++++ crates/ra_hir/src/ty/tests.rs | 6 +-- 4 files changed, 56 insertions(+), 65 deletions(-) delete mode 100644 crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap create mode 100644 crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 00a71a42f..37715a903 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -470,12 +470,12 @@ impl Ty { } // add placeholders for args that were not provided // TODO: handle defaults - for _ in segment + let supplied_params = segment .args_and_bindings .as_ref() .map(|ga| ga.args.len()) - .unwrap_or(0)..def_generics.params.len() - { + .unwrap_or(0); + for _ in supplied_params..def_generics.params.len() { substs.push(Ty::Unknown); } assert_eq!(substs.len(), def_generics.params.len()); @@ -507,7 +507,20 @@ impl Ty { } sig_mut.output.walk_mut(f); } - Ty::FnDef { substs, .. } | Ty::Adt { substs, .. } => { + Ty::FnDef { substs, sig, .. } => { + let sig_mut = Arc::make_mut(sig); + for input in &mut sig_mut.input { + input.walk_mut(f); + } + sig_mut.output.walk_mut(f); + // Without an Arc::make_mut_slice, we can't avoid the clone here: + let mut v: Vec<_> = substs.0.iter().cloned().collect(); + for t in &mut v { + t.walk_mut(f); + } + substs.0 = v.into(); + } + Ty::Adt { substs, .. } => { // Without an Arc::make_mut_slice, we can't avoid the clone here: let mut v: Vec<_> = substs.0.iter().cloned().collect(); for t in &mut v { @@ -579,7 +592,7 @@ impl Ty { /// or function); so if `self` is `Option`, this returns the `u32`. fn substs(&self) -> Option { match self { - Ty::Adt { substs, .. } => Some(substs.clone()), + Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()), _ => None, } } @@ -617,9 +630,6 @@ impl fmt::Display for Ty { Ty::FnDef { name, substs, sig, .. } => { - // don't have access to the param types here :-( - // we could store them in the def, but not sure if it - // is worth it write!(f, "fn {}", name)?; if substs.0.len() > 0 { join(substs.0.iter()) @@ -1156,33 +1166,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .into(); let typable = typable?; let ty = self.db.type_for_def(typable); + let generics = GenericParams::default(); + let substs = Ty::substs_from_path( + self.db, + &self.module, + self.impl_block.as_ref(), + &generics, + path, + typable, + ); + let ty = ty.apply_substs(substs); let ty = self.insert_type_vars(ty); - // try to get generic parameters from the path and add them to the - // function type substitutions - if let Ty::FnDef { ref def, .. } = ty { - let last_seg_bindings = path - .segments - .last() - .and_then(|segment| segment.args_and_bindings.as_ref()); - if let Some(generic_args) = last_seg_bindings { - let generic_params = def.generic_params(self.db); - if generic_args.args.len() == generic_params.params.len() { - let substs = Ty::substs_from_path( - self.db, - &self.module, - self.impl_block.as_ref(), - &generic_params, - path, - (*def).into(), - ); - return Some(ty.apply_substs(substs)); - } else { - // ERROR: incorrect number of type params - } - } - } - Some(ty) } @@ -1408,8 +1403,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Ty::Unknown } Expr::Call { callee, args } => { - // TODO: we should use turbofish hints like this: - // f::(x) let callee_ty = self.infer_expr(*callee, &Expectation::none()); let (param_tys, ret_ty) = match &callee_ty { Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), diff --git a/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap b/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap deleted file mode 100644 index 85aeefa0c..000000000 --- a/crates/ra_hir/src/ty/snapshots/tests__generic_fn.snap +++ /dev/null @@ -1,26 +0,0 @@ ---- -created: "2019-01-26T18:16:16.568375+00:00" -creator: insta@0.5.2 -expression: "&result" -source: crates/ra_hir/src/ty/tests.rs ---- -[10; 11) 'x': [unknown] -[21; 30) '{ x }': [unknown] -[27; 28) 'x': [unknown] -[44; 45) 'x': &[unknown] -[56; 65) '{ x }': &[unknown] -[62; 63) 'x': &[unknown] -[77; 197) '{ ...(1); }': () -[87; 88) 'y': u32 -[91; 96) '10u32': u32 -[102; 104) 'id': fn id(T) -> T -[102; 107) 'id(y)': u32 -[105; 106) 'y': u32 -[117; 118) 'x': bool -[127; 132) 'clone': fn clone(&T) -> T -[127; 135) 'clone(z)': bool -[133; 134) 'z': &bool -[173; 191) 'id::': fn id(T) -> T -[173; 194) 'id::(1)': i32 -[192; 193) '1': i32 - diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap new file mode 100644 index 000000000..a99323264 --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap @@ -0,0 +1,26 @@ +--- +created: "2019-01-27T16:54:18.368427685+00:00" +creator: insta@0.5.2 +expression: "&result" +source: crates/ra_hir/src/ty/tests.rs +--- +[10; 11) 'x': [unknown] +[21; 30) '{ x }': [unknown] +[27; 28) 'x': [unknown] +[44; 45) 'x': &[unknown] +[56; 65) '{ x }': &[unknown] +[62; 63) 'x': &[unknown] +[77; 157) '{ ...(1); }': () +[87; 88) 'y': u32 +[91; 96) '10u32': u32 +[102; 104) 'id': fn id(T) -> T +[102; 107) 'id(y)': u32 +[105; 106) 'y': u32 +[117; 118) 'x': bool +[127; 132) 'clone': fn clone(&T) -> T +[127; 135) 'clone(z)': bool +[133; 134) 'z': &bool +[141; 151) 'id::': fn id(T) -> T +[141; 154) 'id::(1)': i128 +[152; 153) '1': i128 + diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index fac566626..ac12d974b 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -597,7 +597,7 @@ fn test() { #[test] fn infer_type_param() { check_inference( - "generic_fn", + "infer_type_param", r#" fn id(x: T) -> T { x @@ -611,9 +611,7 @@ fn test() { let y = 10u32; id(y); let x: bool = clone(z); - - // bad turbofish - ignore! - id::(1); + id::(1); } "#, ); -- cgit v1.2.3