aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-08-05 20:13:34 +0100
committerFlorian Diebold <[email protected]>2019-08-12 20:43:00 +0100
commit6cfdfdecbaed38534397f16e1ea1cda38b0b9395 (patch)
tree44366b5104b57969a3e337acbeb30209ad709087 /crates
parent3a9a0bc968d9bb97c80f18b4323b3ad75cc8bbad (diff)
Add representations of associated types
This adds three different representations, copied from the Chalk model: - `Ty::Projection` is an associated type projection written somewhere in the code, like `<Foo as Trait>::Bar`. - `Ty::UnselectedProjection` is similar, but we don't know the trait yet (`Foo::Bar`). - The above representations are normalized to their actual types during type inference. When that isn't possible, for example for `T::Item` inside an `fn foo<T: Iterator>`, the type is normalized to an application type with `TypeCtor::AssociatedType`.
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs4
-rw-r--r--crates/ra_hir/src/ty.rs86
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs23
3 files changed, 113 insertions, 0 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 779764590..89fc1d1a1 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -838,6 +838,10 @@ impl TypeAlias {
838 self.id.module(db) 838 self.id.module(db)
839 } 839 }
840 840
841 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
842 self.module(db).krate(db)
843 }
844
841 /// The containing impl block, if this is a method. 845 /// The containing impl block, if this is a method.
842 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 846 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
843 let module_impls = db.impls_in_module(self.module(db)); 847 let module_impls = db.impls_in_module(self.module(db));
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 82589e504..f9cf3ec72 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -94,6 +94,12 @@ pub enum TypeCtor {
94 94
95 /// A tuple type. For example, `(i32, bool)`. 95 /// A tuple type. For example, `(i32, bool)`.
96 Tuple { cardinality: u16 }, 96 Tuple { cardinality: u16 },
97
98 /// Represents an associated item like `Iterator::Item`. This is used
99 /// when we have tried to normalize a projection like `T::Item` but
100 /// couldn't find a better representation. In that case, we generate
101 /// an **application type** like `(Iterator::Item)<T>`.
102 AssociatedType(TypeAlias),
97} 103}
98 104
99/// A nominal type with (maybe 0) type parameters. This might be a primitive 105/// A nominal type with (maybe 0) type parameters. This might be a primitive
@@ -114,6 +120,12 @@ pub struct ProjectionTy {
114 pub parameters: Substs, 120 pub parameters: Substs,
115} 121}
116 122
123#[derive(Clone, PartialEq, Eq, Debug, Hash)]
124pub struct UnselectedProjectionTy {
125 pub type_name: Name,
126 pub parameters: Substs,
127}
128
117/// A type. 129/// A type.
118/// 130///
119/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents 131/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
@@ -127,6 +139,18 @@ pub enum Ty {
127 /// several other things. 139 /// several other things.
128 Apply(ApplicationTy), 140 Apply(ApplicationTy),
129 141
142 /// A "projection" type corresponds to an (unnormalized)
143 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
144 /// trait and all its parameters are fully known.
145 Projection(ProjectionTy),
146
147 /// This is a variant of a projection in which the trait is
148 /// **not** known. It corresponds to a case where people write
149 /// `T::Item` without specifying the trait. We would then try to
150 /// figure out the trait by looking at all the traits that are in
151 /// scope.
152 UnselectedProjection(UnselectedProjectionTy),
153
130 /// A type parameter; for example, `T` in `fn f<T>(x: T) {} 154 /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
131 Param { 155 Param {
132 /// The index of the parameter (starting with parameters from the 156 /// The index of the parameter (starting with parameters from the
@@ -352,6 +376,16 @@ impl Ty {
352 t.walk(f); 376 t.walk(f);
353 } 377 }
354 } 378 }
379 Ty::Projection(p_ty) => {
380 for t in p_ty.parameters.iter() {
381 t.walk(f);
382 }
383 }
384 Ty::UnselectedProjection(p_ty) => {
385 for t in p_ty.parameters.iter() {
386 t.walk(f);
387 }
388 }
355 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 389 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
356 } 390 }
357 f(self); 391 f(self);
@@ -362,6 +396,12 @@ impl Ty {
362 Ty::Apply(a_ty) => { 396 Ty::Apply(a_ty) => {
363 a_ty.parameters.walk_mut(f); 397 a_ty.parameters.walk_mut(f);
364 } 398 }
399 Ty::Projection(p_ty) => {
400 p_ty.parameters.walk_mut(f);
401 }
402 Ty::UnselectedProjection(p_ty) => {
403 p_ty.parameters.walk_mut(f);
404 }
365 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 405 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
366 } 406 }
367 f(self); 407 f(self);
@@ -572,7 +612,51 @@ impl HirDisplay for ApplicationTy {
572 write!(f, ">")?; 612 write!(f, ">")?;
573 } 613 }
574 } 614 }
615 TypeCtor::AssociatedType(type_alias) => {
616 let trait_name = type_alias
617 .parent_trait(f.db)
618 .and_then(|t| t.name(f.db))
619 .unwrap_or_else(Name::missing);
620 let name = type_alias.name(f.db);
621 write!(f, "{}::{}", trait_name, name)?;
622 if self.parameters.len() > 0 {
623 write!(f, "<")?;
624 f.write_joined(&*self.parameters.0, ", ")?;
625 write!(f, ">")?;
626 }
627 }
628 }
629 Ok(())
630 }
631}
632
633impl HirDisplay for ProjectionTy {
634 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
635 let trait_name = self
636 .associated_ty
637 .parent_trait(f.db)
638 .and_then(|t| t.name(f.db))
639 .unwrap_or_else(Name::missing);
640 write!(f, "<{} as {}", self.parameters[0].display(f.db), trait_name,)?;
641 if self.parameters.len() > 1 {
642 write!(f, "<")?;
643 f.write_joined(&self.parameters[1..], ", ")?;
644 write!(f, ">")?;
645 }
646 write!(f, ">::{}", self.associated_ty.name(f.db))?;
647 Ok(())
648 }
649}
650
651impl HirDisplay for UnselectedProjectionTy {
652 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
653 write!(f, "{}", self.parameters[0].display(f.db))?;
654 if self.parameters.len() > 1 {
655 write!(f, "<")?;
656 f.write_joined(&self.parameters[1..], ", ")?;
657 write!(f, ">")?;
575 } 658 }
659 write!(f, "::{}", self.type_name)?;
576 Ok(()) 660 Ok(())
577 } 661 }
578} 662}
@@ -581,6 +665,8 @@ impl HirDisplay for Ty {
581 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 665 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
582 match self { 666 match self {
583 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, 667 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
668 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
669 Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?,
584 Ty::Param { name, .. } => write!(f, "{}", name)?, 670 Ty::Param { name, .. } => write!(f, "{}", name)?,
585 Ty::Bound(idx) => write!(f, "?{}", idx)?, 671 Ty::Bound(idx) => write!(f, "?{}", idx)?,
586 Ty::Unknown => write!(f, "{{unknown}}")?, 672 Ty::Unknown => write!(f, "{{unknown}}")?,
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 9e7ae0724..21055dcfd 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -50,6 +50,19 @@ impl ToChalk for Ty {
50 let parameters = apply_ty.parameters.to_chalk(db); 50 let parameters = apply_ty.parameters.to_chalk(db);
51 chalk_ir::ApplicationTy { name, parameters }.cast() 51 chalk_ir::ApplicationTy { name, parameters }.cast()
52 } 52 }
53 Ty::Projection(proj_ty) => {
54 let associated_ty_id = proj_ty.associated_ty.to_chalk(db);
55 let parameters = proj_ty.parameters.to_chalk(db);
56 chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast()
57 }
58 Ty::UnselectedProjection(proj_ty) => {
59 let type_name = lalrpop_intern::intern(&proj_ty.type_name.to_string());
60 let parameters = proj_ty.parameters.to_chalk(db);
61 chalk_ir::Ty::UnselectedProjection(chalk_ir::UnselectedProjectionTy {
62 type_name,
63 parameters,
64 })
65 }
53 Ty::Param { idx, .. } => { 66 Ty::Param { idx, .. } => {
54 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty() 67 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty()
55 } 68 }
@@ -529,6 +542,16 @@ pub(crate) fn struct_datum_query(
529 adt.krate(db) != Some(krate), 542 adt.krate(db) != Some(krate),
530 ) 543 )
531 } 544 }
545 TypeCtor::AssociatedType(type_alias) => {
546 let generic_params = type_alias.generic_params(db);
547 let bound_vars = Substs::bound_vars(&generic_params);
548 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
549 (
550 generic_params.count_params_including_parent(),
551 where_clauses,
552 type_alias.krate(db) != Some(krate),
553 )
554 }
532 }; 555 };
533 let flags = chalk_rust_ir::StructFlags { 556 let flags = chalk_rust_ir::StructFlags {
534 upstream, 557 upstream,