implied_bounds/_lib.rs
1#![doc = include_str!("../README.md")]
2#![no_std]
3#![forbid(unsafe_code)]
4#![allow(unused_braces)]
5
6pub use helper_trait::ImpliedPredicate;
7mod helper_trait;
8
9/// Convenience attribute macro to help one rewrite a `trait` definition as per the rules described
10/// in the documentation of [`ImpliedPredicate`].
11///
12/// Indeed, that trait is very handy, but its usage is neither very obvious to write, nor very
13/// readable afterwards.
14///
15/// But it is actually a very mechanical operation, hence being a good fit for macro automation ๐
16///
17/// ## Example
18///
19/// The following fails to compile:
20///
21/// ```rust ,compile_fail
22/// trait Trait<U: Clone>
23/// where
24/// Self::Gat<true>: Send,
25/// {
26/// type Gat<const IS_SEND: bool>;
27/// }
28///
29/// fn demo<T: Trait<U>, U>()
30/// where
31/// // โ Error, missing:
32/// // U: Clone,
33/// // T::Gat<true>: Send,
34/// {}
35/// ```
36///
37/// - Error message:
38///
39/// <details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
40///
41/// ```rust ,ignore
42/// # /*
43/// error[E0277]: the trait bound `U: Clone` is not satisfied
44/// --> src/_lib.rs:29:12
45/// |
46/// 10 | fn demo<T: Trait<U>, U>()
47/// | ^^^^^^^^ the trait `Clone` is not implemented for `U`
48/// |
49/// note: required by a bound in `Trait`
50/// --> src/_lib.rs:22:16
51/// |
52/// 3 | trait Trait<U: Clone>
53/// | ^^^^^ required by this bound in `Trait`
54/// help: consider restricting type parameter `U`
55/// |
56/// 10 | fn demo<T: Trait<U>, U: std::clone::Clone>()
57/// | +++++++++++++++++++
58///
59/// error[E0277]: `<T as Trait<U>>::Gat<true>` cannot be sent between threads safely
60/// --> src/_lib.rs:29:12
61/// |
62/// 10 | fn demo<T: Trait<U>, U>()
63/// | ^^^^^^^^ `<T as Trait<U>>::Gat<true>` cannot be sent between threads safely
64/// |
65/// = help: the trait `Send` is not implemented for `<T as Trait<U>>::Gat<true>`
66/// note: required by a bound in `Trait`
67/// --> src/_lib.rs:24:22
68/// |
69/// 3 | trait Trait<U: Clone>
70/// | ----- required by a bound in this trait
71/// 4 | where
72/// 5 | Self::Gat<true>: Send,
73/// | ^^^^ required by this bound in `Trait`
74/// help: consider further restricting the associated type
75/// |
76/// 11 | where <T as Trait<U>>::Gat<true>: Send
77/// | ++++++++++++++++++++++++++++++++
78/// # */
79/// ```
80///
81/// </details>
82///
83/// You can easily fix this by slapping the <code>[#\[implied_bounds\]][`implied_bounds`]</code>
84/// attribute on it:
85///
86/// ```rust
87/// #[::implied_bounds::implied_bounds] // ๐
88/// trait Trait<U: Clone>
89/// where
90/// Self::Gat<true>: Send,
91/// {
92/// type Gat<const IS_SEND: bool>;
93/// }
94///
95/// fn demo<T: Trait<U>, U>()
96/// where
97/// // OK โ
98/// {}
99/// ```
100///
101/// This shall not change anything for implementors (they have to abide by the provided
102/// bounds/clauses/predicates no matter whether the
103/// <code>[#\[implied_bounds\]][`implied_bounds`]</code> attribute is used or not, and it shall
104/// suffice).
105///
106/// ## How does the macro work
107///
108/// - Tip: you can provide the `debug` arg to the attribute for it to highlight the non-implied
109/// clauses it shall rewrite:
110///
111/// ```rust
112/// # /*
113/// // ๐
114/// #[implied_bounds(debug)]
115/// trait ...
116/// # */
117/// ```
118///
119/// The attribute identifies the non-implied clauses (bounds on generic type parameters, as well
120/// as `where` clauses where the left-hand-side (bounded type) is not `Self`), and rewrites them
121/// using [`ImpliedPredicate`], like this:
122///
123/// ```rust
124/// #[::implied_bounds::implied_bounds] // ๐
125/// trait Trait<U: Clone>
126/// where
127/// Self::Gat<true>: Send,
128/// {
129/// type Gat<const IS_SEND: bool>;
130/// }
131/// ```
132///
133/// becomes:
134///
135/// ```rust
136/// trait Trait<U>
137/// :
138/// ::implied_bounds::ImpliedPredicate<U, Impls: Clone> +
139/// ::implied_bounds::ImpliedPredicate<Self::Gat<true>, Impls: Send> +
140/// {
141/// type Gat<const IS_SEND: bool>;
142/// }
143/// ```
144///
145/// where [`ImpliedPredicate`] is trivially-true / always-holding trait clause, on condition
146/// that it be well-formed, _i.e._, on condition that the bounds on its `Impls` associated type
147/// do hold; where its `Impls` associated type is defined to always be the same as the generic arg fed
148/// to it:
149///
150/// ```rust ,ignore
151/// X: Bounds
152/// <=>
153/// ImpliedPredicate<X, Impls: Bounds>
154/// ```
155pub use ::implied_bounds_proc_macros::implied_bounds;
156
157// macro internals
158#[doc(hidden)] /** Not part of the public API */ pub
159mod เถ {
160 pub use ::core; // or `std`
161
162 /// We reรซxport this, and rename it, merely so the diagnostics read a bit more nicely:
163 ///
164 /// That way we get:
165 ///
166 /// > which is required by `<Bar as implied_bounds::เถ::ImpliedPredicate<โฆ>`
167 ///
168 /// instead of:
169 ///
170 /// > which is required by `<Bar as implied_bounds::helper_trait::HasAssoc<โฆ>`
171 pub use crate::helper_trait::HasAssoc as ImpliedPredicate;
172}
173
174#[doc = include_str!("compile_fail_tests.md")]
175mod _compile_fail_tests {}