diff options
author | Florian Diebold <[email protected]> | 2020-03-04 22:00:44 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-06-05 16:08:27 +0100 |
commit | 02962b374ecefd6f2a75956f4fb18806531d1d51 (patch) | |
tree | 7c807d6a09db7e485ea39c3e67331b99829a364c /crates/ra_hir_ty/src/traits/chalk | |
parent | 9c52f527a1cef7d39c2b1c55b49dc5459d392a4d (diff) |
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.
Diffstat (limited to 'crates/ra_hir_ty/src/traits/chalk')
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/interner.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/mapping.rs | 45 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/tls.rs | 5 |
3 files changed, 47 insertions, 5 deletions
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs index e27074ba6..56aab640c 100644 --- a/crates/ra_hir_ty/src/traits/chalk/interner.rs +++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs | |||
@@ -22,6 +22,8 @@ pub type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interne | |||
22 | pub type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; | 22 | pub type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; |
23 | pub type FnDefId = chalk_ir::FnDefId<Interner>; | 23 | pub type FnDefId = chalk_ir::FnDefId<Interner>; |
24 | pub type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; | 24 | pub type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; |
25 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | ||
26 | pub type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; | ||
25 | 27 | ||
26 | impl chalk_ir::interner::Interner for Interner { | 28 | impl chalk_ir::interner::Interner for Interner { |
27 | type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? | 29 | type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? |
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::{ | |||
16 | db::HirDatabase, | 16 | db::HirDatabase, |
17 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, | 17 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, |
18 | traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, | 18 | traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, |
19 | ApplicationTy, CallableDef, GenericPredicate, InEnvironment, ProjectionPredicate, ProjectionTy, | 19 | ApplicationTy, CallableDef, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, |
20 | Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, | 20 | ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | use super::interner::*; | 23 | use super::interner::*; |
@@ -68,7 +68,16 @@ impl ToChalk for Ty { | |||
68 | let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; | 68 | let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; |
69 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) | 69 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) |
70 | } | 70 | } |
71 | Ty::Opaque(_) | Ty::Unknown => { | 71 | Ty::Opaque(opaque_ty) => { |
72 | let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db); | ||
73 | let substitution = opaque_ty.parameters.to_chalk(db); | ||
74 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { | ||
75 | opaque_ty_id, | ||
76 | substitution, | ||
77 | })) | ||
78 | .intern(&Interner) | ||
79 | } | ||
80 | Ty::Unknown => { | ||
72 | let substitution = chalk_ir::Substitution::empty(&Interner); | 81 | let substitution = chalk_ir::Substitution::empty(&Interner); |
73 | let name = TypeName::Error; | 82 | let name = TypeName::Error; |
74 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | 83 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) |
@@ -98,7 +107,11 @@ impl ToChalk for Ty { | |||
98 | let parameters = from_chalk(db, proj.substitution); | 107 | let parameters = from_chalk(db, proj.substitution); |
99 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | 108 | Ty::Projection(ProjectionTy { associated_ty, parameters }) |
100 | } | 109 | } |
101 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), | 110 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { |
111 | let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id); | ||
112 | let parameters = from_chalk(db, opaque_ty.substitution); | ||
113 | Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) | ||
114 | } | ||
102 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => { | 115 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => { |
103 | let parameters: Substs = from_chalk(db, substitution); | 116 | let parameters: Substs = from_chalk(db, substitution); |
104 | Ty::Apply(ApplicationTy { | 117 | Ty::Apply(ApplicationTy { |
@@ -204,6 +217,21 @@ impl ToChalk for hir_def::TraitId { | |||
204 | } | 217 | } |
205 | } | 218 | } |
206 | 219 | ||
220 | impl ToChalk for OpaqueTyId { | ||
221 | type Chalk = chalk_ir::OpaqueTyId<Interner>; | ||
222 | |||
223 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::OpaqueTyId<Interner> { | ||
224 | db.intern_impl_trait_id(self).into() | ||
225 | } | ||
226 | |||
227 | fn from_chalk( | ||
228 | db: &dyn HirDatabase, | ||
229 | opaque_ty_id: chalk_ir::OpaqueTyId<Interner>, | ||
230 | ) -> OpaqueTyId { | ||
231 | db.lookup_intern_impl_trait_id(opaque_ty_id.into()) | ||
232 | } | ||
233 | } | ||
234 | |||
207 | impl ToChalk for TypeCtor { | 235 | impl ToChalk for TypeCtor { |
208 | type Chalk = TypeName<Interner>; | 236 | type Chalk = TypeName<Interner>; |
209 | 237 | ||
@@ -214,6 +242,11 @@ impl ToChalk for TypeCtor { | |||
214 | TypeName::AssociatedType(type_id) | 242 | TypeName::AssociatedType(type_id) |
215 | } | 243 | } |
216 | 244 | ||
245 | TypeCtor::OpaqueType(impl_trait_id) => { | ||
246 | let id = impl_trait_id.to_chalk(db); | ||
247 | TypeName::OpaqueType(id) | ||
248 | } | ||
249 | |||
217 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), | 250 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), |
218 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), | 251 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), |
219 | TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), | 252 | TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), |
@@ -252,7 +285,9 @@ impl ToChalk for TypeCtor { | |||
252 | match type_name { | 285 | match type_name { |
253 | TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), | 286 | TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), |
254 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | 287 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), |
255 | TypeName::OpaqueType(_) => unreachable!(), | 288 | TypeName::OpaqueType(opaque_type_id) => { |
289 | TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)) | ||
290 | } | ||
256 | 291 | ||
257 | TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, | 292 | TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, |
258 | TypeName::Scalar(Scalar::Char) => TypeCtor::Char, | 293 | TypeName::Scalar(Scalar::Char) => TypeCtor::Char, |
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs index d88828c7c..556af7098 100644 --- a/crates/ra_hir_ty/src/traits/chalk/tls.rs +++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs | |||
@@ -69,6 +69,11 @@ impl DebugContext<'_> { | |||
69 | let name = self.0.type_alias_data(type_alias).name.clone(); | 69 | let name = self.0.type_alias_data(type_alias).name.clone(); |
70 | write!(f, "{}::{}", trait_name, name)?; | 70 | write!(f, "{}::{}", trait_name, name)?; |
71 | } | 71 | } |
72 | TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id { | ||
73 | crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | ||
74 | write!(f, "{{impl trait {} of {:?}}}", idx, func)?; | ||
75 | } | ||
76 | }, | ||
72 | TypeCtor::Closure { def, expr } => { | 77 | TypeCtor::Closure { def, expr } => { |
73 | write!(f, "{{closure {:?} in ", expr.into_raw())?; | 78 | write!(f, "{{closure {:?} in ", expr.into_raw())?; |
74 | match def { | 79 | match def { |