aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/traits
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/traits')
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs112
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs4
2 files changed, 108 insertions, 8 deletions
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index 394232fd9..3c8dd4af8 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -4,8 +4,12 @@ use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId};
4use hir_expand::name::name; 4use hir_expand::name::name;
5use ra_db::CrateId; 5use ra_db::CrateId;
6 6
7use super::{AssocTyValue, Impl}; 7use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData};
8use crate::{db::HirDatabase, utils::generics, ApplicationTy, Substs, TraitRef, Ty, TypeCtor}; 8use crate::{
9 db::HirDatabase,
10 utils::{all_super_traits, generics},
11 ApplicationTy, GenericPredicate, Substs, TraitRef, Ty, TypeCtor,
12};
9 13
10pub(super) struct BuiltinImplData { 14pub(super) struct BuiltinImplData {
11 pub num_vars: usize, 15 pub num_vars: usize,
@@ -25,6 +29,8 @@ pub(super) fn get_builtin_impls(
25 db: &impl HirDatabase, 29 db: &impl HirDatabase,
26 krate: CrateId, 30 krate: CrateId,
27 ty: &Ty, 31 ty: &Ty,
32 // The first argument for the trait, if present
33 arg: &Option<Ty>,
28 trait_: TraitId, 34 trait_: TraitId,
29 mut callback: impl FnMut(Impl), 35 mut callback: impl FnMut(Impl),
30) { 36) {
@@ -43,14 +49,43 @@ pub(super) fn get_builtin_impls(
43 } 49 }
44 } 50 }
45 } 51 }
52
53 let unsize_trait = get_unsize_trait(db, krate);
54 if let Some(actual_trait) = unsize_trait {
55 if trait_ == actual_trait {
56 get_builtin_unsize_impls(db, krate, ty, arg, callback);
57 }
58 }
59}
60
61fn get_builtin_unsize_impls(
62 db: &impl HirDatabase,
63 krate: CrateId,
64 ty: &Ty,
65 // The first argument for the trait, if present
66 arg: &Option<Ty>,
67 mut callback: impl FnMut(Impl),
68) {
69 if !check_unsize_impl_prerequisites(db, krate) {
70 return;
71 }
72
46 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, .. }) = ty { 73 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, .. }) = ty {
47 if let Some(actual_trait) = get_unsize_trait(db, krate) { 74 callback(Impl::UnsizeArray);
48 if trait_ == actual_trait { 75 }
49 if check_unsize_impl_prerequisites(db, krate) { 76
50 callback(Impl::UnsizeArray); 77 if let Some(target_trait) = arg.as_ref().and_then(|t| t.dyn_trait_ref()) {
51 } 78 if let Some(trait_ref) = ty.dyn_trait_ref() {
79 let super_traits = all_super_traits(db, trait_ref.trait_);
80 if super_traits.contains(&target_trait.trait_) {
81 // callback(Impl::UnsizeToSuperTraitObject(UnsizeToSuperTraitObjectData {
82 // trait_: trait_ref.trait_,
83 // super_trait: target_trait.trait_,
84 // }));
52 } 85 }
53 } 86 }
87
88 callback(Impl::UnsizeToTraitObject(target_trait.trait_));
54 } 89 }
55} 90}
56 91
@@ -59,6 +94,10 @@ pub(super) fn impl_datum(db: &impl HirDatabase, krate: CrateId, impl_: Impl) ->
59 Impl::ImplBlock(_) => unreachable!(), 94 Impl::ImplBlock(_) => unreachable!(),
60 Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), 95 Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data),
61 Impl::UnsizeArray => array_unsize_impl_datum(db, krate), 96 Impl::UnsizeArray => array_unsize_impl_datum(db, krate),
97 Impl::UnsizeToTraitObject(trait_) => trait_object_unsize_impl_datum(db, krate, trait_),
98 Impl::UnsizeToSuperTraitObject(data) => {
99 super_trait_object_unsize_impl_datum(db, krate, data)
100 }
62 } 101 }
63} 102}
64 103
@@ -216,6 +255,65 @@ fn array_unsize_impl_datum(db: &impl HirDatabase, krate: CrateId) -> BuiltinImpl
216 } 255 }
217} 256}
218 257
258// Trait object unsizing
259
260fn trait_object_unsize_impl_datum(
261 db: &impl HirDatabase,
262 krate: CrateId,
263 trait_: TraitId,
264) -> BuiltinImplData {
265 // impl<T, T1, ...> Unsize<dyn Trait<T1, ...>> for T where T: Trait<T1, ...>
266
267 let unsize_trait = get_unsize_trait(db, krate) // get unsize trait
268 // the existence of the Unsize trait has been checked before
269 .expect("Unsize trait missing");
270
271 let self_ty = Ty::Bound(0);
272
273 let substs = Substs::build_for_def(db, trait_)
274 // this fits together nicely: $0 is our self type, and the rest are the type
275 // args for the trait
276 .fill_with_bound_vars(0)
277 .build();
278 let trait_ref = TraitRef { trait_, substs };
279 // This is both the bound for the `dyn` type, *and* the bound for the impl!
280 // This works because the self type for `dyn` is always Ty::Bound(0), which
281 // we've also made the parameter for our impl self type.
282 let bounds = vec![GenericPredicate::Implemented(trait_ref)];
283
284 let impl_substs = Substs::builder(2).push(self_ty).push(Ty::Dyn(bounds.clone().into())).build();
285
286 let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs };
287
288 BuiltinImplData { num_vars: 1, trait_ref, where_clauses: bounds, assoc_ty_values: Vec::new() }
289}
290
291fn super_trait_object_unsize_impl_datum(
292 db: &impl HirDatabase,
293 krate: CrateId,
294 _data: UnsizeToSuperTraitObjectData,
295) -> BuiltinImplData {
296 // impl Unsize<dyn SuperTrait> for dyn Trait
297
298 let unsize_trait = get_unsize_trait(db, krate) // get unsize trait
299 // the existence of the Unsize trait has been checked before
300 .expect("Unsize trait missing");
301
302 let substs = Substs::builder(2)
303 // .push(Ty::Dyn(todo!()))
304 // .push(Ty::Dyn(todo!()))
305 .build();
306
307 let trait_ref = TraitRef { trait_: unsize_trait, substs };
308
309 BuiltinImplData {
310 num_vars: 1,
311 trait_ref,
312 where_clauses: Vec::new(),
313 assoc_ty_values: Vec::new(),
314 }
315}
316
219fn get_fn_trait( 317fn get_fn_trait(
220 db: &impl HirDatabase, 318 db: &impl HirDatabase,
221 krate: CrateId, 319 krate: CrateId,
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 1bdf13e48..e1e430aeb 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -572,8 +572,10 @@ where
572 .collect(); 572 .collect();
573 573
574 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); 574 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone());
575 let arg: Option<Ty> =
576 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref().clone()));
575 577
576 builtin::get_builtin_impls(self.db, self.krate, &ty, trait_, |i| { 578 builtin::get_builtin_impls(self.db, self.krate, &ty, &arg, trait_, |i| {
577 result.push(i.to_chalk(self.db)) 579 result.push(i.to_chalk(self.db))
578 }); 580 });
579 581