Auto merge of #12198 - jonas-schievink:ide-resolve-supertrait-assoc-types, r=jonas-schievink

fix: Resolve assoc. types of supertraits in the IDE layer

Fixes https://github.com/rust-lang/rust-analyzer/issues/12166
This commit is contained in:
bors 2022-05-09 15:40:45 +00:00
commit ab558053f5
5 changed files with 34 additions and 7 deletions

View file

@ -54,7 +54,7 @@ use hir_def::{
}; };
use hir_expand::{name::name, MacroCallKind}; use hir_expand::{name::name, MacroCallKind};
use hir_ty::{ use hir_ty::{
autoderef, all_super_traits, autoderef,
consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt}, consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt},
diagnostics::BodyValidationDiagnostic, diagnostics::BodyValidationDiagnostic,
method_resolution::{self, TyFingerprint}, method_resolution::{self, TyFingerprint},
@ -1676,6 +1676,11 @@ impl Trait {
db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect() db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
} }
pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
let traits = all_super_traits(db.upcast(), self.into());
traits.iter().flat_map(|tr| Trait::from(*tr).items(db)).collect()
}
pub fn is_auto(self, db: &dyn HirDatabase) -> bool { pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
db.trait_data(self.id).is_auto db.trait_data(self.id).is_auto
} }

View file

@ -168,8 +168,9 @@ pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext)
if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) = if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) =
ctx.sema.resolve_path(&path_seg.parent_path()) ctx.sema.resolve_path(&path_seg.parent_path())
{ {
trait_.items(ctx.sema.db).into_iter().for_each(|it| { trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each(|it| {
if let hir::AssocItem::TypeAlias(alias) = it { if let hir::AssocItem::TypeAlias(alias) = it {
cov_mark::hit!(complete_assoc_type_in_generics_list);
acc.add_type_alias_with_eq(ctx, alias) acc.add_type_alias_with_eq(ctx, alias)
} }
}); });

View file

@ -336,9 +336,13 @@ fn foo<'lt, T, const C: usize>() {
#[test] #[test]
fn completes_types_and_const_in_arg_list() { fn completes_types_and_const_in_arg_list() {
cov_mark::check!(complete_assoc_type_in_generics_list);
check( check(
r#" r#"
trait Trait2 { trait Trait1 {
type Super;
}
trait Trait2: Trait1 {
type Foo; type Foo;
} }
@ -348,14 +352,16 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
ct CONST ct CONST
cp CONST_PARAM cp CONST_PARAM
en Enum en Enum
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
st Record st Record
st Tuple st Tuple
st Unit st Unit
tt Trait tt Trait
tt Trait1
tt Trait2 tt Trait2
ta Foo = (as Trait2) type Foo ta Foo = (as Trait2) type Foo
ta Super = (as Trait1) type Super
tp T tp T
un Union un Union
bt u32 bt u32

View file

@ -386,9 +386,8 @@ impl NameRefClass {
let containing_path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; let containing_path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
let resolved = sema.resolve_path(&containing_path)?; let resolved = sema.resolve_path(&containing_path)?;
if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved { if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved {
// FIXME: resolve in supertraits
if let Some(ty) = tr if let Some(ty) = tr
.items(sema.db) .items_with_supertraits(sema.db)
.iter() .iter()
.filter_map(|&assoc| match assoc { .filter_map(|&assoc| match assoc {
hir::AssocItem::TypeAlias(it) => Some(it), hir::AssocItem::TypeAlias(it) => Some(it),

View file

@ -1012,6 +1012,22 @@ fn f() -> impl Iterator<Item$0 = u8> {}
); );
} }
#[test]
fn goto_def_for_super_assoc_ty_in_path() {
check(
r#"
trait Super {
type Item;
//^^^^
}
trait Sub: Super {}
fn f() -> impl Sub<Item$0 = u8> {}
"#,
);
}
#[test] #[test]
fn unknown_assoc_ty() { fn unknown_assoc_ty() {
check_unresolved( check_unresolved(