1 //! Completion of names from the current scope in type position.
3 use hir::{HirDisplay, ScopeDef};
4 use syntax::{ast, AstNode, SyntaxKind};
7 context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation},
8 render::render_type_inference,
9 CompletionContext, Completions,
12 pub(crate) fn complete_type_path(
13 acc: &mut Completions,
14 ctx: &CompletionContext<'_>,
15 path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
16 location: &TypeLocation,
18 let _p = profile::span("complete_type_path");
20 let scope_def_applicable = |def| {
21 use hir::{GenericParam::*, ModuleDef::*};
23 ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
24 // no values in type places
25 ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false,
26 // unless its a constant in a generic arg list position
27 ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => {
28 matches!(location, TypeLocation::GenericArgList(_))
30 ScopeDef::ImplSelfType(_) => {
31 !matches!(location, TypeLocation::ImplTarget | TypeLocation::ImplTrait)
33 // Don't suggest attribute macros and derives.
34 ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
35 // Type things are fine
36 ScopeDef::ModuleDef(BuiltinType(_) | Adt(_) | Module(_) | Trait(_) | TypeAlias(_))
37 | ScopeDef::AdtSelfType(_)
39 | ScopeDef::GenericParam(TypeParam(_)) => true,
43 let add_assoc_item = |acc: &mut Completions, item| match item {
44 hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArgList(_)) => {
45 acc.add_const(ctx, ct)
47 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => (),
48 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
52 Qualified::TypeAnchor { ty: None, trait_: None } => ctx
55 .flat_map(|&it| hir::Trait::from(it).items(ctx.sema.db))
56 .for_each(|item| add_assoc_item(acc, item)),
57 Qualified::TypeAnchor { trait_: Some(trait_), .. } => {
58 trait_.items(ctx.sema.db).into_iter().for_each(|item| add_assoc_item(acc, item))
60 Qualified::TypeAnchor { ty: Some(ty), trait_: None } => {
61 ctx.iterate_path_candidates(&ty, |item| {
62 add_assoc_item(acc, item);
65 // Iterate assoc types separately
66 ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
67 if let hir::AssocItem::TypeAlias(ty) = item {
68 acc.add_type_alias(ctx, ty)
73 Qualified::With { resolution: None, .. } => {}
74 Qualified::With { resolution: Some(resolution), .. } => {
75 // Add associated types on type parameters and `Self`.
76 ctx.scope.assoc_type_shorthand_candidates(resolution, |_, alias| {
77 acc.add_type_alias(ctx, alias);
82 hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
83 let module_scope = module.scope(ctx.db, Some(ctx.module));
84 for (name, def) in module_scope {
85 if scope_def_applicable(def) {
86 acc.add_path_resolution(ctx, path_ctx, name, def);
90 hir::PathResolution::Def(
91 def @ (hir::ModuleDef::Adt(_)
92 | hir::ModuleDef::TypeAlias(_)
93 | hir::ModuleDef::BuiltinType(_)),
96 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
97 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
98 hir::ModuleDef::BuiltinType(builtin) => builtin.ty(ctx.db),
102 // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
103 // (where AssocType is defined on a trait, not an inherent impl)
105 ctx.iterate_path_candidates(&ty, |item| {
106 add_assoc_item(acc, item);
109 // Iterate assoc types separately
110 ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
111 if let hir::AssocItem::TypeAlias(ty) = item {
112 acc.add_type_alias(ctx, ty)
117 hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
118 // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
119 for item in t.items(ctx.db) {
120 add_assoc_item(acc, item);
123 hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
124 let ty = match resolution {
125 hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
126 hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
130 ctx.iterate_path_candidates(&ty, |item| {
131 add_assoc_item(acc, item);
137 Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
140 TypeLocation::TypeBound => {
141 acc.add_nameref_keywords_with_colon(ctx);
142 ctx.process_all_names(&mut |name, res| {
143 let add_resolution = match res {
144 ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
145 mac.is_fn_like(ctx.db)
148 hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_),
153 acc.add_path_resolution(ctx, path_ctx, name, res);
158 TypeLocation::GenericArgList(Some(arg_list)) => {
159 let in_assoc_type_arg = ctx
162 .any(|node| node.kind() == SyntaxKind::ASSOC_TYPE_ARG);
164 if !in_assoc_type_arg {
165 if let Some(path_seg) =
166 arg_list.syntax().parent().and_then(ast::PathSegment::cast)
171 .find_map(ast::TypeBound::cast)
174 if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(
176 ))) = ctx.sema.resolve_path(&path_seg.parent_path())
178 let arg_idx = arg_list
181 arg.syntax().text_range().end()
182 < ctx.original_token.text_range().start()
186 let n_required_params =
187 trait_.type_or_const_param_count(ctx.sema.db, true);
188 if arg_idx >= n_required_params {
190 .items_with_supertraits(ctx.sema.db)
193 if let hir::AssocItem::TypeAlias(alias) = it {
195 complete_assoc_type_in_generics_list
197 acc.add_type_alias_with_eq(ctx, alias);
202 trait_.type_or_const_param_count(ctx.sema.db, false);
203 if arg_idx >= n_params {
204 return; // only show assoc types
215 acc.add_nameref_keywords_with_colon(ctx);
216 ctx.process_all_names(&mut |name, def| {
217 if scope_def_applicable(def) {
218 acc.add_path_resolution(ctx, path_ctx, name, def);
225 pub(crate) fn complete_ascribed_type(
226 acc: &mut Completions,
227 ctx: &CompletionContext<'_>,
228 path_ctx: &PathCompletionCtx,
229 ascription: &TypeAscriptionTarget,
231 if !path_ctx.is_trivial_path() {
234 let x = match ascription {
235 TypeAscriptionTarget::Let(pat) | TypeAscriptionTarget::FnParam(pat) => {
236 ctx.sema.type_of_pat(pat.as_ref()?)
238 TypeAscriptionTarget::Const(exp) | TypeAscriptionTarget::RetType(exp) => {
239 ctx.sema.type_of_expr(exp.as_ref()?)
243 let ty_string = x.display_source_code(ctx.db, ctx.module.into()).ok()?;
244 acc.add(render_type_inference(ty_string, ctx));