use std::iter;
-use hir::ScopeDef;
+use hir::{ScopeDef, Trait};
use rustc_hash::FxHashSet;
use syntax::{ast, AstNode};
_ => return,
};
+ // special case `<_>::$0` as this doesn't resolve to anything.
+ if path.qualifier().is_none() {
+ if matches!(
+ path.segment().and_then(|it| it.kind()),
+ Some(ast::PathSegmentKind::Type {
+ type_ref: Some(ast::Type::InferType(_)),
+ trait_ref: None,
+ })
+ ) {
+ cov_mark::hit!(completion_type_anchor_empty);
+ ctx.scope
+ .visible_traits()
+ .into_iter()
+ .flat_map(|it| Trait::from(it).items(ctx.sema.db))
+ .for_each(|item| add_assoc_item(acc, ctx, item));
+ return;
+ }
+ }
+
let resolution = match ctx.sema.resolve_path(path) {
Some(res) => res,
None => return,
};
- let context_module = ctx.scope.module();
+ let context_module = ctx.module;
match ctx.completion_location {
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
}
}
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
- acc.add_resolution(ctx, name, &def);
+ acc.add_resolution(ctx, name, def);
}
}
}
match kind {
Some(PathKind::Vis { .. }) => {
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
- if let Some(current_module) = ctx.scope.module() {
+ if let Some(current_module) = ctx.module {
if let Some(next) = current_module
.path_to_root(ctx.db)
.into_iter()
.next()
{
if let Some(name) = next.name(ctx.db) {
- acc.add_resolution(ctx, name, &ScopeDef::ModuleDef(next.into()));
+ acc.add_resolution(ctx, name, ScopeDef::ModuleDef(next.into()));
}
}
}
_ => false,
};
if add_resolution {
- acc.add_resolution(ctx, name, &def);
+ acc.add_resolution(ctx, name, def);
}
}
}
};
if add_resolution {
- acc.add_resolution(ctx, name, &def);
+ acc.add_resolution(ctx, name, def);
}
}
}
hir::PathResolution::Def(
- def
- @
- (hir::ModuleDef::Adt(_)
+ def @ (hir::ModuleDef::Adt(_)
| hir::ModuleDef::TypeAlias(_)
| hir::ModuleDef::BuiltinType(_)),
) => {
ty
}
hir::ModuleDef::BuiltinType(builtin) => {
- let module = match ctx.scope.module() {
+ let module = match ctx.module {
Some(it) => it,
None => return,
};
let krate = ctx.krate;
if let Some(krate) = krate {
let traits_in_scope = ctx.scope.visible_traits();
- ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
- add_assoc_item(acc, ctx, item);
- None::<()>
- });
+ ty.iterate_path_candidates(
+ ctx.db,
+ krate,
+ &traits_in_scope,
+ ctx.module,
+ None,
+ |_ty, item| {
+ add_assoc_item(acc, ctx, item);
+ None::<()>
+ },
+ );
// Iterate assoc types separately
ty.iterate_assoc_items(ctx.db, krate, |item| {
let traits_in_scope = ctx.scope.visible_traits();
let mut seen = FxHashSet::default();
- ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
- // We might iterate candidates of a trait multiple times here, so deduplicate
- // them.
- if seen.insert(item) {
- add_assoc_item(acc, ctx, item);
- }
- None::<()>
- });
+ ty.iterate_path_candidates(
+ ctx.db,
+ krate,
+ &traits_in_scope,
+ ctx.module,
+ None,
+ |_ty, item| {
+ // We might iterate candidates of a trait multiple times here, so deduplicate
+ // them.
+ if seen.insert(item) {
+ add_assoc_item(acc, ctx, item);
+ }
+ None::<()>
+ },
+ );
}
}
hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac),
"#,
expect![[r#"
fn public_method() fn()
- ct PUBLIC_CONST pub const PUBLIC_CONST: u32;
- ta PublicType pub type PublicType;
+ ct PUBLIC_CONST pub const PUBLIC_CONST: u32
+ ta PublicType pub type PublicType = u32
"#]],
);
}
fn foo<T: Sub>() { T::$0 }
"#,
expect![[r#"
- ta SubTy (as Sub) type SubTy;
- ta Ty (as Super) type Ty;
- ct C2 (as Sub) const C2: ();
+ ta SubTy (as Sub) type SubTy
+ ta Ty (as Super) type Ty
+ ct C2 (as Sub) const C2: ()
fn subfunc() (as Sub) fn()
me submethod(…) (as Sub) fn(&self)
- ct CONST (as Super) const CONST: u8;
+ ct CONST (as Super) const CONST: u8
fn func() (as Super) fn()
me method(…) (as Super) fn(&self)
"#]],
}
"#,
expect![[r#"
- ta SubTy (as Sub) type SubTy;
- ta Ty (as Super) type Ty;
- ct CONST (as Super) const CONST: u8;
+ ta SubTy (as Sub) type SubTy
+ ta Ty (as Super) type Ty
+ ct CONST (as Super) const CONST: u8
fn func() (as Super) fn()
me method(…) (as Super) fn(&self)
- ct C2 (as Sub) const C2: ();
+ ct C2 (as Sub) const C2: ()
fn subfunc() (as Sub) fn()
me submethod(…) (as Sub) fn(&self)
"#]],
}
"#,
expect![[r#"
- ct MAX pub const MAX: Self;
+ ct MAX pub const MAX: Self
me func(…) fn(self)
"#]],
);
expect![[r#""#]],
)
}
+
+ #[test]
+ fn type_anchor_empty() {
+ cov_mark::check!(completion_type_anchor_empty);
+ check(
+ r#"
+trait Foo {
+ fn foo() -> Self;
+}
+struct Bar;
+impl Foo for Bar {
+ fn foo() -> {
+ Bar
+ }
+}
+fn bar() -> Bar {
+ <_>::$0
+}
+"#,
+ expect![[r#"
+ fn foo() (as Foo) fn() -> Self
+ "#]],
+ )
+ }
}