Merge #4484
4484: Allow calling dyn trait super trait methods without the super trait in scope r=flodiebold a=flodiebold This also removes some vestiges of the old impl trait support which I think aren't currently in use. Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
commit
8944a9b35a
@ -808,15 +808,13 @@ impl Ty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If this is an `impl Trait` or `dyn Trait`, returns that trait.
|
/// If this is a `dyn Trait`, returns that trait.
|
||||||
pub fn inherent_trait(&self) -> Option<TraitId> {
|
pub fn dyn_trait(&self) -> Option<TraitId> {
|
||||||
match self {
|
match self {
|
||||||
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred {
|
||||||
predicates.iter().find_map(|pred| match pred {
|
GenericPredicate::Implemented(tr) => Some(tr.trait_),
|
||||||
GenericPredicate::Implemented(tr) => Some(tr.trait_),
|
_ => None,
|
||||||
_ => None,
|
}),
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,8 +408,9 @@ fn iterate_trait_method_candidates<T>(
|
|||||||
receiver_ty: Option<&Canonical<Ty>>,
|
receiver_ty: Option<&Canonical<Ty>>,
|
||||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
|
// if ty is `dyn Trait`, the trait doesn't need to be in scope
|
||||||
let inherent_trait = self_ty.value.inherent_trait().into_iter();
|
let inherent_trait =
|
||||||
|
self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
|
||||||
let env_traits = if let Ty::Placeholder(_) = self_ty.value {
|
let env_traits = if let Ty::Placeholder(_) = self_ty.value {
|
||||||
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
|
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
|
||||||
env.trait_predicates_for_self_ty(&self_ty.value)
|
env.trait_predicates_for_self_ty(&self_ty.value)
|
||||||
@ -601,11 +602,6 @@ pub fn implements_trait(
|
|||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
trait_: TraitId,
|
trait_: TraitId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if ty.value.inherent_trait() == Some(trait_) {
|
|
||||||
// FIXME this is a bit of a hack, since Chalk should say the same thing
|
|
||||||
// anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let goal = generic_implements_goal(db, env, trait_, ty.clone());
|
let goal = generic_implements_goal(db, env, trait_, ty.clone());
|
||||||
let solution = db.trait_solve(krate, goal);
|
let solution = db.trait_solve(krate, goal);
|
||||||
|
|
||||||
|
@ -1096,3 +1096,34 @@ fn test() { (S {}).method()<|>; }
|
|||||||
);
|
);
|
||||||
assert_eq!(t, "()");
|
assert_eq!(t, "()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dyn_trait_super_trait_not_in_scope() {
|
||||||
|
assert_snapshot!(
|
||||||
|
infer(r#"
|
||||||
|
mod m {
|
||||||
|
pub trait SuperTrait {
|
||||||
|
fn foo(&self) -> u32 { 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trait Trait: m::SuperTrait {}
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
impl m::SuperTrait for S {}
|
||||||
|
impl Trait for S {}
|
||||||
|
|
||||||
|
fn test(d: &dyn Trait) {
|
||||||
|
d.foo();
|
||||||
|
}
|
||||||
|
"#),
|
||||||
|
@r###"
|
||||||
|
52..56 'self': &Self
|
||||||
|
65..70 '{ 0 }': u32
|
||||||
|
67..68 '0': u32
|
||||||
|
177..178 'd': &dyn Trait
|
||||||
|
192..208 '{ ...o(); }': ()
|
||||||
|
198..199 'd': &dyn Trait
|
||||||
|
198..205 'd.foo()': u32
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user