forward_traits/lib.rs
1/*!
2
3This crate provides general mechanisms for implementing traits on types by
4forwarding an implementation provided by another type.
5
6Two different forwarding methods are provided: Forwarding traits implemented by
7members, and forwarding traits implemented by types that the receiver type can
8convert to. These methods may be used in combination on the same receiver type.
9This crate fully supports generic traits and struct types.
10
11For more details about capabilities and limitations, see the documentation pages
12for the individual macros.
13
14# Basics
15
16In order to forward a trait, some basic things are needed.
17
18```rust
19use forward_traits::{forwardable, forward_receiver, forward_traits};
20```
21
22We need a trait definition which is annotated with information which is used to
23generate forwarded implementations. This is done by applying the
24`#[forwardable]` attribute to the definition.
25
26```rust
27# use forward_traits::forwardable;
28#[forwardable]
29trait FooTrait
30{
31 type Bar;
32
33 fn foo (&self) -> &Self::Bar;
34
35 const BAZ: u32;
36}
37```
38
39Then we need a type which initially implements this trait.
40
41```rust
42# trait FooTrait { type Bar; fn foo (&self) -> &Self::Bar; const BAZ: u32; }
43struct A {}
44
45impl FooTrait for A
46{
47 type Bar = Self;
48
49 fn foo (&self) -> &Self::Bar { self }
50
51 const BAZ: u32 = 42;
52}
53```
54
55Next, we need a type for which we want to implement this trait by forwarding the
56implementation found on the initially implementing type. There are a few
57different ways to define such a type, but here we will demonstrate the newtype
58idiom. This type needs to be annotated with the `#[forward_receiver]`
59attribute.
60
61```rust
62# use forward_traits::forward_receiver;
63# struct A {}
64#[forward_receiver]
65struct B (A);
66```
67
68Lastly, we need to specify that we want to forward a trait. In this case, we
69want to forward a trait implemented by a member, so we write:
70
71```rust
72# use forward_traits::{forwardable, forward_receiver, forward_traits};
73# #[forwardable]
74# trait FooTrait { type Bar; fn foo (&self) -> &Self::Bar; const BAZ: u32; }
75# struct A {}
76# impl FooTrait for A { type Bar = Self; fn foo (&self) -> &Self::Bar { self } const BAZ: u32 = 42; }
77# #[forward_receiver]
78# struct B (A);
79forward_traits! (for B . 0 impl FooTrait);
80```
81
82And now we can see that the trait is properly forwarded.
83
84```rust
85# use forward_traits::{forwardable, forward_receiver, forward_traits};
86# #[forwardable]
87# trait FooTrait { type Bar; fn foo (&self) -> &Self::Bar; const BAZ: u32; }
88# struct A {}
89# impl FooTrait for A { type Bar = Self; fn foo (&self) -> &Self::Bar { self } const BAZ: u32 = 42; }
90# #[forward_receiver]
91# struct B (A);
92# forward_traits! (for B . 0 impl FooTrait);
93assert_eq! (<B as FooTrait>::BAZ, 42);
94```
95
96# Re-Exporting Forwardable Traits
97
98When re-exporting forwardable traits, the `#[forwardable]` attribute should be
99applied to the use statement as well. Note that the attribute will interpret
100every item in the use tree as a trait that should be forwardable. If you want
101to re-export items that aren't forwardable traits from the same module(s),
102you'll need to separate those re-exports out into another use statement;
103
104```rust
105use forward_traits::forwardable;
106
107mod inner
108{
109 use forward_traits::forwardable;
110
111 #[forwardable]
112 pub trait Foo {}
113
114 pub struct Bar {}
115}
116
117#[forwardable]
118pub use inner::Foo;
119
120pub use inner::Bar;
121```
122
123# Traits in Other Crates
124
125Forwarding traits works with traits in other crates, so long as those trait
126definitions are annotated with `#[forwardable]`.
127
128If not, then annotations must be supplied separately. When supplying
129annotations in this way, the trait is imported (or re-exported if a visibility
130modifier is supplied) at the location of the annotation macro. When forwarding
131this trait, you must refer to this import/re-export (or a re-export thereof).
132
133```rust
134use forward_traits
135::{
136 supply_forwarding_info_for_trait,
137 forward_receiver,
138 forward_traits
139};
140
141// This has the side-effect of importing IntoIterator into the current scope.
142supply_forwarding_info_for_trait!
143(
144 std::iter::IntoIterator,
145 trait
146 {
147 type Item;
148 type IntoIter;
149 fn into_iter (self) -> Self::IntoIter;
150 }
151);
152
153#[forward_receiver]
154struct VecWrapper <T> (Vec <T>);
155
156// Note that we are referring to the IntoIterator in the current scope.
157forward_traits! (for VecWrapper . 0 impl IntoIterator);
158
159// Now we can call the trait method on the wrapper type.
160VecWrapper (vec! (1, 2, 3)) . into_iter ();
161```
162
163*/
164
165mod uncurry;
166
167mod generics;
168mod syn;
169mod fold;
170
171mod value_transformer;
172mod type_transformer;
173mod transformer;
174
175mod macros;
176
177use proc_macro::TokenStream;
178
179/**
180
181This attribute primarily annotates trait definitions with forwarding
182information. Secondarily, it is also used to make sure that the forwarding info
183is properly re-exported along with the traits that it belongs to.
184
185# Mechanism
186
187The way that this attribute works is by defining a macro which can be used to
188uncurry the trait forwarding information into another macro.
189
190Due to limitations of macro export rules, a mangled version of that macro's name
191is also created and exported into the crate root. While these names are mangled
192so that they're unlikely to cause name collisions, annotating trait definitions
193of the same name in two different modules of the same crate will _definitely_
194cause a problem. Please keep trait names within a single crate unique.
195
196# Annotating Trait Definitions
197
198Use on trait definitions is pretty simple. Just apply the attribute.
199
200```rust
201# use forward_traits::forwardable;
202#[forwardable]
203trait Foo
204{
205 // ...
206}
207```
208
209The only consideration is that any types used for method arguments or associated
210constants should be named by their fully-qualified paths. This will prevent
211name-resolution errors from occurring in the macro-generated implementations.
212
213# Annotating Re-Exports
214
215When re-exporting a trait that has been annotated, the use statement that does
216the re-export should also be annotated.
217
218```rust
219# use forward_traits::forwardable;
220mod foo
221{
222 # use forward_traits::forwardable;
223 #[forwardable]
224 pub trait Foo
225 {
226 // ...
227 }
228}
229
230#[forwardable]
231pub use foo::Foo;
232```
233
234The forwarding information is located by modifying the path of the trait passed
235into the forwarding macro. If the forwarding information isn't re-exported
236alongside the trait, it won't be properly located if a path to the un-annotated
237re-export is used in the forwarding macro.
238
239*/
240#[proc_macro_attribute]
241pub fn forwardable (attr: TokenStream, item: TokenStream) -> TokenStream
242{
243 macros::forwardable::forwardable_impl (attr, item)
244}
245
246/**
247
248This attribute annotates type definitions with forwarding information.
249
250# Mechanism
251
252The way that this attribute works is by defining a macro which can be used to
253uncurry the type information into another macro.
254
255Due to limitations of macro export rules, a mangled version of that macro's name
256is also created and exported into the crate root. While these names are mangled
257so that they're unlikely to cause name collisions, annotating type definitions
258of the same name in two different modules of the same crate will _definitely_
259cause a problem. Please keep type names within a single crate unique.
260
261# Usage
262
263Usage of this attribute is pretty simple. Just apply it to type definitions.
264
265```rust
266# use forward_traits::forward_receiver;
267#[forward_receiver]
268struct Foo
269{
270 // ...
271}
272```
273
274Both regular structs and tuple-structs are supported.
275
276# Limitations
277
278The only types that are supported are structs. Forwarding methods for enums can
279be done in some circumstances easily enough, but figuring out what type to use
280as the base for the associated types and constants is not as straightforward.
281Solving those sorts of problems is beyond the scope of this crate.
282
283```rust,compile_fail
284# use forward_traits::forward_receiver;
285// Error: expected `struct`
286#[forward_receiver]
287enum Foo
288{
289 // ...
290}
291```
292
293*/
294#[proc_macro_attribute]
295pub fn forward_receiver (attr: TokenStream, item: TokenStream) -> TokenStream
296{
297 macros::forward_receiver::forward_receiver_impl (attr, item)
298}
299
300/**
301
302This macro allows the user to supply forwarding information for a trait in an
303external crate that they do not control.
304
305# Usage
306
307The macro takes two arguments. The first is a path to the trait that we're
308providing annotations for. The second is the annotation information.
309
310The annotation information is basically just a subset of the parts that make up
311a full trait definition.
312
313 * `pub` or `pub (restriction)` - (optional) A visibility specification. This
314 isn't strictly a part of the trait's info, but will determine the visibility
315 of the generated macro and trait re-export that is generated as a side-effect
316 of this macro.
317
318 * `trait` - just the keyword `trait`.
319
320 * `<'a, T, const N: usize, ...>` - (optional) generic parameters, as would be
321 found after the type identifier in a normal trait definition. Any default
322 values will be ignored, and should not be provided.
323
324 * `where T: 'a, ...` - (optional) a where clause, as would be found in the
325 trait definition.
326
327 * `{type Error; fn try_from (x: T) -> Result <Self, Self::Error>; ...}` - A
328 block containing the definitions of the trait items. Again, any default
329 values (or implementations) will be ignored, and should not be provided.
330
331All types included should be named by their fully-qualified paths whenever
332applicable.
333
334# Mechanism
335
336The way that this attribute works is by defining a macro which can be used to
337uncurry the trait forwarding information into another macro.
338
339Due to limitations of macro export rules, a mangled version of that macro's name
340is also created and exported into the crate root. While these names are mangled
341so that they're unlikely to cause name collisions, annotating trait definitions
342of the same name in two different modules of the same crate will _definitely_
343cause a problem. Please keep trait names within a single crate unique.
344
345# Example
346
347```rust
348# use forward_traits::{supply_forwarding_info_for_trait, forward_receiver, forward_traits};
349supply_forwarding_info_for_trait!
350(
351 std::iter::FromIterator,
352 pub (crate) trait <A>
353 {
354 fn from_iter <T> (iter: T) -> Self
355 where T: IntoIterator <Item = A>;
356 }
357);
358# #[forward_receiver]
359# struct VecWrapper <T> (Vec <T>);
360# impl <T> From <Vec <T>> for VecWrapper <T> { fn from (vec: Vec <T>) -> Self { Self (vec) } }
361# forward_traits! (for VecWrapper -> Vec <T> impl FromIterator <T>);
362```
363
364*/
365#[proc_macro]
366pub fn supply_forwarding_info_for_trait (input: TokenStream) -> TokenStream
367{
368 macros::supply_trait_info::supply_forwarding_info_for_trait_impl (input)
369}
370
371#[doc (hidden)]
372#[proc_macro]
373pub fn __forward_trait (input: TokenStream) -> TokenStream
374{
375 macros::forward_traits::__forward_trait_impl (input)
376}
377
378/**
379
380The namesake of the crate, this macro generates trait implementations by
381delegating the trait items to another type.
382
383# Usage
384
385The syntax for the argument to this macro is a little complicated.
386
387## Base Type Transformation
388
389The first part of the syntax is a specification of the base type and how to
390transform it into the delegated type. There are two such transformations
391available.
392
393 * Conversion: `Ident -> Type`. The type named by the ident (it is expected to
394 be in the same scope as the macro invocation) is transformed into the
395 delegated type via conversion traits. For arguments, the following types are
396 converted using the specified traits.
397
398 * `Self`: `std::convert::Into <DelegatedType>`
399 * `&Self`: `std::convert::AsRef <DelegatedType>`
400 * `&mut Self`: `std::convert::AsMut <DelegatedType>`
401
402 Besides these specific types, `Box`, `Option`, `Result`, tuple types, and
403 array types are also transformed if their contents are a transformable type.
404 All arguments of a convertible type are converted, not just the receiver.
405
406 The return value may be converted as well, if it is a form of `Self` type.
407 This uses the following trait.
408
409 * `-> Self`: `std::convert::From <DelegatedType>`
410
411 Like with arguments, `Result` and `Box` forms are also transformed.
412
413 The conversion traits that are actually used need to be implemented for the
414 base type. Any conversion traits that are not used are not required.
415
416 * Member access: `Ident . Ident|Index`. The first ident is the same as with
417 conversion. The `Ident|Index` names a member of the struct to delegate to.
418 An ident is required in the case of a struct with named fields, and an index
419 is required in the case of a tuple struct.
420
421 `Self`, `&Self`, and `&mut Self` typed arguments are tranformed via member
422 access. Like with conversion, `Box`, `Option`, `Result`, tuple types, and
423 array types are also transformed if they contain some form of `Self`. Member
424 delegation cannot transform return values.
425
426## Additional Transformations
427
428After the base type transformation, we might want to list some other type
429transformations to be applied. The set of conversions available is the same as
430for the base type transformation. These specifications have a slightly
431different syntax, as they do not rely on type annotations like the base type
432transformation does.
433
434 * Conversion: `Type -> Type`. Instead of an ident in the first position, we
435 have a full type. The behavior is otherwise the same.
436
437 * Member access: `Type . Ident|Index : Type`. Not only do we have a type in
438 the first position instead of an ident, but the type of the member must also
439 be provided.
440
441These transformations do not assume that the type on the left is in the same
442scope as the macro invocation. The transformations applied, and the rules that
443must be followed for the types on the left side of these transformation
444specifications are otherwise the same as for the base type transformation.
445
446Note that the base type transformation only transforms forms of type `Self`. If
447the base type is explicitly written out rather than being referred to with the
448`Self` type, then it won't be transformed by the base type transformation.
449
450The base type _can_ be used on the left-hand side of an additional
451transformation to specify that explicit forms of the base type should be
452transformed as well.
453
454### Associated Type Transformations
455
456If the type on the LHS of an additional transformation is an associated type (of
457the form `Self::TypeName`), then some additional things will happen.
458
459Associated types in forwarded trait implementations will be assigned to the type
460on the RHS of the additional transformation, rather than to the associated type
461provided by the delegated trait implementation. Values of that associated type
462will be transformed, like with other transformations.
463
464If the associated type takes any lifetime parameters, then the LHS of the
465additional transformation should be prefixed with quanfitied lifetimes (`for
466<Lifetime, ...>`). The overall syntax for an associated type on the LHS of an
467additional transformation looks like `for <Lifetime, ...> Self::TypeName
468<Lifetime, ...>`.
469
470Due to language limitations, it is generally not possible to transform
471associated types that take type or const parameters.
472
473## Forwarded Traits
474
475Lastly, we have the actual traits to forward.
476
477In the simplest form, this is just the path to the trait, plus a set of generic
478arguments (which will be interpreted as if the base type generics are in scope).
479
480However, additional generic paramters may be required in order to provide the
481trait with all of its generic arguments. These may be supplied by prefixing the
482path to the trait with a `for <GenericParam, ...>` construction. Keep in mind
483that any generic parameters provided as part of the transformation specification
484will also be in scope.
485
486Normally, the where clause is constructed by combining the where clause of on
487the type definition, the where clause provided with the transformation
488specifications, and the where clause on the trait definition, and then finally
489adding some additional traits necessary for the forwarding. Some of the generic
490parameters or arguments may end up requiring some additional where predicates
491beyond the computed set, however. These additional predicates may be provided
492by appending a where clause to the forwarded trait specification. If a where
493clause is appended, it must also be followed by a semi-colon (`;`).
494
495If all of these syntactic elements are required in the same specification, you
496can end up with something looking like this:
497
498```rust,ignore
499for <GenericParam, ...> path::to::Trait <GenericArgument, ...> where WherePredicate, ...;
500```
501
502## Putting It All Together
503
504There are some additional bits of glue that are required in-between the parts.
505
506Before the base type transformation specification goes the `for` keyword. If
507there are any generic parameters which should be introduced for all trait
508implementations beyond those introduced by the receiver type definition, they
509may be listed in angle brackets in-between the `for` keyword and the base type
510transformation specification.
511
512Additional transformations are listed, comma-separated, inside of square brackets
513(`[]`). This angle-bracketed list comes immediately after the base type
514transformation. The angle-bracketed list may be omitted in its entirety if no
515additional transformations are to be specified.
516
517If any additional where predicates should be introduced for all trait
518implementations beyond those introduced by the receiver type definition, a where
519clause may be provided after the additional transformations.
520
521The `impl` keyword comes next, marking the beginning of the list of forwarded
522traits.
523
524Finally, the forwarded traits are listed, separated by plus tokens (`+`).
525
526The overall structure, including all optional parts, looks like this.
527
528```rust,ignore
529forward_traits!
530(
531 for <GenericParam, ...> BaseTransformation [AdditionalTransformation, ...]
532 where WherePredicate, ...
533 impl ForwardedTrait + ...
534);
535```
536
537# Examples
538
539Here we need to introduce a lifetime for one of our forwarded trait's generic
540arguments.
541
542```rust
543# use forward_traits::supply_forwarding_info_for_trait;
544#
545# supply_forwarding_info_for_trait!
546# (
547# std::iter::IntoIterator,
548# trait
549# {
550# type Item;
551# type IntoIter;
552#
553# fn into_iter (self) -> Self::IntoIter;
554# }
555# );
556#
557# supply_forwarding_info_for_trait!
558# (
559# std::convert::TryFrom,
560# trait <T>
561# {
562# type Error;
563#
564# fn try_from (value: T) -> std::result::Result <Self, Self::Error>;
565# }
566# );
567#
568use forward_traits::{forward_receiver, forward_traits};
569
570#[derive (Debug)]
571#[forward_receiver]
572struct Point
573{
574 x: f32,
575 y: f32
576}
577
578impl From <Point> for [f32; 2]
579{
580 fn from (p: Point) -> [f32; 2]
581 {
582 [p . x, p . y]
583 }
584}
585
586impl From <[f32; 2]> for Point
587{
588 fn from (a: [f32; 2]) -> Self
589 {
590 Self {x: a [0], y: a [1]}
591 }
592}
593
594// Make sure that the traits we want are annotated. In this case, we've
595// annotated some std traits and imported them into the local scope.
596
597forward_traits! (for Point -> [f32; 2] impl for <'a> TryFrom <&'a [f32]> + IntoIterator);
598
599// Now we can do weird stuff, life try to construct Point from slices.
600
601Point::try_from ([1f32, 2f32] . as_slice ()) . unwrap () . into_iter ();
602Point::try_from ([1f32] . as_slice ()) . unwrap_err ();
603```
604
605Here we're just doing some boring member delegation.
606
607```rust
608# use forward_traits::supply_forwarding_info_for_trait;
609#
610# supply_forwarding_info_for_trait!
611# (
612# std::ops::Index,
613# trait <Idx>
614# {
615# type Output;
616#
617# fn index (&self, index: Idx) -> &Self::Output;
618# }
619# );
620#
621# supply_forwarding_info_for_trait!
622# (
623# std::ops::IndexMut,
624# trait <Idx>
625# where Self: Index <Idx>
626# {
627# fn index_mut (&mut self, index: Idx) -> &mut Self::Output;
628# }
629# );
630#
631use forward_traits::{forward_receiver, forward_traits};
632
633#[forward_receiver]
634struct Foo
635{
636 header: [u8; 4],
637 items: Vec <u8>
638}
639
640forward_traits! (for Foo . items impl Index <usize> + IndexMut <usize>);
641```
642
643Here we're transforming more than one type at once, and we need to introduce a
644generic parameter in order to specify these additional transformations.
645
646```rust
647use forward_traits::{forwardable, forward_receiver, forward_traits};
648
649struct Algebra {}
650
651#[forwardable]
652trait Foo <T>
653{
654 fn foo (self, x: T);
655}
656
657impl <T> Foo <T> for Algebra
658{
659 fn foo (self, x: T) {}
660}
661
662struct Wrap <T> (T);
663
664#[forward_receiver]
665struct WrapAlgebra {}
666
667impl Into <Algebra> for WrapAlgebra
668{
669 fn into (self) -> Algebra
670 {
671 Algebra {}
672 }
673}
674
675forward_traits!
676(
677 for <T> WrapAlgebra -> Algebra [Wrap <T> . 0: T]
678 impl Foo <Wrap <T>>
679);
680
681WrapAlgebra {} . foo (Wrap::<f32> (1.0))
682```
683*/
684#[proc_macro]
685pub fn forward_traits (input: TokenStream) -> TokenStream
686{
687 macros::forward_traits::forward_traits_impl (input)
688}