aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/lower.rs65
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs16
-rw-r--r--crates/ra_hir/src/ty/tests.rs175
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs4
4 files changed, 246 insertions, 14 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index debedcbb8..47d161277 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -17,7 +17,7 @@ use crate::{
17 path::{GenericArg, PathSegment}, 17 path::{GenericArg, PathSegment},
18 resolve::{Resolution, Resolver}, 18 resolve::{Resolution, Resolver},
19 ty::AdtDef, 19 ty::AdtDef,
20 type_ref::TypeRef, 20 type_ref::{TypeBound, TypeRef},
21 BuiltinType, Const, Enum, EnumVariant, Function, HirDatabase, ModuleDef, Path, Static, Struct, 21 BuiltinType, Const, Enum, EnumVariant, Function, HirDatabase, ModuleDef, Path, Static, Struct,
22 StructField, Trait, TypeAlias, Union, 22 StructField, Trait, TypeAlias, Union,
23}; 23};
@@ -58,6 +58,22 @@ impl Ty {
58 let sig = Substs(inner_tys.into()); 58 let sig = Substs(inner_tys.into());
59 Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) 59 Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig)
60 } 60 }
61 TypeRef::DynTrait(bounds) => {
62 let self_ty = Ty::Bound(0);
63 let predicates = bounds
64 .iter()
65 .map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()))
66 .collect::<Vec<_>>();
67 Ty::Dyn(predicates.into())
68 }
69 TypeRef::ImplTrait(bounds) => {
70 let self_ty = Ty::Bound(0);
71 let predicates = bounds
72 .iter()
73 .map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()))
74 .collect::<Vec<_>>();
75 Ty::Opaque(predicates.into())
76 }
61 TypeRef::Error => Ty::Unknown, 77 TypeRef::Error => Ty::Unknown,
62 } 78 }
63 } 79 }
@@ -310,13 +326,46 @@ impl TraitRef {
310 TraitRef { trait_, substs } 326 TraitRef { trait_, substs }
311 } 327 }
312 328
313 pub(crate) fn for_where_predicate( 329 pub(crate) fn from_where_predicate(
314 db: &impl HirDatabase, 330 db: &impl HirDatabase,
315 resolver: &Resolver, 331 resolver: &Resolver,
316 pred: &WherePredicate, 332 pred: &WherePredicate,
317 ) -> Option<TraitRef> { 333 ) -> Option<TraitRef> {
318 let self_ty = Ty::from_hir(db, resolver, &pred.type_ref); 334 let self_ty = Ty::from_hir(db, resolver, &pred.type_ref);
319 TraitRef::from_path(db, resolver, &pred.trait_ref, Some(self_ty)) 335 TraitRef::from_type_bound(db, resolver, &pred.bound, self_ty)
336 }
337
338 pub(crate) fn from_type_bound(
339 db: &impl HirDatabase,
340 resolver: &Resolver,
341 bound: &TypeBound,
342 self_ty: Ty,
343 ) -> Option<TraitRef> {
344 match bound {
345 TypeBound::Path(path) => TraitRef::from_path(db, resolver, path, Some(self_ty)),
346 TypeBound::Error => None,
347 }
348 }
349}
350
351impl GenericPredicate {
352 pub(crate) fn from_where_predicate(
353 db: &impl HirDatabase,
354 resolver: &Resolver,
355 where_predicate: &WherePredicate,
356 ) -> GenericPredicate {
357 TraitRef::from_where_predicate(db, &resolver, where_predicate)
358 .map_or(GenericPredicate::Error, GenericPredicate::Implemented)
359 }
360
361 pub(crate) fn from_type_bound(
362 db: &impl HirDatabase,
363 resolver: &Resolver,
364 bound: &TypeBound,
365 self_ty: Ty,
366 ) -> GenericPredicate {
367 TraitRef::from_type_bound(db, &resolver, bound, self_ty)
368 .map_or(GenericPredicate::Error, GenericPredicate::Implemented)
320 } 369 }
321} 370}
322 371
@@ -376,10 +425,7 @@ pub(crate) fn trait_env(
376) -> Arc<super::TraitEnvironment> { 425) -> Arc<super::TraitEnvironment> {
377 let predicates = resolver 426 let predicates = resolver
378 .where_predicates_in_scope() 427 .where_predicates_in_scope()
379 .map(|pred| { 428 .map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
380 TraitRef::for_where_predicate(db, &resolver, pred)
381 .map_or(GenericPredicate::Error, GenericPredicate::Implemented)
382 })
383 .collect::<Vec<_>>(); 429 .collect::<Vec<_>>();
384 430
385 Arc::new(super::TraitEnvironment { predicates }) 431 Arc::new(super::TraitEnvironment { predicates })
@@ -393,10 +439,7 @@ pub(crate) fn generic_predicates_query(
393 let resolver = def.resolver(db); 439 let resolver = def.resolver(db);
394 let predicates = resolver 440 let predicates = resolver
395 .where_predicates_in_scope() 441 .where_predicates_in_scope()
396 .map(|pred| { 442 .map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
397 TraitRef::for_where_predicate(db, &resolver, pred)
398 .map_or(GenericPredicate::Error, GenericPredicate::Implemented)
399 })
400 .collect::<Vec<_>>(); 443 .collect::<Vec<_>>();
401 predicates.into() 444 predicates.into()
402} 445}
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 57fd5492d..c5818b738 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3273,6 +3273,181 @@ fn test<T: ApplyL>(t: T) {
3273 assert_eq!(t, "{unknown}"); 3273 assert_eq!(t, "{unknown}");
3274} 3274}
3275 3275
3276#[test]
3277fn impl_trait() {
3278 assert_snapshot_matches!(
3279 infer(r#"
3280trait Trait<T> {
3281 fn foo(&self) -> T;
3282 fn foo2(&self) -> i64;
3283}
3284fn bar() -> impl Trait<u64> {}
3285
3286fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
3287 x;
3288 y;
3289 let z = bar();
3290 x.foo();
3291 y.foo();
3292 z.foo();
3293 x.foo2();
3294 y.foo2();
3295 z.foo2();
3296}
3297"#),
3298 @r###"
3299
3300 ⋮[30; 34) 'self': &Self
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
3323 "###
3324 );
3325}
3326
3327#[test]
3328fn dyn_trait() {
3329 assert_snapshot_matches!(
3330 infer(r#"
3331trait Trait<T> {
3332 fn foo(&self) -> T;
3333 fn foo2(&self) -> i64;
3334}
3335fn bar() -> dyn Trait<u64> {}
3336
3337fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
3338 x;
3339 y;
3340 let z = bar();
3341 x.foo();
3342 y.foo();
3343 z.foo();
3344 x.foo2();
3345 y.foo2();
3346 z.foo2();
3347}
3348"#),
3349 @r###"
3350
3351 ⋮[30; 34) 'self': &Self
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
3374 "###
3375 );
3376}
3377
3378#[test]
3379fn dyn_trait_bare() {
3380 assert_snapshot_matches!(
3381 infer(r#"
3382trait Trait {
3383 fn foo(&self) -> u64;
3384}
3385fn bar() -> Trait {}
3386
3387fn test(x: Trait, y: &Trait) -> u64 {
3388 x;
3389 y;
3390 let z = bar();
3391 x.foo();
3392 y.foo();
3393 z.foo();
3394}
3395"#),
3396 @r###"
3397
3398 ⋮[27; 31) 'self': &Self
3399 ⋮[61; 63) '{}': ()
3400 ⋮[73; 74) 'x': {unknown}
3401 ⋮[83; 84) 'y': &{unknown}
3402 ⋮[101; 176) '{ ...o(); }': ()
3403 ⋮[107; 108) 'x': {unknown}
3404 ⋮[114; 115) 'y': &{unknown}
3405 ⋮[125; 126) 'z': {unknown}
3406 ⋮[129; 132) 'bar': fn bar() -> {unknown}
3407 ⋮[129; 134) 'bar()': {unknown}
3408 ⋮[140; 141) 'x': {unknown}
3409 ⋮[140; 147) 'x.foo()': {unknown}
3410 ⋮[153; 154) 'y': &{unknown}
3411 ⋮[153; 160) 'y.foo()': {unknown}
3412 ⋮[166; 167) 'z': {unknown}
3413 ⋮[166; 173) 'z.foo()': {unknown}
3414 "###
3415 );
3416}
3417
3418#[test]
3419fn weird_bounds() {
3420 assert_snapshot_matches!(
3421 infer(r#"
3422trait Trait {}
3423fn test() {
3424 let a: impl Trait + 'lifetime = foo;
3425 let b: impl 'lifetime = foo;
3426 let b: impl (Trait) = foo;
3427 let b: impl ('lifetime) = foo;
3428 let d: impl ?Sized = foo;
3429 let e: impl Trait + ?Sized = foo;
3430}
3431"#),
3432 @r###"
3433
3434 ⋮[26; 237) '{ ...foo; }': ()
3435 ⋮[36; 37) 'a': impl Trait + {error}
3436 ⋮[64; 67) 'foo': impl Trait + {error}
3437 ⋮[77; 78) 'b': impl {error}
3438 ⋮[97; 100) 'foo': impl {error}
3439 ⋮[110; 111) 'b': impl Trait
3440 ⋮[128; 131) 'foo': impl Trait
3441 ⋮[141; 142) 'b': impl {error}
3442 ⋮[163; 166) 'foo': impl {error}
3443 ⋮[176; 177) 'd': impl {error}
3444 ⋮[193; 196) 'foo': impl {error}
3445 ⋮[206; 207) 'e': impl Trait + {error}
3446 ⋮[231; 234) 'foo': impl Trait + {error}
3447 "###
3448 );
3449}
3450
3276fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 3451fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
3277 let file = db.parse(pos.file_id).ok().unwrap(); 3452 let file = db.parse(pos.file_id).ok().unwrap();
3278 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 3453 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 6df7094c5..2ebc06135 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -80,7 +80,9 @@ impl ToChalk for Ty {
80 // FIXME this is clearly incorrect, but probably not too incorrect 80 // FIXME this is clearly incorrect, but probably not too incorrect
81 // and I'm not sure what to actually do with Ty::Unknown 81 // and I'm not sure what to actually do with Ty::Unknown
82 // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty) 82 // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty)
83 Ty::Unknown => { 83 //
84 // FIXME also dyn and impl Trait are currently handled like Unknown because Chalk doesn't have them yet
85 Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => {
84 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty() 86 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty()
85 } 87 }
86 } 88 }