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 {}