From 6cfdfdecbaed38534397f16e1ea1cda38b0b9395 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Mon, 5 Aug 2019 21:13:34 +0200 Subject: 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 `::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`, the type is normalized to an application type with `TypeCtor::AssociatedType`. --- crates/ra_hir/src/ty/traits/chalk.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'crates/ra_hir/src/ty/traits/chalk.rs') 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 { let parameters = apply_ty.parameters.to_chalk(db); chalk_ir::ApplicationTy { name, parameters }.cast() } + Ty::Projection(proj_ty) => { + let associated_ty_id = proj_ty.associated_ty.to_chalk(db); + let parameters = proj_ty.parameters.to_chalk(db); + chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast() + } + Ty::UnselectedProjection(proj_ty) => { + let type_name = lalrpop_intern::intern(&proj_ty.type_name.to_string()); + let parameters = proj_ty.parameters.to_chalk(db); + chalk_ir::Ty::UnselectedProjection(chalk_ir::UnselectedProjectionTy { + type_name, + parameters, + }) + } Ty::Param { idx, .. } => { PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty() } @@ -529,6 +542,16 @@ pub(crate) fn struct_datum_query( adt.krate(db) != Some(krate), ) } + TypeCtor::AssociatedType(type_alias) => { + let generic_params = type_alias.generic_params(db); + let bound_vars = Substs::bound_vars(&generic_params); + let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); + ( + generic_params.count_params_including_parent(), + where_clauses, + type_alias.krate(db) != Some(krate), + ) + } }; let flags = chalk_rust_ir::StructFlags { upstream, -- cgit v1.2.3 From 6265497523469990ce39e6817423c35a17055a54 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 7 Aug 2019 22:06:09 +0200 Subject: Normalize associated types during inference --- crates/ra_hir/src/ty/traits/chalk.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir/src/ty/traits/chalk.rs') diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 21055dcfd..e669f835b 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -402,11 +402,12 @@ where &self, projection: &'p chalk_ir::ProjectionTy, ) -> (Arc, &'p [Parameter], &'p [Parameter]) { - debug!("split_projection {:?}", projection); - unimplemented!() + let proj_ty: ProjectionTy = from_chalk(self.db, projection.clone()); + debug!("split_projection {:?} = {}", projection, proj_ty.display(self.db)); + // we don't support GATs, so I think this should always be correct currently + (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) } fn custom_clauses(&self) -> Vec { - debug!("custom_clauses"); vec![] } fn all_structs(&self) -> Vec { -- cgit v1.2.3 From 5af9691dc9132db61b50c4e90cdeda6fea0c5dd9 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 11 Aug 2019 15:54:31 +0200 Subject: Handle placeholder assoc types when Chalk produces them --- crates/ra_hir/src/ty/traits/chalk.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir/src/ty/traits/chalk.rs') diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index e669f835b..6df7094c5 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -45,8 +45,17 @@ impl ToChalk for Ty { fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { match self { Ty::Apply(apply_ty) => { - let struct_id = apply_ty.ctor.to_chalk(db); - let name = TypeName::TypeKindId(struct_id.into()); + let name = match apply_ty.ctor { + TypeCtor::AssociatedType(type_alias) => { + let type_id = type_alias.to_chalk(db); + TypeName::AssociatedType(type_id) + } + _ => { + // other TypeCtors get interned and turned into a chalk StructId + let struct_id = apply_ty.ctor.to_chalk(db); + TypeName::TypeKindId(struct_id.into()) + } + }; let parameters = apply_ty.parameters.to_chalk(db); chalk_ir::ApplicationTy { name, parameters }.cast() } @@ -79,15 +88,21 @@ impl ToChalk for Ty { fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { match chalk { chalk_ir::Ty::Apply(apply_ty) => { + // FIXME this is kind of hacky due to the fact that + // TypeName::Placeholder is a Ty::Param on our side match apply_ty.name { TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { let ctor = from_chalk(db, struct_id); let parameters = from_chalk(db, apply_ty.parameters); Ty::Apply(ApplicationTy { ctor, parameters }) } + TypeName::AssociatedType(type_id) => { + let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id)); + let parameters = from_chalk(db, apply_ty.parameters); + Ty::Apply(ApplicationTy { ctor, parameters }) + } // FIXME handle TypeKindId::Trait/Type here TypeName::TypeKindId(_) => unimplemented!(), - TypeName::AssociatedType(_) => unimplemented!(), TypeName::Placeholder(idx) => { assert_eq!(idx.ui, UniverseIndex::ROOT); Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } -- cgit v1.2.3