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 | |
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')
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 52 | ||||
-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 |
4 files changed, 89 insertions, 15 deletions
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 61de3cc30..a72a82f5a 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -4,7 +4,7 @@ use std::sync::Arc; | |||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; | 6 | use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; |
7 | use chalk_solve::rust_ir::{self, WellKnownTrait}; | 7 | use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; |
8 | 8 | ||
9 | use hir_def::{ | 9 | use hir_def::{ |
10 | lang_item::{lang_attr, LangItemTarget}, | 10 | lang_item::{lang_attr, LangItemTarget}, |
@@ -100,6 +100,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
100 | fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> { | 100 | fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> { |
101 | self.db.associated_ty_value(self.krate, id) | 101 | self.db.associated_ty_value(self.krate, id) |
102 | } | 102 | } |
103 | |||
103 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<Interner>> { | 104 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<Interner>> { |
104 | vec![] | 105 | vec![] |
105 | } | 106 | } |
@@ -130,11 +131,34 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
130 | self.db.program_clauses_for_chalk_env(self.krate, environment.clone()) | 131 | self.db.program_clauses_for_chalk_env(self.krate, environment.clone()) |
131 | } | 132 | } |
132 | 133 | ||
133 | fn opaque_ty_data( | 134 | fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> { |
134 | &self, | 135 | let interned_id = crate::db::InternedOpaqueTyId::from(id); |
135 | _id: chalk_ir::OpaqueTyId<Interner>, | 136 | let full_id = self.db.lookup_intern_impl_trait_id(interned_id); |
136 | ) -> Arc<rust_ir::OpaqueTyDatum<Interner>> { | 137 | let (func, idx) = match full_id { |
137 | unimplemented!() | 138 | crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => (func, idx), |
139 | }; | ||
140 | let datas = | ||
141 | self.db.return_type_impl_traits(func).expect("impl trait id without impl traits"); | ||
142 | let data = &datas.value.impl_traits[idx as usize]; | ||
143 | let bound = OpaqueTyDatumBound { | ||
144 | bounds: make_binders( | ||
145 | data.bounds | ||
146 | .value | ||
147 | .iter() | ||
148 | .cloned() | ||
149 | .filter(|b| !b.is_error()) | ||
150 | .map(|b| b.to_chalk(self.db)) | ||
151 | .collect(), | ||
152 | 1, | ||
153 | ), | ||
154 | }; | ||
155 | let num_vars = datas.num_binders; | ||
156 | Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) }) | ||
157 | } | ||
158 | |||
159 | fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { | ||
160 | // FIXME: actually provide the hidden type; it is relevant for auto traits | ||
161 | Ty::Unknown.to_chalk(self.db) | ||
138 | } | 162 | } |
139 | 163 | ||
140 | fn force_impl_for( | 164 | fn force_impl_for( |
@@ -150,10 +174,6 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
150 | // FIXME: implement actual object safety | 174 | // FIXME: implement actual object safety |
151 | true | 175 | true |
152 | } | 176 | } |
153 | |||
154 | fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { | ||
155 | Ty::Unknown.to_chalk(self.db) | ||
156 | } | ||
157 | } | 177 | } |
158 | 178 | ||
159 | pub(crate) fn program_clauses_for_chalk_env_query( | 179 | pub(crate) fn program_clauses_for_chalk_env_query( |
@@ -460,6 +480,18 @@ impl From<crate::traits::GlobalImplId> for ImplId { | |||
460 | } | 480 | } |
461 | } | 481 | } |
462 | 482 | ||
483 | impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId { | ||
484 | fn from(id: OpaqueTyId) -> Self { | ||
485 | InternKey::from_intern_id(id.0) | ||
486 | } | ||
487 | } | ||
488 | |||
489 | impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId { | ||
490 | fn from(id: crate::db::InternedOpaqueTyId) -> Self { | ||
491 | chalk_ir::OpaqueTyId(id.as_intern_id()) | ||
492 | } | ||
493 | } | ||
494 | |||
463 | impl From<rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId { | 495 | impl From<rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId { |
464 | fn from(id: rust_ir::AssociatedTyValueId<Interner>) -> Self { | 496 | fn from(id: rust_ir::AssociatedTyValueId<Interner>) -> Self { |
465 | Self::from_intern_id(id.0) | 497 | Self::from_intern_id(id.0) |
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 { |