impl_tools/
lib.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6#![allow(clippy::needless_doctest_main)]
7// Lint advocates use of bool::then_some, stablizied in rustc 1.62.0
8#![allow(clippy::unnecessary_lazy_evaluations)]
9
10//! # Impl-tools
11//!
12//! [`#[autoimpl]`](macro@autoimpl) is an alternative to
13//! [`#[derive]`](macro@derive) with more features (also usable on traits).
14//!
15//! [`#[impl_default]`](macro@impl_default) is an alternative to
16//! `#[derive(Default)]` supporting field initializers.
17//!
18//! [`#[impl_self]`](macro@impl_self) provides `impl Self` syntax, avoiding the
19//! need to repeat generics when writing impls on a local type definition.
20//! This supercedes [`impl_scope!`] (except regarding [`macro@impl_default`]).
21//!
22//! [`impl_anon!`] is a function-like macro used to define and instantiate a
23//! unique (single-use) type. It supports everything supported by [`impl_scope!`]
24//! plus field initializers and (limited) automatic typing of fields.
25//!
26//! User-extensions to both [`#[autoimpl]`](macro@autoimpl) and [`macro@impl_self`]
27//! are possible with a custom proc-macro crate depending on
28//! [impl-tools-lib](https://crates.io/crates/impl-tools-lib).
29
30#[cfg(doctest)]
31doc_comment::doctest!("../README.md");
32
33extern crate proc_macro;
34
35use lib::{anon, scope};
36use proc_macro::TokenStream;
37use proc_macro_error2::{emit_call_site_error, proc_macro_error};
38use syn::parse_macro_input;
39
40use impl_tools_lib::{self as lib, autoimpl};
41
42/// Impl [`Default`] with given field or type initializers
43///
44/// This macro may be used in one of two ways.
45///
46/// NOTE: this macro is already partially obsolete since Rust 1.62 added support
47/// for [default enum variants](https://blog.rust-lang.org/2022/06/30/Rust-1.62.0/#default-enum-variants).
48/// Once [RFC 3681](https://github.com/rust-lang/rfcs/pull/3681) (default field values)
49/// is stable in this crate's MSRV, this macro will be deprecated.
50///
51/// ### Type-level initializer
52///
53/// ```
54/// # use impl_tools::impl_default;
55/// /// A simple enum; default value is Blue
56/// #[impl_default(Colour::Blue)]
57/// enum Colour {
58///     Red,
59///     Green,
60///     Blue,
61/// }
62///
63/// fn main() {
64///     assert!(matches!(Colour::default(), Colour::Blue));
65/// }
66/// ```
67///
68/// A where clause is optional: `#[impl_default(EXPR where BOUNDS)]`.
69///
70/// ### Field-level initializer
71///
72/// This variant only supports structs. Fields specified as `name: type = expr`
73/// will be initialized with `expr`, while other fields will be initialized with
74/// `Default::default()`.
75///
76/// ```
77/// # use impl_tools::{impl_default, impl_scope};
78/// impl_scope! {
79///     #[impl_default]
80///     struct Person {
81///         name: String = "Jane Doe".to_string(),
82///         age: u32 = 72,
83///         occupation: String,
84///     }
85/// }
86///
87/// fn main() {
88///     let person = Person::default();
89///     assert_eq!(person.name, "Jane Doe");
90///     assert_eq!(person.age, 72);
91///     assert_eq!(person.occupation, "");
92/// }
93/// ```
94///
95/// A where clause is optional: `#[impl_default(where BOUNDS)]`.
96#[proc_macro_attribute]
97#[proc_macro_error]
98pub fn impl_default(args: TokenStream, item: TokenStream) -> TokenStream {
99    let mut toks = item.clone();
100    match syn::parse::<lib::ImplDefault>(args) {
101        Ok(attr) => toks.extend(TokenStream::from(attr.expand(item.into()))),
102        Err(err) => {
103            emit_call_site_error!(err);
104            // Since this form of invocation only adds implementations, we can
105            // safely output the original item, thus reducing secondary errors.
106        }
107    }
108    toks
109}
110
111/// An alternative to the standard [`macro@derive`] macro
112///
113/// This macro may be used:
114///
115/// -   [On a type definition](#on-type-definitions), to implement a specified trait
116/// -   [On a trait definition](#on-trait-definitions), to implement the trait for specified types
117///     supporting [`Deref`]
118///
119/// # On type definitions
120///
121/// `#[autoimpl]` on type definitions functions similarly to [`#[derive]`](macro@derive). The differences are as follows.
122///
123/// There is no implied bound on generic parameters. Instead, bounds must be specified explicitly, using syntax like `where T: Clone`. The special syntax `where T: trait` may be used where `trait` desugars to the target trait for each implementation. An example:
124/// ```
125/// # use impl_tools::autoimpl;
126/// #[autoimpl(Clone, Debug where T: trait)]
127/// struct Wrapper<T>(pub T);
128/// ```
129///
130/// ### `ignore`
131///
132/// Traits like [`Debug`] may be implemented while `ignore`-ing some fields, for example:
133/// ```
134/// # use impl_tools::autoimpl;
135/// #[autoimpl(Debug ignore self.f)]
136/// struct PairWithFn<T> {
137///     x: f32,
138///     y: f32,
139///     f: fn(&T),
140/// }
141/// ```
142///
143/// ### `using`
144///
145/// Traits like [`Deref`] may be implemented by `using` a named field, for example:
146/// ```
147/// # use impl_tools::autoimpl;
148/// #[autoimpl(Deref, DerefMut using self.1)]
149/// struct AnnotatedWrapper<T>(String, T);
150/// ```
151/// In the above example, [`Deref::Target`] will be implemented as `T` (the type
152/// of the field `self.1`). The `Target` type may instead be specified explicitly:
153/// ```
154/// # use impl_tools::autoimpl;
155/// #[autoimpl(Deref<Target = T> using self.0)]
156/// struct MyBoxingWrapper<T: ?Sized>(Box<T>);
157/// ```
158///
159/// ## Supported traits
160///
161/// | Path | *ignore* | *using* | *notes* |
162/// |----- |--- |--- |--- |
163/// | [`::core::borrow::Borrow<T>`] | - | borrow target | `T` is type of target field |
164/// | [`::core::borrow::BorrowMut<T>`] | - | borrow target | `T` is type of target field |
165/// | [`::core::clone::Clone`] | yes | - | ignored fields use `Default::default()` |
166/// | [`::core::cmp::Eq`] | * | - | *allowed with `PartialEq` |
167/// | [`::core::cmp::Ord`] | yes | - | |
168/// | [`::core::cmp::PartialEq`] | yes | - | |
169/// | [`::core::cmp::PartialOrd`] | yes | - | |
170/// | [`::core::convert::AsRef<T>`] | - | ref target | `T` is type of target field |
171/// | [`::core::convert::AsMut<T>`] | - | ref target | `T` is type of target field |
172/// | [`::core::default::Default`] | - | - | [`macro@impl_default`] is a more flexible alternative |
173/// | [`::core::fmt::Debug`] | yes | - | |
174/// | [`::core::hash::Hash`] | yes | - | |
175/// | [`::core::marker::Copy`] | * | - | *allowed with `Clone` |
176/// | [`::core::ops::Deref`] | - | deref target | See [`Deref::Target` type](#dereftarget-type) below |
177/// | [`::core::ops::DerefMut`] | - | deref target | |
178///
179/// Traits are matched using the path, as follows:
180///
181/// -   Only the last component, e.g. `#[autoimpl(Clone)]`
182/// -   The full path with leading `::`, e.g. `#[autoimpl(::core::clone::Clone)]`
183/// -   The full path without leading `::`, e.g. `#[autoimpl(core::clone::Clone)]`
184/// -   The full path with/without leading `::`, using `std` instead of `core` or `alloc`,
185///     e.g. `#[autoimpl(std::clone::Clone)]`
186///
187/// ## Parameter syntax
188///
189/// > _ParamsMulti_ :\
190/// > &nbsp;&nbsp; ( _Trait_ ),+ _Using_? _Ignores_? _WhereClause_?
191/// >
192/// > _Using_ :\
193/// > &nbsp;&nbsp; `using` `self` `.` _Member_
194/// >
195/// > _Ignores_ :\
196/// > &nbsp;&nbsp; `ignore` ( `self` `.` _Member_ ),+
197/// >
198/// > _WhereClause_ :\
199/// > &nbsp;&nbsp; `where` ( _WherePredicate_ ),*
200///
201/// **Targets:** each *Trait* listed is implemented for the annotated type.
202///
203///
204/// # On trait definitions
205///
206/// `#[autoimpl]` on trait definitions generates an implementation of that trait
207/// for the given targets. This functions using an implementation of [`Deref`]
208/// (and, where required, [`DerefMut`]) to lower the target type to some other
209/// type supporting the trait. We call this latter type the **definitive type**.
210///
211/// It is required that the target type(s) implemented are generic over some
212/// type parameter(s). These generic parameters are introduced using `for<..>`.
213/// It is further required that at least one generic parameter has a bound on
214/// `trait`; the first such parameter is inferred to be the *definitive type*.
215///
216/// For example, the following usage implements `MyTrait` for targets `&T`,
217/// `&mut T` and `Box<dyn MyTrait>` using definitive type `T`:
218/// ```
219/// # use impl_tools::autoimpl;
220/// #[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
221/// trait MyTrait {
222///     fn f(&self) -> String;
223/// }
224/// ```
225/// The expansion for target `Box<T>` looks like:
226/// ```
227/// # trait MyTrait {
228/// #     fn f(&self) -> String;
229/// # }
230/// #[automatically_derived]
231/// impl<T: MyTrait + ?Sized> MyTrait for Box<T> {
232///     fn f(&self) -> String {
233///         <T as MyTrait>::f(self)
234///     }
235/// }
236/// ```
237///
238/// ## Generics
239///
240/// Traits using generics and trait items using generics are, for the most part,
241/// supported.
242///
243/// Items with a where clause with a type bound on `Self` cannot be implemented
244/// via [`Deref`] since the item is not guaranteed to exist on the definitive
245/// type. Such items with a default implementation may be implemented using this
246/// that default implementation, though this results in a warning by default
247/// (requires feature "nightly-diagnostics").
248/// In other cases an error is reported.
249///
250/// An example:
251/// ```
252/// # use impl_tools::autoimpl;
253/// # use std::fmt::Debug;
254/// #[autoimpl(for<'a, T> &'a T, &'a mut T, Box<T> where T: trait + ?Sized)]
255/// trait G<V>
256/// where
257///     V: Debug,
258/// {
259///     fn g(&self) -> V;
260///
261///     fn s<X>(&self, f: impl Fn(V) -> X) -> X
262///     where
263///         Self: Sized,
264///     {
265///         f(self.g())
266///     }
267/// }
268/// ```
269///
270/// ## Parameter syntax
271///
272/// > _ParamsTrait_ :\
273/// > &nbsp;&nbsp; `for` _Generics_ ( _Type_ ),+ _WhereClause_?
274///
275/// [`Deref`]: std::ops::Deref
276/// [`Deref::Target`]: std::ops::Deref::Target
277/// [`DerefMut`]: std::ops::DerefMut
278#[proc_macro_attribute]
279#[proc_macro_error]
280pub fn autoimpl(attr: TokenStream, item: TokenStream) -> TokenStream {
281    let mut toks = item.clone();
282    match syn::parse::<autoimpl::Attr>(attr) {
283        Ok(autoimpl::Attr::ForDeref(ai)) => toks.extend(TokenStream::from(ai.expand(item.into()))),
284        Ok(autoimpl::Attr::ImplTraits(ai)) => {
285            // We could use lazy_static to construct a HashMap for fast lookups,
286            // but given the small number of impls a "linear map" is fine.
287            let find_impl = |path: &syn::Path| {
288                autoimpl::STD_IMPLS
289                    .iter()
290                    .cloned()
291                    .find(|impl_| impl_.path().matches_ident_or_path(path))
292            };
293            toks.extend(TokenStream::from(ai.expand(item.into(), find_impl)))
294        }
295        Err(err) => {
296            emit_call_site_error!(err);
297            // Since autoimpl only adds implementations, we can safely output
298            // the original item, thus reducing secondary errors.
299        }
300    }
301    toks
302}
303
304/// Implement a type with `impl Self` syntax
305///
306/// This macro facilitates definition of a type (struct, enum or union) plus
307/// implementations via `impl Self { .. }` syntax: `Self` is expanded to the
308/// type's name, including generics and bounds (as defined on the type).
309///
310/// Caveat: `rustfmt` can not yet format contents (see
311/// [rustfmt#5254](https://github.com/rust-lang/rustfmt/issues/5254),
312/// [rustfmt#5538](https://github.com/rust-lang/rustfmt/pull/5538)).
313///
314/// Note: this macro is largely redundant with the [`macro@impl_self`] macro,
315/// the one exception being [`macro@impl_default`] support. This macro will be
316/// deprecated simultaneously with [`macro@impl_default`].
317///
318/// ## Special attribute macros
319///
320/// Additionally, `impl_scope!` supports special attribute macros evaluated
321/// within its scope:
322///
323/// -   [`#[impl_default]`](macro@impl_default): implement [`Default`] using
324///     field initializers (which are not legal syntax outside of `impl_scope!`)
325///
326/// Note: matching these macros within `impl_scope!` does not use path
327/// resolution. Using `#[impl_tools::impl_default]` would resolve the variant
328/// of this macro which *doesn't support* field initializers.
329///
330/// ## Syntax
331///
332/// > _ImplScope_ :\
333/// > &nbsp;&nbsp; `impl_scope!` `{` _ScopeItem_ _ItemImpl_ * `}`
334/// >
335/// > _ScopeItem_ :\
336/// > &nbsp;&nbsp; _ItemEnum_ | _ItemStruct_ | _ItemType_ | _ItemUnion_
337///
338/// That is, one type definition followed by a set of implementations.
339/// Impls must take one of two forms:
340///
341/// -   `impl Self { ... }` — generic parameters and bounds of the type are used
342/// -   `impl MyType { ... }` where `MyType` matches the name of the defined type
343///
344/// Generic parameters from the type are included implicitly with the first form.
345/// Additional generic parameters and where clauses are supported (parameters
346/// and bounds are merged).
347///
348/// ## Example
349///
350/// ```
351/// impl_tools::impl_scope! {
352///     struct Pair<T>(T, T);
353///
354///     impl Self {
355///         pub fn new(a: T, b: T) -> Self {
356///             Pair(a, b)
357///         }
358///     }
359///
360///     impl Self where T: Clone {
361///         pub fn splat(a: T) -> Self {
362///             let b = a.clone();
363///             Pair(a, b)
364///         }
365///     }
366/// }
367/// ```
368#[proc_macro_error]
369#[proc_macro]
370pub fn impl_scope(input: TokenStream) -> TokenStream {
371    let mut scope = parse_macro_input!(input as scope::Scope);
372    scope.apply_attrs(scope::find_impl_default);
373    scope.expand().into()
374}
375
376/// Construct an anonymous struct
377///
378/// Rust doesn't currently support [`impl Trait { ... }` expressions](https://github.com/canndrew/rfcs/blob/impl-trait-expressions/text/0000-impl-trait-expressions.md)
379/// or implicit typing of struct fields. This macro is a **hack** allowing that.
380///
381/// Example:
382/// ```
383/// use std::fmt;
384/// fn main() {
385///     let world = "world";
386///     let says_hello_world = impl_tools::impl_anon! {
387///         struct(&'static str = world);
388///         impl fmt::Display for Self {
389///             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
390///                 write!(f, "hello {}", self.0)
391///             }
392///         }
393///     };
394///     assert_eq!(format!("{}", says_hello_world), "hello world");
395/// }
396/// ```
397///
398/// That is, this macro creates an anonymous struct type (must be a struct),
399/// which may have trait implementations, then creates an instance of that
400/// struct.
401///
402/// Struct fields may have a fixed type or may be generic. Syntax is as follows:
403///
404/// -   **regular struct:** `ident: ty = value`
405/// -   **regular struct:** `ident: ty` (uses `Default` to construct value)
406/// -   **regular struct:** `ident = value` (type is generic without bounds)
407/// -   **tuple struct:** `ty = value`
408/// -   **tuple struct:** `ty` (uses `Default` to construct value)
409///
410/// The field name, `ident`, may be `_` (anonymous field).
411///
412/// The field type, `ty`, may be or may contain inferred types (`_`) and/or
413/// `impl Trait` type expressions. These are substituted with generics on the
414/// type.
415///
416/// Refer to [examples](https://github.com/search?q=impl_anon+repo%3Akas-gui%2Fkas+path%3Aexamples&type=Code) for usage.
417#[proc_macro_error]
418#[proc_macro]
419pub fn impl_anon(input: TokenStream) -> TokenStream {
420    let mut scope = parse_macro_input!(input as anon::Anon).into_scope();
421    scope.apply_attrs(scope::find_impl_default);
422    scope.expand().into()
423}
424
425/// Implement a type with `impl Self` syntax
426///
427/// This attribute macro supports a type (struct, enum, type alias or union)
428/// definition plus associated `impl` items within a `mod`.
429///
430/// Macro expansion discards the `mod` entirely, placing all contents into the
431/// outer scope. This simplifies privacy rules in many use-cases, and highlights
432/// that the usage of `mod` is purely a hack to make the macro input valid Rust
433/// syntax (and thus compatible with `rustfmt`).
434///
435/// ## Syntax
436///
437/// > _ImplSelf_ :\
438/// > &nbsp;&nbsp; `#[impl_self]` `mod` _Name_ `{` _ScopeItem_ _ItemImpl_ * `}`
439/// >
440/// > _ScopeItem_ :\
441/// > &nbsp;&nbsp; _ItemEnum_ | _ItemStruct_ | _ItemType_ | _ItemUnion_
442///
443/// Here, _ItemEnum_, _ItemStruct_, _ItemType_ and _ItemUnion_ are `enum`,
444/// `struct`, `type` alias and `union` definitions respectively. Whichever of
445/// these is used, it must match the module name _Name_.
446///
447/// _ItemImpl_ is an `impl` item. It may use the standard implementation syntax
448/// (e.g. `impl Debug for MyType { .. }`) or `impl Self` syntax (see below).
449///
450/// The `mod` may not contain any other items, except `doc` items (documentation
451/// on the module itself is ignored in favour of documentation on the defined
452/// type) and attributes (which apply as usual).
453///
454/// ### `impl Self` syntax
455///
456/// `impl Self` "syntax" is syntactically-valid (but not semantically-valid)
457/// Rust syntax for writing inherent and trait `impl` blocks:
458///
459/// -   `impl Self { ... }` — an inherent `impl` item on the defined type
460/// -   `impl Debug for Self { ... }` — a trait `impl` item on the defined type
461///
462/// Generic parameters and bounds are copied from the type definition.
463/// Additional generic parameters may be specified; these extend the list of
464/// generic parameters on the type itself, and thus must have distinct names.
465/// Additional bounds (where clauses) may be specified; these extend the list of
466/// bounds on the type itself.
467///
468/// ## Example
469///
470/// ```
471/// #[impl_tools::impl_self]
472/// mod Pair {
473///     /// A pair of values of type `T`
474///     pub struct Pair<T>(T, T);
475///
476///     impl Self {
477///         pub fn new(a: T, b: T) -> Self {
478///             Pair(a, b)
479///         }
480///     }
481///
482///     impl Self where T: Clone {
483///         pub fn splat(a: T) -> Self {
484///             let b = a.clone();
485///             Pair(a, b)
486///         }
487///     }
488/// }
489/// ```
490#[proc_macro_attribute]
491#[proc_macro_error]
492pub fn impl_self(attr: TokenStream, input: TokenStream) -> TokenStream {
493    let _ = parse_macro_input!(attr as scope::ScopeModAttrs);
494    let scope = parse_macro_input!(input as scope::ScopeMod);
495    scope.contents.expand().into()
496}