aboutsummaryrefslogtreecommitdiff
path: root/crates
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
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')
-rw-r--r--crates/ra_hir/src/generics.rs20
-rw-r--r--crates/ra_hir/src/ty.rs120
-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
-rw-r--r--crates/ra_hir/src/type_ref.rs51
-rw-r--r--crates/ra_syntax/src/ast.rs2
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs26
8 files changed, 366 insertions, 42 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index e75337cdf..d6728cc9f 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -11,7 +11,7 @@ use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 name::SELF_TYPE, 12 name::SELF_TYPE,
13 path::Path, 13 path::Path,
14 type_ref::TypeRef, 14 type_ref::{TypeBound, TypeRef},
15 AdtDef, AsName, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct, 15 AdtDef, AsName, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct,
16 Trait, TypeAlias, Union, 16 Trait, TypeAlias, Union,
17}; 17};
@@ -35,10 +35,12 @@ pub struct GenericParams {
35 35
36/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined 36/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined
37/// where clauses like `where T: Foo + Bar` are turned into multiple of these. 37/// where clauses like `where T: Foo + Bar` are turned into multiple of these.
38/// It might still result in multiple actual predicates though, because of
39/// associated type bindings like `Iterator<Item = u32>`.
38#[derive(Clone, PartialEq, Eq, Debug)] 40#[derive(Clone, PartialEq, Eq, Debug)]
39pub struct WherePredicate { 41pub struct WherePredicate {
40 pub(crate) type_ref: TypeRef, 42 pub(crate) type_ref: TypeRef,
41 pub(crate) trait_ref: Path, 43 pub(crate) bound: TypeBound,
42} 44}
43 45
44// FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) 46// FIXME: consts can have type parameters from their parents (i.e. associated consts of traits)
@@ -143,18 +145,8 @@ impl GenericParams {
143 // FIXME: remove this bound 145 // FIXME: remove this bound
144 return; 146 return;
145 } 147 }
146 let path = bound 148 let bound = TypeBound::from_ast(bound);
147 .type_ref() 149 self.where_predicates.push(WherePredicate { type_ref, bound });
148 .and_then(|tr| match tr {
149 ast::TypeRef::PathType(path) => path.path(),
150 _ => None,
151 })
152 .and_then(Path::from_ast);
153 let path = match path {
154 Some(p) => p,
155 None => return,
156 };
157 self.where_predicates.push(WherePredicate { type_ref, trait_ref: path });
158 } 150 }
159 151
160 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 152 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 642dd02cb..4e5bdbae4 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -161,14 +161,28 @@ pub enum Ty {
161 name: Name, 161 name: Name,
162 }, 162 },
163 163
164 /// A bound type variable. Only used during trait resolution to represent 164 /// A bound type variable. Used during trait resolution to represent Chalk
165 /// Chalk variables. 165 /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
166 Bound(u32), 166 Bound(u32),
167 167
168 /// A type variable used during type checking. Not to be confused with a 168 /// A type variable used during type checking. Not to be confused with a
169 /// type parameter. 169 /// type parameter.
170 Infer(InferTy), 170 Infer(InferTy),
171 171
172 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
173 ///
174 /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
175 /// represents the `Self` type inside the bounds. This is currently
176 /// implicit; Chalk has the `Binders` struct to make it explicit, but it
177 /// didn't seem worth the overhead yet.
178 Dyn(Arc<[GenericPredicate]>),
179
180 /// An opaque type (`impl Trait`).
181 ///
182 /// The predicates are quantified over the `Self` type; see `Ty::Dyn` for
183 /// more.
184 Opaque(Arc<[GenericPredicate]>),
185
172 /// A placeholder for a type which could not be computed; this is propagated 186 /// A placeholder for a type which could not be computed; this is propagated
173 /// to avoid useless error messages. Doubles as a placeholder where type 187 /// to avoid useless error messages. Doubles as a placeholder where type
174 /// variables are inserted before type checking, since we want to try to 188 /// variables are inserted before type checking, since we want to try to
@@ -194,6 +208,12 @@ impl Substs {
194 Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into()) 208 Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into())
195 } 209 }
196 210
211 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
212 for t in self.0.iter() {
213 t.walk(f);
214 }
215 }
216
197 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 217 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
198 // Without an Arc::make_mut_slice, we can't avoid the clone here: 218 // Without an Arc::make_mut_slice, we can't avoid the clone here:
199 let mut v: Vec<_> = self.0.iter().cloned().collect(); 219 let mut v: Vec<_> = self.0.iter().cloned().collect();
@@ -270,6 +290,14 @@ impl TraitRef {
270 }); 290 });
271 self 291 self
272 } 292 }
293
294 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
295 self.substs.walk(f);
296 }
297
298 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
299 self.substs.walk_mut(f);
300 }
273} 301}
274 302
275/// Like `generics::WherePredicate`, but with resolved types: A condition on the 303/// Like `generics::WherePredicate`, but with resolved types: A condition on the
@@ -299,6 +327,20 @@ impl GenericPredicate {
299 GenericPredicate::Error => self, 327 GenericPredicate::Error => self,
300 } 328 }
301 } 329 }
330
331 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
332 match self {
333 GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
334 GenericPredicate::Error => {}
335 }
336 }
337
338 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
339 match self {
340 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f),
341 GenericPredicate::Error => {}
342 }
343 }
302} 344}
303 345
304/// Basically a claim (currently not validated / checked) that the contained 346/// Basically a claim (currently not validated / checked) that the contained
@@ -386,6 +428,11 @@ impl Ty {
386 t.walk(f); 428 t.walk(f);
387 } 429 }
388 } 430 }
431 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
432 for p in predicates.iter() {
433 p.walk(f);
434 }
435 }
389 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 436 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
390 } 437 }
391 f(self); 438 f(self);
@@ -402,6 +449,13 @@ impl Ty {
402 Ty::UnselectedProjection(p_ty) => { 449 Ty::UnselectedProjection(p_ty) => {
403 p_ty.parameters.walk_mut(f); 450 p_ty.parameters.walk_mut(f);
404 } 451 }
452 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
453 let mut v: Vec<_> = predicates.iter().cloned().collect();
454 for p in &mut v {
455 p.walk_mut(f);
456 }
457 *predicates = v.into();
458 }
405 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 459 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
406 } 460 }
407 f(self); 461 f(self);
@@ -669,6 +723,28 @@ impl HirDisplay for Ty {
669 Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?, 723 Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?,
670 Ty::Param { name, .. } => write!(f, "{}", name)?, 724 Ty::Param { name, .. } => write!(f, "{}", name)?,
671 Ty::Bound(idx) => write!(f, "?{}", idx)?, 725 Ty::Bound(idx) => write!(f, "?{}", idx)?,
726 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
727 match self {
728 Ty::Dyn(_) => write!(f, "dyn ")?,
729 Ty::Opaque(_) => write!(f, "impl ")?,
730 _ => unreachable!(),
731 };
732 // looping by hand here just to format the bounds in a slightly nicer way
733 let mut first = true;
734 for p in predicates.iter() {
735 if !first {
736 write!(f, " + ")?;
737 }
738 first = false;
739 match p {
740 // don't show the $0 self type
741 GenericPredicate::Implemented(trait_ref) => {
742 trait_ref.hir_fmt_ext(f, false)?
743 }
744 GenericPredicate::Error => p.hir_fmt(f)?,
745 }
746 }
747 }
672 Ty::Unknown => write!(f, "{{unknown}}")?, 748 Ty::Unknown => write!(f, "{{unknown}}")?,
673 Ty::Infer(..) => write!(f, "_")?, 749 Ty::Infer(..) => write!(f, "_")?,
674 } 750 }
@@ -676,14 +752,16 @@ impl HirDisplay for Ty {
676 } 752 }
677} 753}
678 754
679impl HirDisplay for TraitRef { 755impl TraitRef {
680 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 756 fn hir_fmt_ext(
681 write!( 757 &self,
682 f, 758 f: &mut HirFormatter<impl HirDatabase>,
683 "{}: {}", 759 with_self_ty: bool,
684 self.substs[0].display(f.db), 760 ) -> fmt::Result {
685 self.trait_.name(f.db).unwrap_or_else(Name::missing) 761 if with_self_ty {
686 )?; 762 write!(f, "{}: ", self.substs[0].display(f.db),)?;
763 }
764 write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?;
687 if self.substs.len() > 1 { 765 if self.substs.len() > 1 {
688 write!(f, "<")?; 766 write!(f, "<")?;
689 f.write_joined(&self.substs[1..], ", ")?; 767 f.write_joined(&self.substs[1..], ", ")?;
@@ -693,6 +771,28 @@ impl HirDisplay for TraitRef {
693 } 771 }
694} 772}
695 773
774impl HirDisplay for TraitRef {
775 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
776 self.hir_fmt_ext(f, true)
777 }
778}
779
780impl HirDisplay for &GenericPredicate {
781 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
782 HirDisplay::hir_fmt(*self, f)
783 }
784}
785
786impl HirDisplay for GenericPredicate {
787 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
788 match self {
789 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
790 GenericPredicate::Error => write!(f, "{{error}}")?,
791 }
792 Ok(())
793 }
794}
795
696impl HirDisplay for Obligation { 796impl HirDisplay for Obligation {
697 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 797 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
698 match self { 798 match self {
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 }
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs
index b92a0b55a..949fa7a2c 100644
--- a/crates/ra_hir/src/type_ref.rs
+++ b/crates/ra_hir/src/type_ref.rs
@@ -1,7 +1,7 @@
1//! HIR for references to types. Paths in these are not yet resolved. They can 1//! HIR for references to types. Paths in these are not yet resolved. They can
2//! be directly created from an ast::TypeRef, without further queries. 2//! be directly created from an ast::TypeRef, without further queries.
3 3
4use ra_syntax::ast::{self, TypeAscriptionOwner}; 4use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner};
5 5
6use crate::Path; 6use crate::Path;
7 7
@@ -49,8 +49,16 @@ pub enum TypeRef {
49 /// A fn pointer. Last element of the vector is the return type. 49 /// A fn pointer. Last element of the vector is the return type.
50 Fn(Vec<TypeRef>), 50 Fn(Vec<TypeRef>),
51 // For 51 // For
52 // ImplTrait, 52 ImplTrait(Vec<TypeBound>),
53 // DynTrait, 53 DynTrait(Vec<TypeBound>),
54 Error,
55}
56
57#[derive(Clone, PartialEq, Eq, Hash, Debug)]
58pub enum TypeBound {
59 Path(Path),
60 // also for<> bounds
61 // also Lifetimes
54 Error, 62 Error,
55} 63}
56 64
@@ -95,8 +103,12 @@ impl TypeRef {
95 } 103 }
96 // for types are close enough for our purposes to the inner type for now... 104 // for types are close enough for our purposes to the inner type for now...
97 ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()), 105 ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()),
98 ast::TypeRef::ImplTraitType(_inner) => TypeRef::Error, 106 ast::TypeRef::ImplTraitType(inner) => {
99 ast::TypeRef::DynTraitType(_inner) => TypeRef::Error, 107 TypeRef::ImplTrait(type_bounds_from_ast(inner.type_bound_list()))
108 }
109 ast::TypeRef::DynTraitType(inner) => {
110 TypeRef::DynTrait(type_bounds_from_ast(inner.type_bound_list()))
111 }
100 } 112 }
101 } 113 }
102 114
@@ -112,3 +124,32 @@ impl TypeRef {
112 TypeRef::Tuple(Vec::new()) 124 TypeRef::Tuple(Vec::new())
113 } 125 }
114} 126}
127
128pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> {
129 if let Some(type_bounds) = type_bounds_opt {
130 type_bounds.bounds().map(TypeBound::from_ast).collect()
131 } else {
132 vec![]
133 }
134}
135
136impl TypeBound {
137 pub(crate) fn from_ast(node: ast::TypeBound) -> Self {
138 match node.kind() {
139 Some(ast::TypeBoundKind::PathType(path_type)) => {
140 let path = match path_type.path() {
141 Some(p) => p,
142 None => return TypeBound::Error,
143 };
144 let path = match Path::from_ast(path) {
145 Some(p) => p,
146 None => return TypeBound::Error,
147 };
148 TypeBound::Path(path)
149 }
150 Some(ast::TypeBoundKind::ForType(_)) | Some(ast::TypeBoundKind::Lifetime(_)) | None => {
151 TypeBound::Error
152 }
153 }
154 }
155}
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 6f0489617..afdfca66e 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -15,7 +15,7 @@ use crate::{
15 15
16pub use self::{ 16pub use self::{
17 expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp}, 17 expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp},
18 extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind}, 18 extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind},
19 generated::*, 19 generated::*,
20 tokens::*, 20 tokens::*,
21 traits::*, 21 traits::*,
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index efe261fc2..8de979ca2 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -399,3 +399,29 @@ impl ast::TraitDef {
399 self.syntax().children_with_tokens().any(|t| t.kind() == T![auto]) 399 self.syntax().children_with_tokens().any(|t| t.kind() == T![auto])
400 } 400 }
401} 401}
402
403#[derive(Clone, Debug, PartialEq, Eq, Hash)]
404pub enum TypeBoundKind {
405 /// Trait
406 PathType(ast::PathType),
407 /// for<'a> ...
408 ForType(ast::ForType),
409 /// 'a
410 Lifetime(ast::SyntaxToken),
411}
412
413impl ast::TypeBound {
414 pub fn kind(&self) -> Option<TypeBoundKind> {
415 let child = self.syntax.first_child_or_token()?;
416 match child.kind() {
417 PATH_TYPE => Some(TypeBoundKind::PathType(
418 ast::PathType::cast(child.into_node().unwrap()).unwrap(),
419 )),
420 FOR_TYPE => Some(TypeBoundKind::ForType(
421 ast::ForType::cast(child.into_node().unwrap()).unwrap(),
422 )),
423 LIFETIME => Some(TypeBoundKind::Lifetime(child.into_token().unwrap())),
424 _ => unreachable!(),
425 }
426 }
427}