diff options
Diffstat (limited to 'crates/hir_ty/src/traits/chalk.rs')
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 127 |
1 files changed, 98 insertions, 29 deletions
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 01b5717a3..27f0ed628 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | lang_item::{lang_attr, LangItemTarget}, | 11 | lang_item::{lang_attr, LangItemTarget}, |
12 | AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, | 12 | AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, |
13 | }; | 13 | }; |
14 | use hir_expand::name::name; | ||
14 | 15 | ||
15 | use super::ChalkContext; | 16 | use super::ChalkContext; |
16 | use crate::{ | 17 | use crate::{ |
@@ -18,10 +19,12 @@ use crate::{ | |||
18 | display::HirDisplay, | 19 | display::HirDisplay, |
19 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, | 20 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, |
20 | utils::generics, | 21 | utils::generics, |
21 | CallableDefId, DebruijnIndex, FnSig, GenericPredicate, Substs, Ty, TypeCtor, | 22 | BoundVar, CallableDefId, DebruijnIndex, FnSig, GenericPredicate, ProjectionPredicate, |
23 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | ||
22 | }; | 24 | }; |
23 | use mapping::{ | 25 | use mapping::{ |
24 | convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, | 26 | convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType, |
27 | TypeAliasAsValue, | ||
25 | }; | 28 | }; |
26 | 29 | ||
27 | pub use self::interner::*; | 30 | pub use self::interner::*; |
@@ -166,27 +169,88 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
166 | fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> { | 169 | fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> { |
167 | let interned_id = crate::db::InternedOpaqueTyId::from(id); | 170 | let interned_id = crate::db::InternedOpaqueTyId::from(id); |
168 | let full_id = self.db.lookup_intern_impl_trait_id(interned_id); | 171 | let full_id = self.db.lookup_intern_impl_trait_id(interned_id); |
169 | let (func, idx) = match full_id { | 172 | let bound = match full_id { |
170 | crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => (func, idx), | 173 | crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
171 | }; | 174 | let datas = self |
172 | let datas = | 175 | .db |
173 | self.db.return_type_impl_traits(func).expect("impl trait id without impl traits"); | 176 | .return_type_impl_traits(func) |
174 | let data = &datas.value.impl_traits[idx as usize]; | 177 | .expect("impl trait id without impl traits"); |
175 | let bound = OpaqueTyDatumBound { | 178 | let data = &datas.value.impl_traits[idx as usize]; |
176 | bounds: make_binders( | 179 | let bound = OpaqueTyDatumBound { |
177 | data.bounds | 180 | bounds: make_binders( |
178 | .value | 181 | data.bounds |
179 | .iter() | 182 | .value |
180 | .cloned() | 183 | .iter() |
181 | .filter(|b| !b.is_error()) | 184 | .cloned() |
182 | .map(|b| b.to_chalk(self.db)) | 185 | .filter(|b| !b.is_error()) |
183 | .collect(), | 186 | .map(|b| b.to_chalk(self.db)) |
184 | 1, | 187 | .collect(), |
185 | ), | 188 | 1, |
186 | where_clauses: make_binders(vec![], 0), | 189 | ), |
190 | where_clauses: make_binders(vec![], 0), | ||
191 | }; | ||
192 | let num_vars = datas.num_binders; | ||
193 | make_binders(bound, num_vars) | ||
194 | } | ||
195 | crate::OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | ||
196 | if let Some((future_trait, future_output)) = self | ||
197 | .db | ||
198 | .lang_item(self.krate, "future_trait".into()) | ||
199 | .and_then(|item| item.as_trait()) | ||
200 | .and_then(|trait_| { | ||
201 | let alias = | ||
202 | self.db.trait_data(trait_).associated_type_by_name(&name![Output])?; | ||
203 | Some((trait_, alias)) | ||
204 | }) | ||
205 | { | ||
206 | // Making up `AsyncBlock<T>: Future<Output = T>` | ||
207 | // | ||
208 | // |--------------------OpaqueTyDatum-------------------| | ||
209 | // |-------------OpaqueTyDatumBound--------------| | ||
210 | // for<T> <Self> [Future<Self>, Future::Output<Self> = T] | ||
211 | // ^1 ^0 ^0 ^0 ^1 | ||
212 | let impl_bound = GenericPredicate::Implemented(TraitRef { | ||
213 | trait_: future_trait, | ||
214 | // Self type as the first parameter. | ||
215 | substs: Substs::single(Ty::Bound(BoundVar { | ||
216 | debruijn: DebruijnIndex::INNERMOST, | ||
217 | index: 0, | ||
218 | })), | ||
219 | }); | ||
220 | let proj_bound = GenericPredicate::Projection(ProjectionPredicate { | ||
221 | // The parameter of the opaque type. | ||
222 | ty: Ty::Bound(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }), | ||
223 | projection_ty: ProjectionTy { | ||
224 | associated_ty: future_output, | ||
225 | // Self type as the first parameter. | ||
226 | parameters: Substs::single(Ty::Bound(BoundVar::new( | ||
227 | DebruijnIndex::INNERMOST, | ||
228 | 0, | ||
229 | ))), | ||
230 | }, | ||
231 | }); | ||
232 | let bound = OpaqueTyDatumBound { | ||
233 | bounds: make_binders( | ||
234 | vec![impl_bound.to_chalk(self.db), proj_bound.to_chalk(self.db)], | ||
235 | 1, | ||
236 | ), | ||
237 | where_clauses: make_binders(vec![], 0), | ||
238 | }; | ||
239 | // The opaque type has 1 parameter. | ||
240 | make_binders(bound, 1) | ||
241 | } else { | ||
242 | // If failed to find `Future::Output`, return empty bounds as fallback. | ||
243 | let bound = OpaqueTyDatumBound { | ||
244 | bounds: make_binders(vec![], 0), | ||
245 | where_clauses: make_binders(vec![], 0), | ||
246 | }; | ||
247 | // The opaque type has 1 parameter. | ||
248 | make_binders(bound, 1) | ||
249 | } | ||
250 | } | ||
187 | }; | 251 | }; |
188 | let num_vars = datas.num_binders; | 252 | |
189 | Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) }) | 253 | Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound }) |
190 | } | 254 | } |
191 | 255 | ||
192 | fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { | 256 | fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { |
@@ -277,7 +341,7 @@ pub(crate) fn associated_ty_data_query( | |||
277 | id: AssocTypeId, | 341 | id: AssocTypeId, |
278 | ) -> Arc<AssociatedTyDatum> { | 342 | ) -> Arc<AssociatedTyDatum> { |
279 | debug!("associated_ty_data {:?}", id); | 343 | debug!("associated_ty_data {:?}", id); |
280 | let type_alias: TypeAliasId = from_chalk(db, id); | 344 | let type_alias: TypeAliasId = from_chalk::<TypeAliasAsAssocType, _>(db, id).0; |
281 | let trait_ = match type_alias.lookup(db.upcast()).container { | 345 | let trait_ = match type_alias.lookup(db.upcast()).container { |
282 | AssocContainerId::TraitId(t) => t, | 346 | AssocContainerId::TraitId(t) => t, |
283 | _ => panic!("associated type not in trait"), | 347 | _ => panic!("associated type not in trait"), |
@@ -331,8 +395,10 @@ pub(crate) fn trait_datum_query( | |||
331 | fundamental: false, | 395 | fundamental: false, |
332 | }; | 396 | }; |
333 | let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); | 397 | let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); |
334 | let associated_ty_ids = | 398 | let associated_ty_ids = trait_data |
335 | trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); | 399 | .associated_types() |
400 | .map(|type_alias| TypeAliasAsAssocType(type_alias).to_chalk(db)) | ||
401 | .collect(); | ||
336 | let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; | 402 | let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; |
337 | let well_known = | 403 | let well_known = |
338 | lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); | 404 | lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); |
@@ -370,6 +436,7 @@ fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str { | |||
370 | WellKnownTrait::FnMut => "fn_mut", | 436 | WellKnownTrait::FnMut => "fn_mut", |
371 | WellKnownTrait::Fn => "fn", | 437 | WellKnownTrait::Fn => "fn", |
372 | WellKnownTrait::Unsize => "unsize", | 438 | WellKnownTrait::Unsize => "unsize", |
439 | WellKnownTrait::Unpin => "unpin", | ||
373 | } | 440 | } |
374 | } | 441 | } |
375 | 442 | ||
@@ -513,7 +580,7 @@ fn type_alias_associated_ty_value( | |||
513 | let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; | 580 | let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; |
514 | let value = rust_ir::AssociatedTyValue { | 581 | let value = rust_ir::AssociatedTyValue { |
515 | impl_id: impl_id.to_chalk(db), | 582 | impl_id: impl_id.to_chalk(db), |
516 | associated_ty_id: assoc_ty.to_chalk(db), | 583 | associated_ty_id: TypeAliasAsAssocType(assoc_ty).to_chalk(db), |
517 | value: make_binders(value_bound, ty.num_binders), | 584 | value: make_binders(value_bound, ty.num_binders), |
518 | }; | 585 | }; |
519 | Arc::new(value) | 586 | Arc::new(value) |
@@ -548,9 +615,11 @@ pub(crate) fn fn_def_datum_query( | |||
548 | }; | 615 | }; |
549 | let datum = FnDefDatum { | 616 | let datum = FnDefDatum { |
550 | id: fn_def_id, | 617 | id: fn_def_id, |
551 | abi: (), | 618 | sig: chalk_ir::FnSig { |
552 | safety: chalk_ir::Safety::Safe, | 619 | abi: (), |
553 | variadic: sig.value.is_varargs, | 620 | safety: chalk_ir::Safety::Safe, |
621 | variadic: sig.value.is_varargs, | ||
622 | }, | ||
554 | binders: make_binders(bound, sig.num_binders), | 623 | binders: make_binders(bound, sig.num_binders), |
555 | }; | 624 | }; |
556 | Arc::new(datum) | 625 | Arc::new(datum) |