aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-08-22 12:23:50 +0100
committerFlorian Diebold <[email protected]>2019-08-22 20:55:11 +0100
commitb1a40042e8f595af0486cf1cc70b63be1ff302b3 (patch)
treec3f58127c4a330275d2dd635bb5fb11ca7957ddc /crates
parent16a7d8cc850002b427fdc8d21ccde81caaed7902 (diff)
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()`.
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/ty.rs13
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs16
-rw-r--r--crates/ra_hir/src/ty/tests.rs82
3 files changed, 79 insertions, 32 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 4e5bdbae4..b54c80318 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -583,6 +583,19 @@ impl Ty {
583 ty => ty, 583 ty => ty,
584 }) 584 })
585 } 585 }
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 }
586} 599}
587 600
588impl HirDisplay for &Ty { 601impl HirDisplay for &Ty {
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 3f4c43aee..9873a0440 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -211,12 +211,19 @@ fn iterate_trait_method_candidates<T>(
211 let krate = resolver.krate()?; 211 let krate = resolver.krate()?;
212 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) 212 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
213 let env = lower::trait_env(db, resolver); 213 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 {
215 let data = t.trait_data(db); 217 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
216 // we'll be lazy about checking whether the type implements the 223 // we'll be lazy about checking whether the type implements the
217 // trait, but if we find out it doesn't, we'll skip the rest of the 224 // trait, but if we find out it doesn't, we'll skip the rest of the
218 // iteration 225 // iteration
219 let mut known_implemented = false; 226 let mut known_implemented = inherently_implemented;
220 for item in data.items() { 227 for item in data.items() {
221 if let TraitItem::Function(m) = *item { 228 if let TraitItem::Function(m) = *item {
222 let data = m.data(db); 229 let data = m.data(db);
@@ -271,6 +278,11 @@ pub(crate) fn implements_trait(
271 krate: Crate, 278 krate: Crate,
272 trait_: Trait, 279 trait_: Trait,
273) -> bool { 280) -> 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 }
274 let env = lower::trait_env(db, resolver); 286 let env = lower::trait_env(db, resolver);
275 let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); 287 let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone());
276 let solution = db.trait_solve(krate, goal); 288 let solution = db.trait_solve(krate, goal);
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 93c62b0d4..41cea9564 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3279,6 +3279,7 @@ fn impl_trait() {
3279 infer(r#" 3279 infer(r#"
3280trait Trait<T> { 3280trait Trait<T> {
3281 fn foo(&self) -> T; 3281 fn foo(&self) -> T;
3282 fn foo2(&self) -> i64;
3282} 3283}
3283fn bar() -> impl Trait<u64> {} 3284fn bar() -> impl Trait<u64> {}
3284 3285
@@ -3289,26 +3290,36 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
3289 x.foo(); 3290 x.foo();
3290 y.foo(); 3291 y.foo();
3291 z.foo(); 3292 z.foo();
3293 x.foo2();
3294 y.foo2();
3295 z.foo2();
3292} 3296}
3293"#), 3297"#),
3294 @r###" 3298 @r###"
3295 3299
3296 ⋮[30; 34) 'self': &Self 3300 ⋮[30; 34) 'self': &Self
3297 ⋮[72; 74) '{}': () 3301 ⋮[55; 59) 'self': &Self
3298 ⋮[84; 85) 'x': impl Trait<u64> 3302 ⋮[99; 101) '{}': ()
3299 ⋮[104; 105) 'y': &impl Trait<u64> 3303 ⋮[111; 112) 'x': impl Trait<u64>
3300 ⋮[125; 200) '{ ...o(); }': () 3304 ⋮[131; 132) 'y': &impl Trait<u64>
3301 ⋮[131; 132) 'x': impl Trait<u64> 3305 ⋮[152; 269) '{ ...2(); }': ()
3302 ⋮[138; 139) 'y': &impl Trait<u64> 3306 ⋮[158; 159) 'x': impl Trait<u64>
3303 ⋮[149; 150) 'z': impl Trait<u64> 3307 ⋮[165; 166) 'y': &impl Trait<u64>
3304 ⋮[153; 156) 'bar': fn bar() -> impl Trait<u64> 3308 ⋮[176; 177) 'z': impl Trait<u64>
3305 ⋮[153; 158) 'bar()': impl Trait<u64> 3309 ⋮[180; 183) 'bar': fn bar() -> impl Trait<u64>
3306 ⋮[164; 165) 'x': impl Trait<u64> 3310 ⋮[180; 185) 'bar()': impl Trait<u64>
3307 ⋮[164; 171) 'x.foo()': {unknown} 3311 ⋮[191; 192) 'x': impl Trait<u64>
3308 ⋮[177; 178) 'y': &impl Trait<u64> 3312 ⋮[191; 198) 'x.foo()': {unknown}
3309 ⋮[177; 184) 'y.foo()': {unknown} 3313 ⋮[204; 205) 'y': &impl Trait<u64>
3310 ⋮[190; 191) 'z': impl Trait<u64> 3314 ⋮[204; 211) 'y.foo()': {unknown}
3311 ⋮[190; 197) 'z.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
3312 "### 3323 "###
3313 ); 3324 );
3314} 3325}
@@ -3319,6 +3330,7 @@ fn dyn_trait() {
3319 infer(r#" 3330 infer(r#"
3320trait Trait<T> { 3331trait Trait<T> {
3321 fn foo(&self) -> T; 3332 fn foo(&self) -> T;
3333 fn foo2(&self) -> i64;
3322} 3334}
3323fn bar() -> dyn Trait<u64> {} 3335fn bar() -> dyn Trait<u64> {}
3324 3336
@@ -3329,26 +3341,36 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
3329 x.foo(); 3341 x.foo();
3330 y.foo(); 3342 y.foo();
3331 z.foo(); 3343 z.foo();
3344 x.foo2();
3345 y.foo2();
3346 z.foo2();
3332} 3347}
3333"#), 3348"#),
3334 @r###" 3349 @r###"
3335 3350
3336 ⋮[30; 34) 'self': &Self 3351 ⋮[30; 34) 'self': &Self
3337 ⋮[71; 73) '{}': () 3352 ⋮[55; 59) 'self': &Self
3338 ⋮[83; 84) 'x': dyn Trait<u64> 3353 ⋮[98; 100) '{}': ()
3339 ⋮[102; 103) 'y': &dyn Trait<u64> 3354 ⋮[110; 111) 'x': dyn Trait<u64>
3340 ⋮[122; 197) '{ ...o(); }': () 3355 ⋮[129; 130) 'y': &dyn Trait<u64>
3341 ⋮[128; 129) 'x': dyn Trait<u64> 3356 ⋮[149; 266) '{ ...2(); }': ()
3342 ⋮[135; 136) 'y': &dyn Trait<u64> 3357 ⋮[155; 156) 'x': dyn Trait<u64>
3343 ⋮[146; 147) 'z': dyn Trait<u64> 3358 ⋮[162; 163) 'y': &dyn Trait<u64>
3344 ⋮[150; 153) 'bar': fn bar() -> dyn Trait<u64> 3359 ⋮[173; 174) 'z': dyn Trait<u64>
3345 ⋮[150; 155) 'bar()': dyn Trait<u64> 3360 ⋮[177; 180) 'bar': fn bar() -> dyn Trait<u64>
3346 ⋮[161; 162) 'x': dyn Trait<u64> 3361 ⋮[177; 182) 'bar()': dyn Trait<u64>
3347 ⋮[161; 168) 'x.foo()': {unknown} 3362 ⋮[188; 189) 'x': dyn Trait<u64>
3348 ⋮[174; 175) 'y': &dyn Trait<u64> 3363 ⋮[188; 195) 'x.foo()': {unknown}
3349 ⋮[174; 181) 'y.foo()': {unknown} 3364 ⋮[201; 202) 'y': &dyn Trait<u64>
3350 ⋮[187; 188) 'z': dyn Trait<u64> 3365 ⋮[201; 208) 'y.foo()': {unknown}
3351 ⋮[187; 194) 'z.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
3352 "### 3374 "###
3353 ); 3375 );
3354} 3376}