diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-08-12 20:43:57 +0100 |
---|---|---|
committer | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-08-12 20:43:57 +0100 |
commit | 2c65a059840dd2092a00e90337a8221cd832c456 (patch) | |
tree | fa1f8c46158271eb859928ed9da3eb389f861c09 /crates/ra_hir/src/ty/traits | |
parent | 0cf48e48d75d267bfa38ff1319e7f7c0468fb53f (diff) | |
parent | 5af9691dc9132db61b50c4e90cdeda6fea0c5dd9 (diff) |
Merge #1677
1677: Associated types r=flodiebold a=flodiebold
This implements basic support for (fully qualified) associated type projections:
- handle fully qualified paths like `<T as Trait>::AssocType` (basically desugaring to something like `Trait<Self=T>::AssocType`)
- lower these to a new `Ty::Projection` enum variant
- also introduce `Ty::UnselectedProjection` for cases like `T::AssocType` where the trait from which the type comes isn't specified, but these aren't handled further so far
- in inference, normalize these projections using Chalk: basically, when encountering a type e.g. from a type annotation or signature, we replace these `Ty::Projection`s by type variables and add obligations to normalize the associated type
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/traits')
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 9e7ae0724..6df7094c5 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -45,11 +45,33 @@ impl ToChalk for Ty { | |||
45 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { | 45 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { |
46 | match self { | 46 | match self { |
47 | Ty::Apply(apply_ty) => { | 47 | Ty::Apply(apply_ty) => { |
48 | let struct_id = apply_ty.ctor.to_chalk(db); | 48 | let name = match apply_ty.ctor { |
49 | let name = TypeName::TypeKindId(struct_id.into()); | 49 | TypeCtor::AssociatedType(type_alias) => { |
50 | let type_id = type_alias.to_chalk(db); | ||
51 | TypeName::AssociatedType(type_id) | ||
52 | } | ||
53 | _ => { | ||
54 | // other TypeCtors get interned and turned into a chalk StructId | ||
55 | let struct_id = apply_ty.ctor.to_chalk(db); | ||
56 | TypeName::TypeKindId(struct_id.into()) | ||
57 | } | ||
58 | }; | ||
50 | let parameters = apply_ty.parameters.to_chalk(db); | 59 | let parameters = apply_ty.parameters.to_chalk(db); |
51 | chalk_ir::ApplicationTy { name, parameters }.cast() | 60 | chalk_ir::ApplicationTy { name, parameters }.cast() |
52 | } | 61 | } |
62 | Ty::Projection(proj_ty) => { | ||
63 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | ||
64 | let parameters = proj_ty.parameters.to_chalk(db); | ||
65 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast() | ||
66 | } | ||
67 | Ty::UnselectedProjection(proj_ty) => { | ||
68 | let type_name = lalrpop_intern::intern(&proj_ty.type_name.to_string()); | ||
69 | let parameters = proj_ty.parameters.to_chalk(db); | ||
70 | chalk_ir::Ty::UnselectedProjection(chalk_ir::UnselectedProjectionTy { | ||
71 | type_name, | ||
72 | parameters, | ||
73 | }) | ||
74 | } | ||
53 | Ty::Param { idx, .. } => { | 75 | Ty::Param { idx, .. } => { |
54 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty() | 76 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty() |
55 | } | 77 | } |
@@ -66,15 +88,21 @@ impl ToChalk for Ty { | |||
66 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { | 88 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { |
67 | match chalk { | 89 | match chalk { |
68 | chalk_ir::Ty::Apply(apply_ty) => { | 90 | chalk_ir::Ty::Apply(apply_ty) => { |
91 | // FIXME this is kind of hacky due to the fact that | ||
92 | // TypeName::Placeholder is a Ty::Param on our side | ||
69 | match apply_ty.name { | 93 | match apply_ty.name { |
70 | TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { | 94 | TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { |
71 | let ctor = from_chalk(db, struct_id); | 95 | let ctor = from_chalk(db, struct_id); |
72 | let parameters = from_chalk(db, apply_ty.parameters); | 96 | let parameters = from_chalk(db, apply_ty.parameters); |
73 | Ty::Apply(ApplicationTy { ctor, parameters }) | 97 | Ty::Apply(ApplicationTy { ctor, parameters }) |
74 | } | 98 | } |
99 | TypeName::AssociatedType(type_id) => { | ||
100 | let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id)); | ||
101 | let parameters = from_chalk(db, apply_ty.parameters); | ||
102 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
103 | } | ||
75 | // FIXME handle TypeKindId::Trait/Type here | 104 | // FIXME handle TypeKindId::Trait/Type here |
76 | TypeName::TypeKindId(_) => unimplemented!(), | 105 | TypeName::TypeKindId(_) => unimplemented!(), |
77 | TypeName::AssociatedType(_) => unimplemented!(), | ||
78 | TypeName::Placeholder(idx) => { | 106 | TypeName::Placeholder(idx) => { |
79 | assert_eq!(idx.ui, UniverseIndex::ROOT); | 107 | assert_eq!(idx.ui, UniverseIndex::ROOT); |
80 | Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } | 108 | Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } |
@@ -389,11 +417,12 @@ where | |||
389 | &self, | 417 | &self, |
390 | projection: &'p chalk_ir::ProjectionTy, | 418 | projection: &'p chalk_ir::ProjectionTy, |
391 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) { | 419 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) { |
392 | debug!("split_projection {:?}", projection); | 420 | let proj_ty: ProjectionTy = from_chalk(self.db, projection.clone()); |
393 | unimplemented!() | 421 | debug!("split_projection {:?} = {}", projection, proj_ty.display(self.db)); |
422 | // we don't support GATs, so I think this should always be correct currently | ||
423 | (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) | ||
394 | } | 424 | } |
395 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause> { | 425 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause> { |
396 | debug!("custom_clauses"); | ||
397 | vec![] | 426 | vec![] |
398 | } | 427 | } |
399 | fn all_structs(&self) -> Vec<chalk_ir::StructId> { | 428 | fn all_structs(&self) -> Vec<chalk_ir::StructId> { |
@@ -529,6 +558,16 @@ pub(crate) fn struct_datum_query( | |||
529 | adt.krate(db) != Some(krate), | 558 | adt.krate(db) != Some(krate), |
530 | ) | 559 | ) |
531 | } | 560 | } |
561 | TypeCtor::AssociatedType(type_alias) => { | ||
562 | let generic_params = type_alias.generic_params(db); | ||
563 | let bound_vars = Substs::bound_vars(&generic_params); | ||
564 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); | ||
565 | ( | ||
566 | generic_params.count_params_including_parent(), | ||
567 | where_clauses, | ||
568 | type_alias.krate(db) != Some(krate), | ||
569 | ) | ||
570 | } | ||
532 | }; | 571 | }; |
533 | let flags = chalk_rust_ir::StructFlags { | 572 | let flags = chalk_rust_ir::StructFlags { |
534 | upstream, | 573 | upstream, |