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_error3::{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/// > ( _Trait_ ),+ _Using_? _Ignores_? _WhereClause_?
191/// >
192/// > _Using_ :\
193/// > `using` `self` `.` _Member_
194/// >
195/// > _Ignores_ :\
196/// > `ignore` ( `self` `.` _Member_ ),+
197/// >
198/// > _WhereClause_ :\
199/// > `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 over that targets' own implementations of the trait.
208/// Targets may or may not be generic.
209///
210/// Method implementations either defer to a field (if `using self._Member_` is
211/// specified; e.g. `using self.0` or `using self.inner`) or use [`Deref`] (and,
212/// where required, [`DerefMut`]).
213///
214/// For example,
215/// ```
216/// # use impl_tools::autoimpl;
217/// struct MyVec {
218/// vec: Vec<()>,
219/// }
220///
221/// #[autoimpl(for MyVec using self.vec)]
222/// trait IsEmpty {
223/// fn is_empty(&self) -> bool;
224/// }
225///
226/// impl<T> IsEmpty for Vec<T> {
227/// fn is_empty(&self) -> bool {
228/// Vec::is_empty(self)
229/// }
230/// }
231/// ```
232///
233/// Associated `const` and `type` items are only supported where the targets are
234/// generic over some parameter with a bound like `T: trait`. We call this the
235/// **definitive type**.
236///
237/// For example, the following usage implements `MyTrait` for targets `&T`,
238/// `&mut T` and `Box<dyn MyTrait>` using definitive type `T`:
239/// ```
240/// # use impl_tools::autoimpl;
241/// #[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
242/// trait MyTrait {
243/// type X;
244///
245/// fn f(&self) -> Self::X;
246/// }
247/// ```
248/// The expansion for target `Box<T>` looks like:
249/// ```
250/// # trait MyTrait {
251/// # type X;
252/// # fn f(&self) -> Self::X;
253/// # }
254/// #[automatically_derived]
255/// impl<T: MyTrait + ?Sized> MyTrait for Box<T> {
256/// type X = <T as MyTrait>::X;
257///
258/// fn f(&self) -> Self::X {
259/// <T as MyTrait>::f(self)
260/// }
261/// }
262/// ```
263///
264/// ## Generics
265///
266/// Traits using generics and trait items using generics are, for the most part,
267/// supported.
268///
269/// Items with a where clause with a type bound on `Self` cannot be implemented
270/// via [`Deref`] since the item is not guaranteed to exist on the definitive
271/// type. Such items with a default implementation may be implemented using this
272/// that default implementation, though this results in a warning by default
273/// (requires feature "nightly-diagnostics").
274/// In other cases an error is reported.
275///
276/// An example:
277/// ```
278/// # use impl_tools::autoimpl;
279/// # use std::fmt::Debug;
280/// #[autoimpl(for<'a, T> &'a T, &'a mut T, Box<T> where T: trait + ?Sized)]
281/// trait G<V>
282/// where
283/// V: Debug,
284/// {
285/// fn g(&self) -> V;
286///
287/// fn s<X>(&self, f: impl Fn(V) -> X) -> X
288/// where
289/// Self: Sized,
290/// {
291/// f(self.g())
292/// }
293/// }
294/// ```
295///
296/// ## Parameter syntax
297///
298/// > _ParamsTrait_ :\
299/// > `for` _Generics_ ( _Type_ ),+ _WhereClause_?
300///
301/// [`Deref`]: std::ops::Deref
302/// [`Deref::Target`]: std::ops::Deref::Target
303/// [`DerefMut`]: std::ops::DerefMut
304#[proc_macro_attribute]
305#[proc_macro_error]
306pub fn autoimpl(attr: TokenStream, item: TokenStream) -> TokenStream {
307 let mut toks = item.clone();
308 match syn::parse::<autoimpl::Attr>(attr) {
309 Ok(autoimpl::Attr::ForDeref(ai)) => toks.extend(TokenStream::from(ai.expand(item.into()))),
310 Ok(autoimpl::Attr::ImplTraits(ai)) => {
311 // We could use lazy_static to construct a HashMap for fast lookups,
312 // but given the small number of impls a "linear map" is fine.
313 let find_impl = |path: &syn::Path| {
314 autoimpl::STD_IMPLS
315 .iter()
316 .cloned()
317 .find(|impl_| impl_.path().matches_ident_or_path(path))
318 };
319 toks.extend(TokenStream::from(ai.expand(item.into(), find_impl)))
320 }
321 Err(err) => {
322 emit_call_site_error!(err);
323 // Since autoimpl only adds implementations, we can safely output
324 // the original item, thus reducing secondary errors.
325 }
326 }
327 toks
328}
329
330/// Support simultaneous definition of a trait and its implementation
331///
332/// Sometimes a trait is used only (or primarily) to provide an interface over a
333/// single object. In such cases, writing out the method prototypes twice (in
334/// both the trait and its implementation) should be unnecessary.
335///
336/// This attribute splits an implementation for a specified target off from a
337/// trait definition.
338///
339/// # Details
340///
341/// This attribute must be applied to a trait definition. This trait definition
342/// is retained with only modifications being that method *implementations* and
343/// `#[inline]` attributes are removed. An implied limitation of this attribute
344/// is that methods of the trait cannot have default implementations.
345///
346/// Meanwhile, an implementation of the trait is generated for the given target.
347/// This implementation uses all method implementations from the trait.
348///
349/// Generics may be introduced for the implementation only using syntax like
350/// `#[split_impl(for<'a, T> Target<'a, T> where T: Trait)]`.
351/// Implementation generics are combined with trait generics.
352///
353/// Specific attributes of the trait are copied to the implementation: `cfg`,
354/// `allow`, `warn`, `deny`, `forbid`. All trait method attributes except `doc`
355/// are copied to the implementation.
356///
357/// # Example
358///
359/// ```
360/// # use impl_tools::split_impl;
361/// #[split_impl(for str)]
362/// trait Greet {
363/// /// Introduce yourself
364/// fn greet(&self) {
365/// println!("Hello world, I am {self}!");
366/// }
367/// }
368///
369/// fn main() {
370/// "Ferris".greet();
371/// }
372/// ```
373#[proc_macro_attribute]
374#[proc_macro_error]
375pub fn split_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
376 match syn::parse::<lib::SplitImpl>(attr) {
377 Ok(attr) => match syn::parse::<syn::ItemTrait>(item) {
378 Ok(trait_) => attr.process(trait_).into(),
379 Err(err) => err.to_compile_error().into(),
380 },
381 Err(err) => {
382 emit_call_site_error!(err);
383 item
384 }
385 }
386}
387
388/// Implement a type with `impl Self` syntax
389///
390/// This macro facilitates definition of a type (struct, enum or union) plus
391/// implementations via `impl Self { .. }` syntax: `Self` is expanded to the
392/// type's name, including generics and bounds (as defined on the type).
393///
394/// Caveat: `rustfmt` can not yet format contents (see
395/// [rustfmt#5254](https://github.com/rust-lang/rustfmt/issues/5254),
396/// [rustfmt#5538](https://github.com/rust-lang/rustfmt/pull/5538)).
397///
398/// Note: this macro is largely redundant with the [`macro@impl_self`] macro,
399/// the one exception being [`macro@impl_default`] support. This macro will be
400/// deprecated simultaneously with [`macro@impl_default`].
401///
402/// ## Special attribute macros
403///
404/// Additionally, `impl_scope!` supports special attribute macros evaluated
405/// within its scope:
406///
407/// - [`#[impl_default]`](macro@impl_default): implement [`Default`] using
408/// field initializers (which are not legal syntax outside of `impl_scope!`)
409///
410/// Note: matching these macros within `impl_scope!` does not use path
411/// resolution. Using `#[impl_tools::impl_default]` would resolve the variant
412/// of this macro which *doesn't support* field initializers.
413///
414/// ## Syntax
415///
416/// > _ImplScope_ :\
417/// > `impl_scope!` `{` _ScopeItem_ _ItemImpl_ * `}`
418/// >
419/// > _ScopeItem_ :\
420/// > _ItemEnum_ | _ItemStruct_ | _ItemType_ | _ItemUnion_
421///
422/// That is, one type definition followed by a set of implementations.
423/// Impls must take one of two forms:
424///
425/// - `impl Self { ... }` — generic parameters and bounds of the type are used
426/// - `impl MyType { ... }` where `MyType` matches the name of the defined type
427///
428/// Generic parameters from the type are included implicitly with the first form.
429/// Additional generic parameters and where clauses are supported (parameters
430/// and bounds are merged).
431///
432/// ## Example
433///
434/// ```
435/// impl_tools::impl_scope! {
436/// struct Pair<T>(T, T);
437///
438/// impl Self {
439/// pub fn new(a: T, b: T) -> Self {
440/// Pair(a, b)
441/// }
442/// }
443///
444/// impl Self where T: Clone {
445/// pub fn splat(a: T) -> Self {
446/// let b = a.clone();
447/// Pair(a, b)
448/// }
449/// }
450/// }
451/// ```
452#[proc_macro_error]
453#[proc_macro]
454pub fn impl_scope(input: TokenStream) -> TokenStream {
455 let mut scope = parse_macro_input!(input as scope::Scope);
456 scope.apply_attrs(scope::find_impl_default);
457 scope.expand().into()
458}
459
460/// Construct an anonymous struct
461///
462/// Rust doesn't currently support [`impl Trait { ... }` expressions](https://github.com/canndrew/rfcs/blob/impl-trait-expressions/text/0000-impl-trait-expressions.md)
463/// or implicit typing of struct fields. This macro is a **hack** allowing that.
464///
465/// Example:
466/// ```
467/// use std::fmt;
468/// fn main() {
469/// let world = "world";
470/// let says_hello_world = impl_tools::impl_anon! {
471/// struct(&'static str = world);
472/// impl fmt::Display for Self {
473/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
474/// write!(f, "hello {}", self.0)
475/// }
476/// }
477/// };
478/// assert_eq!(format!("{}", says_hello_world), "hello world");
479/// }
480/// ```
481///
482/// That is, this macro creates an anonymous struct type (must be a struct),
483/// which may have trait implementations, then creates an instance of that
484/// struct.
485///
486/// Struct fields may have a fixed type or may be generic. Syntax is as follows:
487///
488/// - **regular struct:** `ident: ty = value`
489/// - **regular struct:** `ident: ty` (uses `Default` to construct value)
490/// - **regular struct:** `ident = value` (type is generic without bounds)
491/// - **tuple struct:** `ty = value`
492/// - **tuple struct:** `ty` (uses `Default` to construct value)
493///
494/// The field name, `ident`, may be `_` (anonymous field).
495///
496/// The field type, `ty`, may be or may contain inferred types (`_`) and/or
497/// `impl Trait` type expressions. These are substituted with generics on the
498/// type.
499///
500/// Refer to [examples](https://github.com/search?q=impl_anon+repo%3Akas-gui%2Fkas+path%3Aexamples&type=Code) for usage.
501#[proc_macro_error]
502#[proc_macro]
503pub fn impl_anon(input: TokenStream) -> TokenStream {
504 let mut scope = parse_macro_input!(input as anon::Anon).into_scope();
505 scope.apply_attrs(scope::find_impl_default);
506 scope.expand().into()
507}
508
509/// Implement a type with `impl Self` syntax
510///
511/// This attribute macro supports a type (struct, enum, type alias or union)
512/// definition plus associated `impl` items within a `mod`.
513///
514/// Macro expansion discards the `mod` entirely, placing all contents into the
515/// outer scope. This simplifies privacy rules in many use-cases, and highlights
516/// that the usage of `mod` is purely a hack to make the macro input valid Rust
517/// syntax (and thus compatible with `rustfmt`).
518///
519/// ## Syntax
520///
521/// > _ImplSelf_ :\
522/// > `#[impl_self]` `mod` _Name_ `{` _ScopeItem_ _ItemImpl_ * `}`
523/// >
524/// > _ScopeItem_ :\
525/// > _ItemEnum_ | _ItemStruct_ | _ItemType_ | _ItemUnion_
526///
527/// Here, _ItemEnum_, _ItemStruct_, _ItemType_ and _ItemUnion_ are `enum`,
528/// `struct`, `type` alias and `union` definitions respectively. Whichever of
529/// these is used, it must match the module name _Name_.
530///
531/// _ItemImpl_ is an `impl` item. It may use the standard implementation syntax
532/// (e.g. `impl Debug for MyType { .. }`) or `impl Self` syntax (see below).
533///
534/// The `mod` may not contain any other items, except `doc` items (documentation
535/// on the module itself is ignored in favour of documentation on the defined
536/// type) and attributes (which apply as usual).
537///
538/// ### `impl Self` syntax
539///
540/// `impl Self` "syntax" is syntactically-valid (but not semantically-valid)
541/// Rust syntax for writing inherent and trait `impl` blocks:
542///
543/// - `impl Self { ... }` — an inherent `impl` item on the defined type
544/// - `impl Debug for Self { ... }` — a trait `impl` item on the defined type
545///
546/// Generic parameters and bounds are copied from the type definition.
547/// Additional generic parameters may be specified; these extend the list of
548/// generic parameters on the type itself, and thus must have distinct names.
549/// Additional bounds (where clauses) may be specified; these extend the list of
550/// bounds on the type itself.
551///
552/// ## Example
553///
554/// ```
555/// #[impl_tools::impl_self]
556/// mod Pair {
557/// /// A pair of values of type `T`
558/// pub struct Pair<T>(T, T);
559///
560/// impl Self {
561/// pub fn new(a: T, b: T) -> Self {
562/// Pair(a, b)
563/// }
564/// }
565///
566/// impl Self where T: Clone {
567/// pub fn splat(a: T) -> Self {
568/// let b = a.clone();
569/// Pair(a, b)
570/// }
571/// }
572/// }
573/// ```
574#[proc_macro_attribute]
575#[proc_macro_error]
576pub fn impl_self(attr: TokenStream, input: TokenStream) -> TokenStream {
577 let _ = parse_macro_input!(attr as scope::ScopeModAttrs);
578 let scope = parse_macro_input!(input as scope::ScopeMod);
579 scope.contents.expand().into()
580}