diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 86 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 23 |
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)] | ||
124 | pub 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 | |||
633 | impl 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 | |||
651 | impl 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, |