This document compares v0.5.11 with the current 0.7.0 worktree. It focuses on changes that can affect users of the crate. Internal refactoring details are not listed.
- The minimum supported Rust version was raised from Rust 1.60 to Rust 1.89.
- The crate now uses the Rust 2024 edition.
- Automatic trait bounds changed a lot. The generated
whereclauses are now based on the field types that the generated code really uses. This can remove old unnecessary bounds, but it can also change the public bounds of generated impls. - Precise generated bounds can show private field types in docs, compiler errors, or public
whereclauses. If your type is public, check that this is acceptable for your API. - Use
bound(*)when you want Educe to addParam: Traitfor every generic type parameter, similar to the built-in derives. This option was added after 0.5.11. Eqis now treated as a marker trait. Field-level equality settings such asignoreandmethodshould be written onPartialEq, not onEq.Intoderives now generateimpl From<YourType> for Targetby default. Callingvalue.into()still works through Rust's blanket impl, andTarget::from(value)also works. Use#[educe(Into(Target, into))]if you need a direct one-wayIntoimpl instead.- If you already wrote your own
From<YourType> for Targetimpl, check for conflicts with the new defaultIntobehavior.
- Automatic bounds are more precise and more clearly documented.
- Ignored fields and fields handled by a custom
methoddo not add automatic bounds for that trait. - Field types without generic parameters do not add constant bounds.
- Common standard library wrapper types are handled more carefully. For example,
Option<T>can addT: Trait, andVec<Box<T>>can add only the needed inner bound. - Types that always implement a trait, such as
PhantomData, raw pointers, function pointers, and selected standard library types, can avoid unnecessary bounds. - Other field types use precise bounds such as
Wrapper<T>: Cloneinstead of always falling back toT: Clone. - Self-recursive generic types are handled better. For example, a type like
List<T>containingBox<List<T>>can avoid trait solver overflow by adding bounds on the type parameters. - Mutually recursive generic types are still a known limitation. Use
bound(*)or a custombound(...)for those cases. - Related traits can inherit generated predicates when they are derived together by Educe:
CopyfromClone,EqandPartialOrdfromPartialEq, andOrdfromEqandPartialOrd. - Explicit
bound(...)values are used as written. If an explicit bound does not satisfy a required supertrait, the compiler will ask for the missing bound. - Older cases where bounds could leak from one generated impl into another were fixed.
Debugwith explicit field methods was fixed for generic types and now avoids more name clashes with user code.Debugoutput handles field names as strings. Tuple field names and custom names are printed more correctly, including tuple indexes such as0.Copy,Clone,Eq,PartialOrd, andOrdderive behavior is more consistent with their real Rust trait relationships.Copycan work with an Educe-generated or built-inCloneimpl, while still respecting the bounds thatCopyreally needs.PartialOrdandOrdwork together more consistently. When both are derived,PartialOrdcan followOrdfield settings such asignore,rank, andmethodso thatpartial_cmpandcmpstay consistent.- When both comparison traits are derived,
Ordcan followPartialOrdfield settings forignoreandrank. APartialOrdmethod cannot be reused forOrdbecause it returnsOption<Ordering>. Ordcan be built when thePartialOrdfeature is not enabled.Intosupports the new defaultFromgeneration for concrete target types and for generic target types whose type parameters are covered by the target type.
- Generated impls are marked with
#[automatically_derived]. - Lint-level attributes from the input type, such as
allow,expect,warn, anddeny, are copied to generated impls. This makes generated code behave more like built-in derives under strict lint settings. Anexpectis copied as anallow, so that a lint which only applies to the type itself does not turn the copy into an unfulfilled expectation. - Diagnostics for invalid attributes and helper parsing were improved.
- The README now has a dedicated Trait Bounds section that explains the automatic bound rules, bound inheritance,
bound(*), and known limitations. - Documentation for unsafe union derives is clearer. It now states that
Debug,PartialEq, andHashunion impls may read, compare, or hash the whole union memory, including padding bytes. - The trait documentation was updated so each trait points to the shared bound rules instead of repeating older simplified rules.
quotenow has a minimum version of1.0.44.proc-macro2now has a minimum version of1.0.80.enum-ordinalizewas updated from4.2to4.4.- The
rustversiondev-dependency was removed.