From 02962b374ecefd6f2a75956f4fb18806531d1d51 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 4 Mar 2020 23:00:44 +0100 Subject: Implement return position impl trait / opaque type support This is working, but I'm not that happy with how the lowering works. We might need an additional representation between `TypeRef` and `Ty` where names are resolved and `impl Trait` bounds are separated out, but things like inference variables don't exist and `impl Trait` is always represented the same way. Also note that this doesn't implement correct handling of RPIT *inside* the function (which involves turning the `impl Trait`s into variables and creating obligations for them). That intermediate representation might help there as well. --- crates/ra_hir_ty/src/traits/chalk/mapping.rs | 45 ++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir_ty/src/traits/chalk/mapping.rs') diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs index 5f6daf842..834360430 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs @@ -16,8 +16,8 @@ use crate::{ db::HirDatabase, primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, - ApplicationTy, CallableDef, GenericPredicate, InEnvironment, ProjectionPredicate, ProjectionTy, - Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, + ApplicationTy, CallableDef, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, + ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, }; use super::interner::*; @@ -68,7 +68,16 @@ impl ToChalk for Ty { let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) } - Ty::Opaque(_) | Ty::Unknown => { + Ty::Opaque(opaque_ty) => { + let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db); + let substitution = opaque_ty.parameters.to_chalk(db); + chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { + opaque_ty_id, + substitution, + })) + .intern(&Interner) + } + Ty::Unknown => { let substitution = chalk_ir::Substitution::empty(&Interner); let name = TypeName::Error; chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) @@ -98,7 +107,11 @@ impl ToChalk for Ty { let parameters = from_chalk(db, proj.substitution); Ty::Projection(ProjectionTy { associated_ty, parameters }) } - chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), + chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { + let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id); + let parameters = from_chalk(db, opaque_ty.substitution); + Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) + } chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => { let parameters: Substs = from_chalk(db, substitution); Ty::Apply(ApplicationTy { @@ -204,6 +217,21 @@ impl ToChalk for hir_def::TraitId { } } +impl ToChalk for OpaqueTyId { + type Chalk = chalk_ir::OpaqueTyId; + + fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::OpaqueTyId { + db.intern_impl_trait_id(self).into() + } + + fn from_chalk( + db: &dyn HirDatabase, + opaque_ty_id: chalk_ir::OpaqueTyId, + ) -> OpaqueTyId { + db.lookup_intern_impl_trait_id(opaque_ty_id.into()) + } +} + impl ToChalk for TypeCtor { type Chalk = TypeName; @@ -214,6 +242,11 @@ impl ToChalk for TypeCtor { TypeName::AssociatedType(type_id) } + TypeCtor::OpaqueType(impl_trait_id) => { + let id = impl_trait_id.to_chalk(db); + TypeName::OpaqueType(id) + } + TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), TypeCtor::Char => TypeName::Scalar(Scalar::Char), TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), @@ -252,7 +285,9 @@ impl ToChalk for TypeCtor { match type_name { TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), - TypeName::OpaqueType(_) => unreachable!(), + TypeName::OpaqueType(opaque_type_id) => { + TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)) + } TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, TypeName::Scalar(Scalar::Char) => TypeCtor::Char, -- cgit v1.2.3