aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-08-13 22:09:08 +0100
committerFlorian Diebold <[email protected]>2019-08-22 18:33:00 +0100
commit16a7d8cc850002b427fdc8d21ccde81caaed7902 (patch)
tree7f3c43cf9e83d479edc7f9b4849dae5fbd0f356d /crates/ra_hir/src/ty
parent08e5d394dfbca28b15ed5dc772d55d48f87c3f54 (diff)
Add `impl Trait` and `dyn Trait` types
- refactor bounds handling in the AST a bit - add HIR for bounds - add `Ty::Dyn` and `Ty::Opaque` variants and lower `dyn Trait` / `impl Trait` syntax to them
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/tests.rs120
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs4
3 files changed, 177 insertions, 12 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/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 57fd5492d..93c62b0d4 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3273,6 +3273,126 @@ 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}
3283fn bar() -> impl Trait<u64> {}
3284
3285fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
3286 x;
3287 y;
3288 let z = bar();
3289 x.foo();
3290 y.foo();
3291 z.foo();
3292}
3293"#),
3294 @r###"
3295
3296 ⋮[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}
3312 "###
3313 );
3314}
3315
3316#[test]
3317fn dyn_trait() {
3318 assert_snapshot_matches!(
3319 infer(r#"
3320trait Trait<T> {
3321 fn foo(&self) -> T;
3322}
3323fn bar() -> dyn Trait<u64> {}
3324
3325fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
3326 x;
3327 y;
3328 let z = bar();
3329 x.foo();
3330 y.foo();
3331 z.foo();
3332}
3333"#),
3334 @r###"
3335
3336 ⋮[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 "###
3353 );
3354}
3355
3356#[test]
3357fn dyn_trait_bare() {
3358 assert_snapshot_matches!(
3359 infer(r#"
3360trait Trait {
3361 fn foo(&self) -> u64;
3362}
3363fn bar() -> Trait {}
3364
3365fn test(x: Trait, y: &Trait) -> u64 {
3366 x;
3367 y;
3368 let z = bar();
3369 x.foo();
3370 y.foo();
3371 z.foo();
3372}
3373"#),
3374 @r###"
3375
3376 ⋮[27; 31) 'self': &Self
3377 ⋮[61; 63) '{}': ()
3378 ⋮[73; 74) 'x': {unknown}
3379 ⋮[83; 84) 'y': &{unknown}
3380 ⋮[101; 176) '{ ...o(); }': ()
3381 ⋮[107; 108) 'x': {unknown}
3382 ⋮[114; 115) 'y': &{unknown}
3383 ⋮[125; 126) 'z': {unknown}
3384 ⋮[129; 132) 'bar': fn bar() -> {unknown}
3385 ⋮[129; 134) 'bar()': {unknown}
3386 ⋮[140; 141) 'x': {unknown}
3387 ⋮[140; 147) 'x.foo()': {unknown}
3388 ⋮[153; 154) 'y': &{unknown}
3389 ⋮[153; 160) 'y.foo()': {unknown}
3390 ⋮[166; 167) 'z': {unknown}
3391 ⋮[166; 173) 'z.foo()': {unknown}
3392 "###
3393 );
3394}
3395
3276fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 3396fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
3277 let file = db.parse(pos.file_id).ok().unwrap(); 3397 let file = db.parse(pos.file_id).ok().unwrap();
3278 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 3398 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 }