]>
Commit | Line | Data |
---|---|---|
f035d41b | 1 | use super::{builder::ClauseBuilder, generalize}; |
3dfed10e | 2 | use crate::{CanonicalVarKinds, Interner, RustIrDatabase, TraitRef, WellKnownTrait}; |
f035d41b | 3 | use chalk_ir::{Floundered, Substitution, Ty}; |
f9f354fc XL |
4 | |
5 | mod clone; | |
6 | mod copy; | |
f035d41b | 7 | mod fn_family; |
f9f354fc | 8 | mod sized; |
f035d41b | 9 | mod unsize; |
f9f354fc XL |
10 | |
11 | /// For well known traits we have special hard-coded impls, either as an | |
12 | /// optimization or to enforce special rules for correctness. | |
13 | pub fn add_builtin_program_clauses<I: Interner>( | |
14 | db: &dyn RustIrDatabase<I>, | |
15 | builder: &mut ClauseBuilder<'_, I>, | |
16 | well_known: WellKnownTrait, | |
17 | trait_ref: &TraitRef<I>, | |
3dfed10e | 18 | binders: &CanonicalVarKinds<I>, |
f035d41b XL |
19 | ) -> Result<(), Floundered> { |
20 | // If `trait_ref` contains bound vars, we want to universally quantify them. | |
21 | // `Generalize` collects them for us. | |
22 | let generalized = generalize::Generalize::apply(db.interner(), trait_ref); | |
23 | ||
24 | builder.push_binders(&generalized, |builder, trait_ref| { | |
25 | let self_ty = trait_ref.self_type_parameter(db.interner()); | |
26 | let ty = self_ty.data(db.interner()); | |
f9f354fc | 27 | |
f035d41b | 28 | match well_known { |
3dfed10e XL |
29 | WellKnownTrait::Sized => { |
30 | sized::add_sized_program_clauses(db, builder, &trait_ref, ty, binders) | |
31 | } | |
32 | WellKnownTrait::Copy => { | |
33 | copy::add_copy_program_clauses(db, builder, &trait_ref, ty, binders) | |
34 | } | |
35 | WellKnownTrait::Clone => { | |
36 | clone::add_clone_program_clauses(db, builder, &trait_ref, ty, binders) | |
37 | } | |
f035d41b XL |
38 | WellKnownTrait::FnOnce | WellKnownTrait::FnMut | WellKnownTrait::Fn => { |
39 | fn_family::add_fn_trait_program_clauses(db, builder, well_known, self_ty)? | |
40 | } | |
41 | WellKnownTrait::Unsize => { | |
42 | unsize::add_unsize_program_clauses(db, builder, &trait_ref, ty) | |
43 | } | |
44 | // Drop impls are provided explicitly | |
45 | WellKnownTrait::Drop => (), | |
46 | } | |
47 | Ok(()) | |
48 | }) | |
49 | } | |
50 | ||
51 | /// Like `add_builtin_program_clauses`, but for `DomainGoal::Normalize` involving | |
52 | /// a projection (e.g. `<fn(u8) as FnOnce<(u8,)>>::Output`) | |
53 | pub fn add_builtin_assoc_program_clauses<I: Interner>( | |
54 | db: &dyn RustIrDatabase<I>, | |
55 | builder: &mut ClauseBuilder<'_, I>, | |
56 | well_known: WellKnownTrait, | |
57 | self_ty: Ty<I>, | |
58 | ) -> Result<(), Floundered> { | |
f9f354fc | 59 | match well_known { |
f035d41b XL |
60 | WellKnownTrait::FnOnce => { |
61 | // If `self_ty` contains bound vars, we want to universally quantify them. | |
62 | // `Generalize` collects them for us. | |
63 | let generalized = generalize::Generalize::apply(db.interner(), &self_ty); | |
64 | ||
65 | builder.push_binders(&generalized, |builder, self_ty| { | |
66 | fn_family::add_fn_trait_program_clauses(db, builder, well_known, self_ty)?; | |
67 | Ok(()) | |
68 | }) | |
69 | } | |
70 | _ => Ok(()), | |
f9f354fc XL |
71 | } |
72 | } | |
73 | ||
74 | /// Given a trait ref `T0: Trait` and a list of types `U0..Un`, pushes a clause of the form | |
75 | /// `Implemented(T0: Trait) :- Implemented(U0: Trait) .. Implemented(Un: Trait)` | |
76 | pub fn needs_impl_for_tys<I: Interner>( | |
77 | db: &dyn RustIrDatabase<I>, | |
78 | builder: &mut ClauseBuilder<'_, I>, | |
79 | trait_ref: &TraitRef<I>, | |
80 | tys: impl Iterator<Item = Ty<I>>, | |
81 | ) { | |
82 | // The trait must take one parameter (a type) | |
83 | debug_assert_eq!( | |
84 | db.trait_datum(trait_ref.trait_id) | |
85 | .binders | |
86 | .len(db.interner()), | |
87 | 1, | |
88 | ); | |
89 | builder.push_clause( | |
90 | trait_ref.clone(), | |
91 | tys.map(|ty| TraitRef { | |
92 | trait_id: trait_ref.trait_id, | |
93 | substitution: Substitution::from1(db.interner(), ty), | |
94 | }), | |
95 | ); | |
96 | } |