mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Lower bounds on trait definition, and resolve assoc types from super traits
This commit is contained in:
parent
4ae4d9c311
commit
60bdb66ef2
11 changed files with 102 additions and 38 deletions
|
@ -1,8 +1,11 @@
|
|||
pub(crate) mod src;
|
||||
pub(crate) mod docs;
|
||||
|
||||
use std::iter;
|
||||
use std::sync::Arc;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use ra_db::{CrateId, Edition, FileId, SourceRootId};
|
||||
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
|
||||
|
||||
|
@ -820,7 +823,43 @@ impl Trait {
|
|||
self.trait_data(db).items().to_vec()
|
||||
}
|
||||
|
||||
pub fn associated_type_by_name(self, db: &impl DefDatabase, name: Name) -> Option<TypeAlias> {
|
||||
fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
|
||||
let resolver = self.resolver(db);
|
||||
// returning the iterator directly doesn't easily work because of
|
||||
// lifetime problems, but since there usually shouldn't be more than a
|
||||
// few direct traits this should be fine (we could even use some kind of
|
||||
// SmallVec if performance is a concern)
|
||||
self.generic_params(db)
|
||||
.where_predicates
|
||||
.iter()
|
||||
.filter_map(|pred| match &pred.type_ref {
|
||||
TypeRef::Path(p) if p.as_ident() == Some(&crate::name::SELF_TYPE) => {
|
||||
pred.bound.as_path()
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.filter_map(|path| {
|
||||
match resolver.resolve_path_without_assoc_items(db, path).take_types() {
|
||||
Some(crate::Resolution::Def(ModuleDef::Trait(t))) => Some(t),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Returns an iterator over the whole super trait hierarchy (not including
|
||||
/// the trait itself). (This iterator may be infinite in case of circular
|
||||
/// super trait dependencies, which are possible in malformed code.)
|
||||
pub fn all_super_traits<'a>(
|
||||
self,
|
||||
db: &'a impl HirDatabase,
|
||||
) -> impl Iterator<Item = Trait> + 'a {
|
||||
self.direct_super_traits(db).into_iter().flat_map(move |t| {
|
||||
iter::once(t).chain(Box::new(t.all_super_traits(db)) as Box<dyn Iterator<Item = Trait>>)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
|
||||
let trait_data = self.trait_data(db);
|
||||
trait_data
|
||||
.items()
|
||||
|
@ -829,7 +868,18 @@ impl Trait {
|
|||
TraitItem::TypeAlias(t) => Some(*t),
|
||||
_ => None,
|
||||
})
|
||||
.find(|t| t.name(db) == name)
|
||||
.find(|t| &t.name(db) == name)
|
||||
}
|
||||
|
||||
pub fn associated_type_by_name_including_super_traits(
|
||||
self,
|
||||
db: &impl HirDatabase,
|
||||
name: &Name,
|
||||
) -> Option<TypeAlias> {
|
||||
iter::once(self)
|
||||
.chain(self.all_super_traits(db))
|
||||
.unique()
|
||||
.find_map(|t| t.associated_type_by_name(db, name))
|
||||
}
|
||||
|
||||
pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue