aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-04-27 23:40:32 +0100
committerJonas Schievink <[email protected]>2020-04-29 23:10:30 +0100
commit8c2670026a4c864a67a06bab654e203ed068f021 (patch)
tree95ed082f04067bcacfb40b1b871b64df3eb4be61 /crates
parent4ff3573e18114e044ed74e785f099a023ebfbf5d (diff)
Complete assoc. items on type parameters
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs10
-rw-r--r--crates/ra_hir/src/semantics.rs47
-rw-r--r--crates/ra_hir_ty/src/lib.rs3
-rw-r--r--crates/ra_hir_ty/src/lower.rs144
-rw-r--r--crates/ra_ide/src/completion/complete_qualified_path.rs273
5 files changed, 408 insertions, 69 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 3fb419571..af59aa1b6 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -953,6 +953,16 @@ impl TypeParam {
953 pub fn module(self, db: &dyn HirDatabase) -> Module { 953 pub fn module(self, db: &dyn HirDatabase) -> Module {
954 self.id.parent.module(db.upcast()).into() 954 self.id.parent.module(db.upcast()).into()
955 } 955 }
956
957 pub fn ty(self, db: &dyn HirDatabase) -> Type {
958 let resolver = self.id.parent.resolver(db.upcast());
959 let environment = TraitEnvironment::lower(db, &resolver);
960 let ty = Ty::Placeholder(self.id);
961 Type {
962 krate: self.id.parent.module(db.upcast()).krate,
963 ty: InEnvironment { value: ty, environment },
964 }
965 }
956} 966}
957 967
958// FIXME: rename from `ImplDef` to `Impl` 968// FIXME: rename from `ImplDef` to `Impl`
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 86bfb416c..687f83f60 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -9,6 +9,7 @@ use hir_def::{
9 AsMacroCall, TraitId, 9 AsMacroCall, TraitId,
10}; 10};
11use hir_expand::ExpansionInfo; 11use hir_expand::ExpansionInfo;
12use hir_ty::associated_types;
12use itertools::Itertools; 13use itertools::Itertools;
13use ra_db::{FileId, FileRange}; 14use ra_db::{FileId, FileRange};
14use ra_prof::profile; 15use ra_prof::profile;
@@ -24,8 +25,9 @@ use crate::{
24 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
25 source_analyzer::{resolve_hir_path, SourceAnalyzer}, 26 source_analyzer::{resolve_hir_path, SourceAnalyzer},
26 AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, 27 AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef,
27 Name, Origin, Path, ScopeDef, Trait, Type, TypeParam, 28 Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
28}; 29};
30use resolver::TypeNs;
29 31
30#[derive(Debug, Clone, PartialEq, Eq)] 32#[derive(Debug, Clone, PartialEq, Eq)]
31pub enum PathResolution { 33pub enum PathResolution {
@@ -40,6 +42,49 @@ pub enum PathResolution {
40 AssocItem(AssocItem), 42 AssocItem(AssocItem),
41} 43}
42 44
45impl PathResolution {
46 fn in_type_ns(self) -> Option<TypeNs> {
47 match self {
48 PathResolution::Def(ModuleDef::Adt(adt)) => Some(TypeNs::AdtId(adt.into())),
49 PathResolution::Def(ModuleDef::BuiltinType(builtin)) => {
50 Some(TypeNs::BuiltinType(builtin))
51 }
52 PathResolution::Def(ModuleDef::Const(_)) => None,
53 PathResolution::Def(ModuleDef::EnumVariant(_)) => None,
54 PathResolution::Def(ModuleDef::Function(_)) => None,
55 PathResolution::Def(ModuleDef::Module(_)) => None,
56 PathResolution::Def(ModuleDef::Static(_)) => None,
57 PathResolution::Def(ModuleDef::Trait(_)) => None,
58 PathResolution::Def(ModuleDef::TypeAlias(alias)) => {
59 Some(TypeNs::TypeAliasId(alias.into()))
60 }
61 PathResolution::Local(_) => None,
62 PathResolution::TypeParam(param) => Some(TypeNs::GenericParam(param.into())),
63 PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType(impl_def.into())),
64 PathResolution::Macro(_) => None,
65 PathResolution::AssocItem(AssocItem::Const(_)) => None,
66 PathResolution::AssocItem(AssocItem::Function(_)) => None,
67 PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => {
68 Some(TypeNs::TypeAliasId(alias.into()))
69 }
70 }
71 }
72
73 /// Returns an iterator over associated types that may be specified after this path (using
74 /// `Ty::Assoc` syntax).
75 pub fn assoc_type_shorthand_candidates<R>(
76 &self,
77 db: &dyn HirDatabase,
78 mut cb: impl FnMut(TypeAlias) -> Option<R>,
79 ) -> Option<R> {
80 if let Some(res) = self.clone().in_type_ns() {
81 associated_types(db, res, |_, _, id| cb(id.into()))
82 } else {
83 None
84 }
85 }
86}
87
43/// Primary API to get semantic information, like types, from syntax trees. 88/// Primary API to get semantic information, like types, from syntax trees.
44pub struct Semantics<'db, DB> { 89pub struct Semantics<'db, DB> {
45 pub db: &'db DB, 90 pub db: &'db DB,
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index a8ef32ec5..341a18683 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -66,7 +66,8 @@ pub use autoderef::autoderef;
66pub use infer::{InferTy, InferenceResult}; 66pub use infer::{InferTy, InferenceResult};
67pub use lower::CallableDef; 67pub use lower::CallableDef;
68pub use lower::{ 68pub use lower::{
69 callable_item_sig, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, 69 associated_types, callable_item_sig, ImplTraitLoweringMode, TyDefId, TyLoweringContext,
70 ValueTyDefId,
70}; 71};
71pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 72pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
72 73
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index a6f893037..67e5c1ccd 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -17,9 +17,9 @@ use hir_def::{
17 path::{GenericArg, Path, PathSegment, PathSegments}, 17 path::{GenericArg, Path, PathSegment, PathSegments},
18 resolver::{HasResolver, Resolver, TypeNs}, 18 resolver::{HasResolver, Resolver, TypeNs},
19 type_ref::{TypeBound, TypeRef}, 19 type_ref::{TypeBound, TypeRef},
20 AdtId, AssocContainerId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, 20 AdtId, AssocContainerId, AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId,
21 ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, 21 HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
22 VariantId, 22 UnionId, VariantId,
23}; 23};
24use ra_arena::map::ArenaMap; 24use ra_arena::map::ArenaMap;
25use ra_db::CrateId; 25use ra_db::CrateId;
@@ -34,6 +34,7 @@ use crate::{
34 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, 34 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate,
35 ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 35 ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
36}; 36};
37use hir_expand::name::Name;
37 38
38#[derive(Debug)] 39#[derive(Debug)]
39pub struct TyLoweringContext<'a> { 40pub struct TyLoweringContext<'a> {
@@ -383,61 +384,37 @@ impl Ty {
383 res: Option<TypeNs>, 384 res: Option<TypeNs>,
384 segment: PathSegment<'_>, 385 segment: PathSegment<'_>,
385 ) -> Ty { 386 ) -> Ty {
386 let traits_from_env: Vec<_> = match res { 387 if let Some(res) = res {
387 Some(TypeNs::SelfType(impl_id)) => match ctx.db.impl_trait(impl_id) { 388 let ty = associated_types(ctx.db, res, move |name, t, associated_ty| {
388 None => return Ty::Unknown, 389 if name == segment.name {
389 Some(trait_ref) => vec![trait_ref.value], 390 let substs = match ctx.type_param_mode {
390 }, 391 TypeParamLoweringMode::Placeholder => {
391 Some(TypeNs::GenericParam(param_id)) => { 392 // if we're lowering to placeholders, we have to put
392 let predicates = ctx.db.generic_predicates_for_param(param_id); 393 // them in now
393 let mut traits_: Vec<_> = predicates 394 let s = Substs::type_params(
394 .iter() 395 ctx.db,
395 .filter_map(|pred| match &pred.value { 396 ctx.resolver
396 GenericPredicate::Implemented(tr) => Some(tr.clone()), 397 .generic_def()
397 _ => None, 398 .expect("there should be generics if there's a generic param"),
398 }) 399 );
399 .collect(); 400 t.substs.clone().subst_bound_vars(&s)
400 // Handle `Self::Type` referring to own associated type in trait definitions 401 }
401 if let GenericDefId::TraitId(trait_id) = param_id.parent { 402 TypeParamLoweringMode::Variable => t.substs.clone(),
402 let generics = generics(ctx.db.upcast(), trait_id.into()); 403 };
403 if generics.params.types[param_id.local_id].provenance 404 // FIXME handle type parameters on the segment
404 == TypeParamProvenance::TraitSelf 405 return Some(Ty::Projection(ProjectionTy {
405 { 406 associated_ty,
406 let trait_ref = TraitRef { 407 parameters: substs,
407 trait_: trait_id, 408 }));
408 substs: Substs::bound_vars(&generics, DebruijnIndex::INNERMOST),
409 };
410 traits_.push(trait_ref);
411 }
412 } 409 }
413 traits_ 410
414 } 411 None
415 _ => return Ty::Unknown, 412 });
416 }; 413
417 let traits = traits_from_env.into_iter().flat_map(|t| all_super_trait_refs(ctx.db, t)); 414 ty.unwrap_or(Ty::Unknown)
418 for t in traits { 415 } else {
419 if let Some(associated_ty) = 416 Ty::Unknown
420 ctx.db.trait_data(t.trait_).associated_type_by_name(&segment.name)
421 {
422 let substs = match ctx.type_param_mode {
423 TypeParamLoweringMode::Placeholder => {
424 // if we're lowering to placeholders, we have to put
425 // them in now
426 let s = Substs::type_params(
427 ctx.db,
428 ctx.resolver
429 .generic_def()
430 .expect("there should be generics if there's a generic param"),
431 );
432 t.substs.subst_bound_vars(&s)
433 }
434 TypeParamLoweringMode::Variable => t.substs,
435 };
436 // FIXME handle (forbid) type parameters on the segment
437 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs });
438 }
439 } 417 }
440 Ty::Unknown
441 } 418 }
442 419
443 fn from_hir_path_inner( 420 fn from_hir_path_inner(
@@ -694,6 +671,61 @@ pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig {
694 } 671 }
695} 672}
696 673
674pub fn associated_types<R>(
675 db: &dyn HirDatabase,
676 res: TypeNs,
677 mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
678) -> Option<R> {
679 let traits_from_env: Vec<_> = match res {
680 TypeNs::SelfType(impl_id) => match db.impl_trait(impl_id) {
681 None => vec![],
682 Some(trait_ref) => vec![trait_ref.value],
683 },
684 TypeNs::GenericParam(param_id) => {
685 let predicates = db.generic_predicates_for_param(param_id);
686 let mut traits_: Vec<_> = predicates
687 .iter()
688 .filter_map(|pred| match &pred.value {
689 GenericPredicate::Implemented(tr) => Some(tr.clone()),
690 _ => None,
691 })
692 .collect();
693 // Handle `Self::Type` referring to own associated type in trait definitions
694 if let GenericDefId::TraitId(trait_id) = param_id.parent {
695 let generics = generics(db.upcast(), trait_id.into());
696 if generics.params.types[param_id.local_id].provenance
697 == TypeParamProvenance::TraitSelf
698 {
699 let trait_ref = TraitRef {
700 trait_: trait_id,
701 substs: Substs::bound_vars(&generics, DebruijnIndex::INNERMOST),
702 };
703 traits_.push(trait_ref);
704 }
705 }
706 traits_
707 }
708 _ => vec![],
709 };
710
711 for t in traits_from_env.into_iter().flat_map(move |t| all_super_trait_refs(db, t)) {
712 let data = db.trait_data(t.trait_);
713
714 for (name, assoc_id) in &data.items {
715 match assoc_id {
716 AssocItemId::TypeAliasId(alias) => {
717 if let Some(result) = cb(name, &t, *alias) {
718 return Some(result);
719 }
720 }
721 AssocItemId::FunctionId(_) | AssocItemId::ConstId(_) => {}
722 }
723 }
724 }
725
726 None
727}
728
697/// Build the type of all specific fields of a struct or enum variant. 729/// Build the type of all specific fields of a struct or enum variant.
698pub(crate) fn field_types_query( 730pub(crate) fn field_types_query(
699 db: &dyn HirDatabase, 731 db: &dyn HirDatabase,
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs
index dd10f74e6..69e789a49 100644
--- a/crates/ra_ide/src/completion/complete_qualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_qualified_path.rs
@@ -5,19 +5,30 @@ use ra_syntax::AstNode;
5use test_utils::tested_by; 5use test_utils::tested_by;
6 6
7use crate::completion::{CompletionContext, Completions}; 7use crate::completion::{CompletionContext, Completions};
8use rustc_hash::FxHashSet;
8 9
9pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) { 10pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
10 let path = match &ctx.path_prefix { 11 let path = match &ctx.path_prefix {
11 Some(path) => path.clone(), 12 Some(path) => path.clone(),
12 _ => return, 13 _ => return,
13 }; 14 };
14 let def = match ctx.scope().resolve_hir_path(&path) { 15 let scope = ctx.scope();
15 Some(PathResolution::Def(def)) => def, 16 let context_module = scope.module();
16 _ => return, 17
18 let res = if let Some(res) = scope.resolve_hir_path(&path) {
19 res
20 } else {
21 return;
17 }; 22 };
18 let context_module = ctx.scope().module(); 23
19 match def { 24 // Add associated types on type parameters and `Self`.
20 hir::ModuleDef::Module(module) => { 25 res.assoc_type_shorthand_candidates(ctx.db, |alias| {
26 acc.add_type_alias(ctx, alias);
27 None::<()>
28 });
29
30 match res {
31 PathResolution::Def(hir::ModuleDef::Module(module)) => {
21 let module_scope = module.scope(ctx.db, context_module); 32 let module_scope = module.scope(ctx.db, context_module);
22 for (name, def) in module_scope { 33 for (name, def) in module_scope {
23 if ctx.use_item_syntax.is_some() { 34 if ctx.use_item_syntax.is_some() {
@@ -35,7 +46,8 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
35 acc.add_resolution(ctx, name.to_string(), &def); 46 acc.add_resolution(ctx, name.to_string(), &def);
36 } 47 }
37 } 48 }
38 hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { 49 PathResolution::Def(def @ hir::ModuleDef::Adt(_))
50 | PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) => {
39 if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { 51 if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
40 for variant in e.variants(ctx.db) { 52 for variant in e.variants(ctx.db) {
41 acc.add_enum_variant(ctx, variant, None); 53 acc.add_enum_variant(ctx, variant, None);
@@ -46,8 +58,10 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
46 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), 58 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
47 _ => unreachable!(), 59 _ => unreachable!(),
48 }; 60 };
49 // Iterate assoc types separately 61
50 // FIXME: complete T::AssocType 62 // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
63 // (where AssocType is defined on a trait, not an inherent impl)
64
51 let krate = ctx.krate; 65 let krate = ctx.krate;
52 if let Some(krate) = krate { 66 if let Some(krate) = krate {
53 let traits_in_scope = ctx.scope().traits_in_scope(); 67 let traits_in_scope = ctx.scope().traits_in_scope();
@@ -65,6 +79,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
65 None::<()> 79 None::<()>
66 }); 80 });
67 81
82 // Iterate assoc types separately
68 ty.iterate_impl_items(ctx.db, krate, |item| { 83 ty.iterate_impl_items(ctx.db, krate, |item| {
69 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { 84 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
70 return None; 85 return None;
@@ -77,7 +92,8 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
77 }); 92 });
78 } 93 }
79 } 94 }
80 hir::ModuleDef::Trait(t) => { 95 PathResolution::Def(hir::ModuleDef::Trait(t)) => {
96 // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
81 for item in t.items(ctx.db) { 97 for item in t.items(ctx.db) {
82 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { 98 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
83 continue; 99 continue;
@@ -91,8 +107,38 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
91 } 107 }
92 } 108 }
93 } 109 }
110 PathResolution::TypeParam(_) | PathResolution::SelfType(_) => {
111 if let Some(krate) = ctx.krate {
112 let ty = match res {
113 PathResolution::TypeParam(param) => param.ty(ctx.db),
114 PathResolution::SelfType(impl_def) => impl_def.target_ty(ctx.db),
115 _ => return,
116 };
117
118 let traits_in_scope = ctx.scope().traits_in_scope();
119 let mut seen = FxHashSet::default();
120 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
121 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
122 return None;
123 }
124
125 // We might iterate candidates of a trait multiple times here, so deduplicate
126 // them.
127 if seen.insert(item) {
128 match item {
129 hir::AssocItem::Function(func) => {
130 acc.add_function(ctx, func, None);
131 }
132 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
133 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
134 }
135 }
136 None::<()>
137 });
138 }
139 }
94 _ => {} 140 _ => {}
95 }; 141 }
96} 142}
97 143
98#[cfg(test)] 144#[cfg(test)]
@@ -844,6 +890,211 @@ mod tests {
844 } 890 }
845 891
846 #[test] 892 #[test]
893 fn completes_ty_param_assoc_ty() {
894 assert_debug_snapshot!(
895 do_reference_completion(
896 "
897 //- /lib.rs
898 trait Super {
899 type Ty;
900 const CONST: u8;
901 fn func() {}
902 fn method(&self) {}
903 }
904
905 trait Sub: Super {
906 type SubTy;
907 const C2: ();
908 fn subfunc() {}
909 fn submethod(&self) {}
910 }
911
912 fn foo<T: Sub>() {
913 T::<|>
914 }
915 "
916 ),
917 @r###"
918 [
919 CompletionItem {
920 label: "C2",
921 source_range: 219..219,
922 delete: 219..219,
923 insert: "C2",
924 kind: Const,
925 detail: "const C2: ();",
926 },
927 CompletionItem {
928 label: "CONST",
929 source_range: 219..219,
930 delete: 219..219,
931 insert: "CONST",
932 kind: Const,
933 detail: "const CONST: u8;",
934 },
935 CompletionItem {
936 label: "SubTy",
937 source_range: 219..219,
938 delete: 219..219,
939 insert: "SubTy",
940 kind: TypeAlias,
941 detail: "type SubTy;",
942 },
943 CompletionItem {
944 label: "Ty",
945 source_range: 219..219,
946 delete: 219..219,
947 insert: "Ty",
948 kind: TypeAlias,
949 detail: "type Ty;",
950 },
951 CompletionItem {
952 label: "func()",
953 source_range: 219..219,
954 delete: 219..219,
955 insert: "func()$0",
956 kind: Function,
957 lookup: "func",
958 detail: "fn func()",
959 },
960 CompletionItem {
961 label: "method()",
962 source_range: 219..219,
963 delete: 219..219,
964 insert: "method()$0",
965 kind: Method,
966 lookup: "method",
967 detail: "fn method(&self)",
968 },
969 CompletionItem {
970 label: "subfunc()",
971 source_range: 219..219,
972 delete: 219..219,
973 insert: "subfunc()$0",
974 kind: Function,
975 lookup: "subfunc",
976 detail: "fn subfunc()",
977 },
978 CompletionItem {
979 label: "submethod()",
980 source_range: 219..219,
981 delete: 219..219,
982 insert: "submethod()$0",
983 kind: Method,
984 lookup: "submethod",
985 detail: "fn submethod(&self)",
986 },
987 ]
988 "###
989 );
990 }
991
992 #[test]
993 fn completes_self_param_assoc_ty() {
994 assert_debug_snapshot!(
995 do_reference_completion(
996 "
997 //- /lib.rs
998 trait Super {
999 type Ty;
1000 const CONST: u8 = 0;
1001 fn func() {}
1002 fn method(&self) {}
1003 }
1004
1005 trait Sub: Super {
1006 type SubTy;
1007 const C2: () = ();
1008 fn subfunc() {}
1009 fn submethod(&self) {}
1010 }
1011
1012 struct Wrap<T>(T);
1013 impl<T> Super for Wrap<T> {}
1014 impl<T> Sub for Wrap<T> {
1015 fn subfunc() {
1016 // Should be able to assume `Self: Sub + Super`
1017 Self::<|>
1018 }
1019 }
1020 "
1021 ),
1022 @r###"
1023 [
1024 CompletionItem {
1025 label: "C2",
1026 source_range: 365..365,
1027 delete: 365..365,
1028 insert: "C2",
1029 kind: Const,
1030 detail: "const C2: () = ();",
1031 },
1032 CompletionItem {
1033 label: "CONST",
1034 source_range: 365..365,
1035 delete: 365..365,
1036 insert: "CONST",
1037 kind: Const,
1038 detail: "const CONST: u8 = 0;",
1039 },
1040 CompletionItem {
1041 label: "SubTy",
1042 source_range: 365..365,
1043 delete: 365..365,
1044 insert: "SubTy",
1045 kind: TypeAlias,
1046 detail: "type SubTy;",
1047 },
1048 CompletionItem {
1049 label: "Ty",
1050 source_range: 365..365,
1051 delete: 365..365,
1052 insert: "Ty",
1053 kind: TypeAlias,
1054 detail: "type Ty;",
1055 },
1056 CompletionItem {
1057 label: "func()",
1058 source_range: 365..365,
1059 delete: 365..365,
1060 insert: "func()$0",
1061 kind: Function,
1062 lookup: "func",
1063 detail: "fn func()",
1064 },
1065 CompletionItem {
1066 label: "method()",
1067 source_range: 365..365,
1068 delete: 365..365,
1069 insert: "method()$0",
1070 kind: Method,
1071 lookup: "method",
1072 detail: "fn method(&self)",
1073 },
1074 CompletionItem {
1075 label: "subfunc()",
1076 source_range: 365..365,
1077 delete: 365..365,
1078 insert: "subfunc()$0",
1079 kind: Function,
1080 lookup: "subfunc",
1081 detail: "fn subfunc()",
1082 },
1083 CompletionItem {
1084 label: "submethod()",
1085 source_range: 365..365,
1086 delete: 365..365,
1087 insert: "submethod()$0",
1088 kind: Method,
1089 lookup: "submethod",
1090 detail: "fn submethod(&self)",
1091 },
1092 ]
1093 "###
1094 );
1095 }
1096
1097 #[test]
847 fn completes_type_alias() { 1098 fn completes_type_alias() {
848 assert_debug_snapshot!( 1099 assert_debug_snapshot!(
849 do_reference_completion( 1100 do_reference_completion(