# `::implied-bounds`
<img
src="https://raw.githubusercontent.com/danielhenrymantilla/implied-bounds.rs/refs/tags/c1244e3/457381166-528cd8ea-f954-434c-a7f2-6147e82cc10b.png"
height="100px"
/>
Trait trick and helper convenience macro to make **all** of the bounds of a trait definition be
properly _implied/entailed_, as expected, avoiding "non-entailment" bugs which the current trait
system has.
[](
https://github.com/danielhenrymantilla/implied-bounds.rs)
[](
https://crates.io/crates/implied-bounds)
[](
https://docs.rs/implied-bounds)
[](
https://gist.github.com/danielhenrymantilla/9b59de4db8e5f2467ed008b3c450527b)
[](
https://github.com/rust-secure-code/safety-dance/)
[](
https://github.com/danielhenrymantilla/implied-bounds.rs/blob/master/LICENSE-ZLIB)
[](
https://github.com/danielhenrymantilla/implied-bounds.rs/actions)
[](
https://github.com/rust-secure-code/safety-dance/)
# Prior Context
<img
src="https://raw.githubusercontent.com/danielhenrymantilla/implied-bounds.rs/refs/tags/c1244e3/457462208-0e3dc973-57e3-4fcd-9e21-a56e3dff8ffb.png"
height="300px"
/>
<details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
In Rust, when defining a `trait` or some helper type, such as a `struct`, certain bounds are
**not** _implied/entailed_, which is probably contrary to the user/human expectation, and thus,
surprising, unintuitive, and being honest, annoying, since it then requires the user of such `trait`
and `struct` to be repeating the bounds.
```rust ,compile_fail
struct Typical<T: Clone>(T);
fn demo<T>(_: Typical<T>) {} // Error, missing `T: Clone`…
```
- Error message:
<details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
```rust ,ignore
#
```
</details>
And likewise for a `trait`:
```rust ,compile_fail
trait MyTrait<U: Clone> {}
fn demo<T: MyTrait<U>, U>() {} // Error, missing `U: Clone`…
```
- Error message:
<details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
```rust ,ignore
#
```
</details>
Enter this crate.
</details>
# What this crate offers
are tools to alleviate the `trait` case (currently, there is no special tooling for the `struct`
case, but some may be added in the future).
Mainly:
- the maximally convenient [`#[implied_bounds]`][`implied_bounds`] attribute:
```rust
#[::implied_bounds::implied_bounds] trait MyTrait<U: Clone> {}
fn demo<T: MyTrait<U>, U>() {} ```
- Otherwise, if you are wary of magical macros and prefer magical type-system stuff (🤷), if
anything, because they do not impact from-scratch compile-time, you can directly use
[`ImpliedPredicate`] (which is the helper trait used by the macro, under the hood, in its
expansion).
```rust
trait MyTrait<U >
:
::implied_bounds::ImpliedPredicate<U, Impls: Clone> + {}
fn demo<T: MyTrait<U>, U>() {} ```
- Note: you can disable the macro API —and thus, its compilation— by disabling the
otherwise-enabled-by-`"default"` `"proc-macros"` Cargo feature.
Do note, however, that:
- the macro involves a couple of extra knowledge-savy heuristics so as to maximize the
quality of the diagnostics should implementors fail to abide by the clauses of trait;
- the compile-time impact of `syn` with `"full"` features (the only noticeable thing) is:
- of about 1 full second, tops;
- only encountered when compiling _from scratch_, since it's otherwise cached;
- and only avoidable if you curate every transitive dependency of your dependency tree
to avoid it, even though inevitably some crate somewhere shall pull it in,
eventually.
> _Let he who is without `syn` cast the first `build`._
## Which predicates are currently not implied/entailed?
<details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
- Bounds on generic parameters:
```rust
trait Example<U: Clone> {}
```
- `where` clauses wherein the left hand side ("bounded type") of the predicate is neither
`Self` nor a simple associated type:
```rust
trait Example
where
Self : Sized, Self::SimpleAssoc : Send,
String : Into<Self>,
for<'r> &'r Self : IntoIterator,
Self::Gat<true> : Send,
{
type SimpleAssoc;
type Gat<const IS_SEND: bool>;
}
```
- Note that that last `Self::Gat<true> : Send` clause can be rewritten as a `where` clause on
the GAT itself:
```rust
trait Example {
type Gat<const IS_SEND: bool> where Self::Gat<true> : Send;
}
```
This is both equivalent to the other syntax, and not detected/handled by the
[`#[implied_bounds]`][`implied_bounds`] attribute, so be aware you may need to hoist such
clauses to the top-level/`trait`-level `where` clauses in order for the attribute to pick
them up and make them correctly implied/entailed.
</details>
# Inspiration / Credit be given where it is due
The ideas behind the design of the [`ImpliedPredicate`] trait were brought to my attention courtesy
of the [`::imply-hack`](https://docs.rs/imply-hack/0.1.0) crate, from
[`@gtsiam`](https://github.com/gtsiam). Thank you!
I have gone with my own take on the matter, mainly:
- to have the convenience macro;
- to slightly rename the `Is` assoc type as `Impls`, and pay special attention to the
erroring diagnostics to make them as pretty as possible (mostly done in the macro).
[`implied_bounds`]: https://docs.rs/implied-bounds/^0.1.0/implied_bounds/attr.implied_bounds.html
[`ImpliedPredicate`]: https://docs.rs/implied-bounds/^0.1.0/ImpliedPredicate/trait.ImpliedPredicate.html