diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index eaaff5a21f..0df6e97dd4 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs @@ -493,14 +493,14 @@ impl<'a> Printer<'a> { w!(self, "]"); } TypeRef::Fn(args_and_ret, varargs) => { - let (ret, args) = + let ((_, return_type), args) = args_and_ret.split_last().expect("TypeRef::Fn is missing return type"); w!(self, "fn("); - for (i, arg) in args.iter().enumerate() { + for (i, (_, typeref)) in args.iter().enumerate() { if i != 0 { w!(self, ", "); } - self.print_type_ref(arg); + self.print_type_ref(&typeref); } if *varargs { if !args.is_empty() { @@ -509,7 +509,7 @@ impl<'a> Printer<'a> { w!(self, "..."); } w!(self, ") -> "); - self.print_type_ref(ret); + self.print_type_ref(&return_type); } TypeRef::Macro(_ast_id) => { w!(self, ""); diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index cfc69feccc..ee8ef6caa3 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs @@ -1,9 +1,12 @@ //! HIR for references to types. Paths in these are not yet resolved. They can //! be directly created from an ast::TypeRef, without further queries. -use hir_expand::{name::Name, AstId, InFile}; +use hir_expand::{ + name::{AsName, Name}, + AstId, InFile, +}; use std::convert::TryInto; -use syntax::ast; +use syntax::ast::{self, HasName}; use crate::{body::LowerCtx, intern::Interned, path::Path}; @@ -89,7 +92,7 @@ pub enum TypeRef { Array(Box, ConstScalar), Slice(Box), /// A fn pointer. Last element of the vector is the return type. - Fn(Vec, bool /*varargs*/), + Fn(Vec<(Option, TypeRef)>, bool /*varargs*/), // For ImplTrait(Vec>), DynTrait(Vec>), @@ -188,11 +191,22 @@ impl TypeRef { is_varargs = param.dotdotdot_token().is_some(); } - pl.params().map(|p| p.ty()).map(|it| TypeRef::from_ast_opt(ctx, it)).collect() + pl.params() + .map(|it| { + let type_ref = TypeRef::from_ast_opt(ctx, it.ty()); + let name = match it.pat() { + Some(ast::Pat::IdentPat(it)) => Some( + it.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing), + ), + _ => None, + }; + (name, type_ref) + }) + .collect() } else { Vec::new() }; - params.push(ret_ty); + params.push((None, ret_ty)); TypeRef::Fn(params, is_varargs) } // for types are close enough for our purposes to the inner type for now... @@ -230,9 +244,10 @@ impl TypeRef { fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { f(type_ref); match type_ref { - TypeRef::Fn(types, _) | TypeRef::Tuple(types) => { - types.iter().for_each(|t| go(t, f)) + TypeRef::Fn(params, _) => { + params.iter().for_each(|(_, param_type)| go(¶m_type, f)) } + TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)), TypeRef::RawPtr(type_ref, _) | TypeRef::Reference(type_ref, ..) | TypeRef::Array(type_ref, _) diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index f02f4ac024..0e75ddeabc 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -1094,20 +1094,32 @@ impl HirDisplay for TypeRef { inner.hir_fmt(f)?; write!(f, "]")?; } - TypeRef::Fn(tys, is_varargs) => { + TypeRef::Fn(parameters, is_varargs) => { // FIXME: Function pointer qualifiers. write!(f, "fn(")?; - f.write_joined(&tys[..tys.len() - 1], ", ")?; - if *is_varargs { - write!(f, "{}...", if tys.len() == 1 { "" } else { ", " })?; - } - write!(f, ")")?; - let ret_ty = tys.last().unwrap(); - match ret_ty { - TypeRef::Tuple(tup) if tup.is_empty() => {} - _ => { - write!(f, " -> ")?; - ret_ty.hir_fmt(f)?; + if let Some(((_, return_type), function_parameters)) = parameters.split_last() { + for index in 0..function_parameters.len() { + let (param_name, param_type) = &function_parameters[index]; + if let Some(name) = param_name { + write!(f, "{}: ", name)?; + } + + param_type.hir_fmt(f)?; + + if index != function_parameters.len() - 1 { + write!(f, ", ")?; + } + } + if *is_varargs { + write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?; + } + write!(f, ")")?; + match &return_type { + TypeRef::Tuple(tup) if tup.is_empty() => {} + _ => { + write!(f, " -> ")?; + return_type.hir_fmt(f)?; + } } } } diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 55b1a67ea7..a140dd4057 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -201,7 +201,7 @@ impl<'a> TyLoweringContext<'a> { TypeRef::Placeholder => TyKind::Error.intern(Interner), TypeRef::Fn(params, is_varargs) => { let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { - Substitution::from_iter(Interner, params.iter().map(|tr| ctx.lower_ty(tr))) + Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr))) }); TyKind::Function(FnPointer { num_binders: 0, // FIXME lower `for<'a> fn()` correctly diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ed76c84ab4..c5c531c30b 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -1310,6 +1310,60 @@ fn test_hover_function_show_qualifiers() { ); } +#[test] +fn test_hover_function_show_types() { + check( + r#"fn foo$0(a: i32, b:i32) -> i32 { 0 }"#, + expect![[r#" + *foo* + + ```rust + test + ``` + + ```rust + fn foo(a: i32, b: i32) -> i32 + ``` + "#]], + ); +} + +#[test] +fn test_hover_function_pointer_show_identifiers() { + check( + r#"type foo$0 = fn(a: i32, b: i32) -> i32;"#, + expect![[r#" + *foo* + + ```rust + test + ``` + + ```rust + type foo = fn(a: i32, b: i32) -> i32 + ``` + "#]], + ); +} + +#[test] +fn test_hover_function_pointer_no_identifier() { + check( + r#"type foo$0 = fn(i32, _: i32) -> i32;"#, + expect![[r#" + *foo* + + ```rust + test + ``` + + ```rust + type foo = fn(i32, i32) -> i32 + ``` + "#]], + ); +} + #[test] fn test_hover_trait_show_qualifiers() { check_actions(