Skip to content

Commit b1a4004

Browse files
committed
Handle impl/dyn Trait in method resolution
When we have one of these, the `Trait` doesn't need to be in scope to call its methods. So we need to consider this when looking for method candidates. (Actually I think the same is true when we have a bound `T: some::Trait`, but we don't handle that yet). At the same time, since Chalk doesn't handle these types yet, add a small hack to skip Chalk in method resolution and just consider `impl Trait: Trait` always true. This is enough to e.g. get completions for `impl Trait`, but since we don't do any unification we won't infer the return type of e.g. `impl Into<i64>::into()`.
1 parent 16a7d8c commit b1a4004

File tree

3 files changed

+79
-32
lines changed

3 files changed

+79
-32
lines changed

crates/ra_hir/src/ty.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,19 @@ impl Ty {
583583
ty => ty,
584584
})
585585
}
586+
587+
/// If this is an `impl Trait` or `dyn Trait`, returns that trait.
588+
pub fn inherent_trait(&self) -> Option<Trait> {
589+
match self {
590+
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
591+
predicates.iter().find_map(|pred| match pred {
592+
GenericPredicate::Implemented(tr) => Some(tr.trait_),
593+
_ => None,
594+
})
595+
}
596+
_ => None,
597+
}
598+
}
586599
}
587600

588601
impl HirDisplay for &Ty {

crates/ra_hir/src/ty/method_resolution.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,19 @@ fn iterate_trait_method_candidates<T>(
211211
let krate = resolver.krate()?;
212212
// FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
213213
let env = lower::trait_env(db, resolver);
214-
'traits: for t in resolver.traits_in_scope(db) {
214+
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
215+
let traits = ty.value.inherent_trait().into_iter().chain(resolver.traits_in_scope(db));
216+
'traits: for t in traits {
215217
let data = t.trait_data(db);
218+
219+
// FIXME this is a bit of a hack, since Chalk should say the same thing
220+
// anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
221+
let inherently_implemented = ty.value.inherent_trait() == Some(t);
222+
216223
// we'll be lazy about checking whether the type implements the
217224
// trait, but if we find out it doesn't, we'll skip the rest of the
218225
// iteration
219-
let mut known_implemented = false;
226+
let mut known_implemented = inherently_implemented;
220227
for item in data.items() {
221228
if let TraitItem::Function(m) = *item {
222229
let data = m.data(db);
@@ -271,6 +278,11 @@ pub(crate) fn implements_trait(
271278
krate: Crate,
272279
trait_: Trait,
273280
) -> bool {
281+
if ty.value.inherent_trait() == Some(trait_) {
282+
// FIXME this is a bit of a hack, since Chalk should say the same thing
283+
// anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
284+
return true;
285+
}
274286
let env = lower::trait_env(db, resolver);
275287
let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone());
276288
let solution = db.trait_solve(krate, goal);

crates/ra_hir/src/ty/tests.rs

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3279,6 +3279,7 @@ fn impl_trait() {
32793279
infer(r#"
32803280
trait Trait<T> {
32813281
fn foo(&self) -> T;
3282+
fn foo2(&self) -> i64;
32823283
}
32833284
fn bar() -> impl Trait<u64> {}
32843285
@@ -3289,26 +3290,36 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
32893290
x.foo();
32903291
y.foo();
32913292
z.foo();
3293+
x.foo2();
3294+
y.foo2();
3295+
z.foo2();
32923296
}
32933297
"#),
32943298
@r###"
32953299
32963300
⋮[30; 34) 'self': &Self
3297-
⋮[72; 74) '{}': ()
3298-
⋮[84; 85) 'x': impl Trait<u64>
3299-
⋮[104; 105) 'y': &impl Trait<u64>
3300-
⋮[125; 200) '{ ...o(); }': ()
3301-
⋮[131; 132) 'x': impl Trait<u64>
3302-
⋮[138; 139) 'y': &impl Trait<u64>
3303-
⋮[149; 150) 'z': impl Trait<u64>
3304-
⋮[153; 156) 'bar': fn bar() -> impl Trait<u64>
3305-
⋮[153; 158) 'bar()': impl Trait<u64>
3306-
⋮[164; 165) 'x': impl Trait<u64>
3307-
⋮[164; 171) 'x.foo()': {unknown}
3308-
⋮[177; 178) 'y': &impl Trait<u64>
3309-
⋮[177; 184) 'y.foo()': {unknown}
3310-
⋮[190; 191) 'z': impl Trait<u64>
3311-
⋮[190; 197) 'z.foo()': {unknown}
3301+
⋮[55; 59) 'self': &Self
3302+
⋮[99; 101) '{}': ()
3303+
⋮[111; 112) 'x': impl Trait<u64>
3304+
⋮[131; 132) 'y': &impl Trait<u64>
3305+
⋮[152; 269) '{ ...2(); }': ()
3306+
⋮[158; 159) 'x': impl Trait<u64>
3307+
⋮[165; 166) 'y': &impl Trait<u64>
3308+
⋮[176; 177) 'z': impl Trait<u64>
3309+
⋮[180; 183) 'bar': fn bar() -> impl Trait<u64>
3310+
⋮[180; 185) 'bar()': impl Trait<u64>
3311+
⋮[191; 192) 'x': impl Trait<u64>
3312+
⋮[191; 198) 'x.foo()': {unknown}
3313+
⋮[204; 205) 'y': &impl Trait<u64>
3314+
⋮[204; 211) 'y.foo()': {unknown}
3315+
⋮[217; 218) 'z': impl Trait<u64>
3316+
⋮[217; 224) 'z.foo()': {unknown}
3317+
⋮[230; 231) 'x': impl Trait<u64>
3318+
⋮[230; 238) 'x.foo2()': i64
3319+
⋮[244; 245) 'y': &impl Trait<u64>
3320+
⋮[244; 252) 'y.foo2()': i64
3321+
⋮[258; 259) 'z': impl Trait<u64>
3322+
⋮[258; 266) 'z.foo2()': i64
33123323
"###
33133324
);
33143325
}
@@ -3319,6 +3330,7 @@ fn dyn_trait() {
33193330
infer(r#"
33203331
trait Trait<T> {
33213332
fn foo(&self) -> T;
3333+
fn foo2(&self) -> i64;
33223334
}
33233335
fn bar() -> dyn Trait<u64> {}
33243336
@@ -3329,26 +3341,36 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
33293341
x.foo();
33303342
y.foo();
33313343
z.foo();
3344+
x.foo2();
3345+
y.foo2();
3346+
z.foo2();
33323347
}
33333348
"#),
33343349
@r###"
33353350
33363351
⋮[30; 34) 'self': &Self
3337-
⋮[71; 73) '{}': ()
3338-
⋮[83; 84) 'x': dyn Trait<u64>
3339-
⋮[102; 103) 'y': &dyn Trait<u64>
3340-
⋮[122; 197) '{ ...o(); }': ()
3341-
⋮[128; 129) 'x': dyn Trait<u64>
3342-
⋮[135; 136) 'y': &dyn Trait<u64>
3343-
⋮[146; 147) 'z': dyn Trait<u64>
3344-
⋮[150; 153) 'bar': fn bar() -> dyn Trait<u64>
3345-
⋮[150; 155) 'bar()': dyn Trait<u64>
3346-
⋮[161; 162) 'x': dyn Trait<u64>
3347-
⋮[161; 168) 'x.foo()': {unknown}
3348-
⋮[174; 175) 'y': &dyn Trait<u64>
3349-
⋮[174; 181) 'y.foo()': {unknown}
3350-
⋮[187; 188) 'z': dyn Trait<u64>
3351-
⋮[187; 194) 'z.foo()': {unknown}
3352+
⋮[55; 59) 'self': &Self
3353+
⋮[98; 100) '{}': ()
3354+
⋮[110; 111) 'x': dyn Trait<u64>
3355+
⋮[129; 130) 'y': &dyn Trait<u64>
3356+
⋮[149; 266) '{ ...2(); }': ()
3357+
⋮[155; 156) 'x': dyn Trait<u64>
3358+
⋮[162; 163) 'y': &dyn Trait<u64>
3359+
⋮[173; 174) 'z': dyn Trait<u64>
3360+
⋮[177; 180) 'bar': fn bar() -> dyn Trait<u64>
3361+
⋮[177; 182) 'bar()': dyn Trait<u64>
3362+
⋮[188; 189) 'x': dyn Trait<u64>
3363+
⋮[188; 195) 'x.foo()': {unknown}
3364+
⋮[201; 202) 'y': &dyn Trait<u64>
3365+
⋮[201; 208) 'y.foo()': {unknown}
3366+
⋮[214; 215) 'z': dyn Trait<u64>
3367+
⋮[214; 221) 'z.foo()': {unknown}
3368+
⋮[227; 228) 'x': dyn Trait<u64>
3369+
⋮[227; 235) 'x.foo2()': i64
3370+
⋮[241; 242) 'y': &dyn Trait<u64>
3371+
⋮[241; 249) 'y.foo2()': i64
3372+
⋮[255; 256) 'z': dyn Trait<u64>
3373+
⋮[255; 263) 'z.foo2()': i64
33523374
"###
33533375
);
33543376
}

0 commit comments

Comments
 (0)