diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 2854631c6f..ff041150b5 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -311,7 +311,11 @@ impl StructField { self.parent.variant_data(db).fields()[self.id].name.clone() } - pub fn ty(&self, db: &impl HirDatabase) -> Type { + /// Returns the type as in the signature of the struct (i.e., with + /// placeholder types for type parameters). This is good for showing + /// signature help, but not so good to actually get the type of the field + /// when you actually have a variable of the struct. + pub fn signature_ty(&self, db: &impl HirDatabase) -> Type { let var_id = self.parent.into(); let generic_def_id: GenericDefId = match self.parent { VariantDef::Struct(it) => it.id.into(), @@ -485,6 +489,10 @@ impl Adt { let subst = db.generic_defaults(self.into()); subst.iter().any(|ty| ty == &Ty::Unknown) } + + /// Turns this ADT into a type. Any type parameters of the ADT will be + /// turned into unknown types, which is good for e.g. finding the most + /// general set of completions, but will not look very nice when printed. pub fn ty(self, db: &impl HirDatabase) -> Type { let id = AdtId::from(self); Type::from_def(db, id.module(db).krate, id) @@ -1031,7 +1039,7 @@ impl Type { krate: CrateId, def: impl HasResolver + Into + Into, ) -> Type { - let substs = Substs::type_params(db, def); + let substs = Substs::build_for_def(db, def).fill_with_unknown().build(); let ty = db.ty(def.into()).subst(&substs); Type::new(db, krate, def, ty) } diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 2b35a38030..39d09a07fe 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -543,6 +543,20 @@ fn main() { assert_eq!(info.active_parameter, Some(1)); } + #[test] + fn generic_struct() { + let info = call_info( + r#" +struct TS(T); +fn main() { + let s = TS(<|>); +}"#, + ); + + assert_eq!(info.label(), "struct TS(T) -> TS"); + assert_eq!(info.active_parameter, Some(0)); + } + #[test] #[should_panic] fn cant_call_named_structs() { diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 65b3bf6e64..3db17f15ff 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs @@ -1005,4 +1005,36 @@ mod tests { "### ); } + + #[test] + fn completes_hashmap_new() { + assert_debug_snapshot!( + do_reference_completion( + r" + struct RandomState; + struct HashMap {} + + impl HashMap { + pub fn new() -> HashMap { } + } + fn foo() { + HashMap::<|> + } + " + ), + @r###" + [ + CompletionItem { + label: "new()", + source_range: [292; 292), + delete: [292; 292), + insert: "new()$0", + kind: Function, + lookup: "new", + detail: "pub fn new() -> HashMap", + }, + ] + "### + ); + } } diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index a4e9aefe2c..9108442445 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs @@ -273,8 +273,10 @@ impl Completions { pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { let is_deprecated = is_deprecated(variant, ctx.db); let name = variant.name(ctx.db); - let detail_types = - variant.fields(ctx.db).into_iter().map(|field| (field.name(ctx.db), field.ty(ctx.db))); + let detail_types = variant + .fields(ctx.db) + .into_iter() + .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); let detail = match variant.kind(ctx.db) { StructKind::Tuple | StructKind::Unit => { join(detail_types.map(|(_, t)| t.display(ctx.db).to_string())) diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index 2c4c932de9..ec1bbd5a03 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs @@ -64,7 +64,7 @@ impl FunctionSignature { .fields(db) .into_iter() .map(|field: hir::StructField| { - let ty = field.ty(db); + let ty = field.signature_ty(db); format!("{}", ty.display(db)) }) .collect(); @@ -102,7 +102,7 @@ impl FunctionSignature { .into_iter() .map(|field: hir::StructField| { let name = field.name(db); - let ty = field.ty(db); + let ty = field.signature_ty(db); format!("{}: {}", name, ty.display(db)) }) .collect();