mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 14:33:29 +00:00
Use traits from where clauses for method resolution
E.g. if we have `T: some::Trait`, we can call methods from that trait without it needing to be in scope.
This commit is contained in:
parent
d21cdf3c99
commit
a1776b27c7
4 changed files with 44 additions and 21 deletions
|
@ -847,16 +847,22 @@ impl Trait {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over the whole super trait hierarchy (not including
|
/// Returns an iterator over the whole super trait hierarchy (including the
|
||||||
/// the trait itself). (This iterator may be infinite in case of circular
|
/// trait itself).
|
||||||
/// super trait dependencies, which are possible in malformed code.)
|
|
||||||
pub fn all_super_traits<'a>(
|
pub fn all_super_traits<'a>(
|
||||||
self,
|
self,
|
||||||
db: &'a impl HirDatabase,
|
db: &'a impl HirDatabase,
|
||||||
) -> impl Iterator<Item = Trait> + 'a {
|
) -> impl Iterator<Item = Trait> + 'a {
|
||||||
self.direct_super_traits(db).into_iter().flat_map(move |t| {
|
self.all_super_traits_inner(db).unique()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_super_traits_inner<'a>(
|
||||||
|
self,
|
||||||
|
db: &'a impl HirDatabase,
|
||||||
|
) -> impl Iterator<Item = Trait> + 'a {
|
||||||
|
iter::once(self).chain(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>>)
|
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> {
|
pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
|
||||||
|
@ -876,10 +882,7 @@ impl Trait {
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
name: &Name,
|
name: &Name,
|
||||||
) -> Option<TypeAlias> {
|
) -> Option<TypeAlias> {
|
||||||
iter::once(self)
|
self.all_super_traits(db).find_map(|t| t.associated_type_by_name(db, name))
|
||||||
.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> {
|
pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
|
||||||
|
|
|
@ -212,7 +212,13 @@ fn iterate_trait_method_candidates<T>(
|
||||||
// FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
|
// FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
|
||||||
let env = lower::trait_env(db, resolver);
|
let env = lower::trait_env(db, resolver);
|
||||||
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
|
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
|
||||||
let traits = ty.value.inherent_trait().into_iter().chain(resolver.traits_in_scope(db));
|
let inherent_trait = ty.value.inherent_trait().into_iter();
|
||||||
|
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
|
||||||
|
let traits_from_env = env
|
||||||
|
.trait_predicates_for_self_ty(&ty.value)
|
||||||
|
.map(|tr| tr.trait_)
|
||||||
|
.flat_map(|t| t.all_super_traits(db));
|
||||||
|
let traits = inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db));
|
||||||
'traits: for t in traits {
|
'traits: for t in traits {
|
||||||
let data = t.trait_data(db);
|
let data = t.trait_data(db);
|
||||||
|
|
||||||
|
|
|
@ -3660,8 +3660,7 @@ fn test<T: foo::Trait>(x: T) {
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
// FIXME should be u32
|
assert_eq!(t, "u32");
|
||||||
assert_eq!(t, "{unknown}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -3673,8 +3672,8 @@ mod foo {
|
||||||
fn foo(&self) -> u32 {}
|
fn foo(&self) -> u32 {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trait Trait1: SuperTrait {}
|
trait Trait1: foo::SuperTrait {}
|
||||||
trait Trait2 where Self: SuperTrait {}
|
trait Trait2 where Self: foo::SuperTrait {}
|
||||||
|
|
||||||
fn test<T: Trait1, U: Trait2>(x: T, y: U) {
|
fn test<T: Trait1, U: Trait2>(x: T, y: U) {
|
||||||
x.foo();
|
x.foo();
|
||||||
|
@ -3684,13 +3683,13 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) {
|
||||||
@r###"
|
@r###"
|
||||||
[50; 54) 'self': &Self
|
[50; 54) 'self': &Self
|
||||||
[63; 65) '{}': ()
|
[63; 65) '{}': ()
|
||||||
[172; 173) 'x': T
|
[182; 183) 'x': T
|
||||||
[178; 179) 'y': U
|
[188; 189) 'y': U
|
||||||
[184; 213) '{ ...o(); }': ()
|
[194; 223) '{ ...o(); }': ()
|
||||||
[190; 191) 'x': T
|
[200; 201) 'x': T
|
||||||
[190; 197) 'x.foo()': {unknown}
|
[200; 207) 'x.foo()': {unknown}
|
||||||
[203; 204) 'y': U
|
[213; 214) 'y': U
|
||||||
[203; 210) 'y.foo()': {unknown}
|
[213; 220) 'y.foo()': {unknown}
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,21 @@ pub struct TraitEnvironment {
|
||||||
pub predicates: Vec<GenericPredicate>,
|
pub predicates: Vec<GenericPredicate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TraitEnvironment {
|
||||||
|
/// Returns trait refs with the given self type which are supposed to hold
|
||||||
|
/// in this trait env. E.g. if we are in `foo<T: SomeTrait>()`, this will
|
||||||
|
/// find that `T: SomeTrait` if we call it for `T`.
|
||||||
|
pub(crate) fn trait_predicates_for_self_ty<'a>(
|
||||||
|
&'a self,
|
||||||
|
ty: &'a Ty,
|
||||||
|
) -> impl Iterator<Item = &'a TraitRef> + 'a {
|
||||||
|
self.predicates.iter().filter_map(move |pred| match pred {
|
||||||
|
GenericPredicate::Implemented(tr) if tr.self_ty() == ty => Some(tr),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Something (usually a goal), along with an environment.
|
/// Something (usually a goal), along with an environment.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct InEnvironment<T> {
|
pub struct InEnvironment<T> {
|
||||||
|
|
Loading…
Reference in a new issue