1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
/*!
This crate provides general mechanisms for implementing traits on types by
forwarding an implementation provided by another type.
Two different forwarding methods are provided: Forwarding traits implemented by
members, and forwarding traits implemented by types that the receiver type can
convert to. These methods may be used in combination on the same receiver type.
This crate fully supports generic traits and struct types.
For more details about capabilities and limitations, see the documentation pages
for the individual macros.
# Basics
In order to forward a trait, some basic things are needed.
```rust
use forward_traits::{forwardable, forward_receiver, forward_traits_via_member};
```
We need a trait definition which is annotated with information which is used to
generate forwarded implementations. This is done by applying the
`#[forwardable]` attribute to the definition.
```rust
# use forward_traits::forwardable;
#[forwardable]
trait FooTrait
{
type Bar;
fn foo (&self) -> &Self::Bar;
const BAZ: u32;
}
```
Then we need a type which initially implements this trait.
```rust
# trait FooTrait { type Bar; fn foo (&self) -> &Self::Bar; const BAZ: u32; }
struct A {}
impl FooTrait for A
{
type Bar = Self;
fn foo (&self) -> &Self::Bar { self }
const BAZ: u32 = 42;
}
```
Next, we need a type for which we want to implement this trait by forwarding the
implementation found on the initially implementing type. There are a few
different ways to define such a type, but here we will demonstrate the newtype
idiom. This type needs to be annotated with the `#[forward_receiver]`
attribute.
```rust
# use forward_traits::forward_receiver;
# struct A {}
#[forward_receiver]
struct B (A);
```
Lastly, we need to specify that we want to forward a trait using one of the
forwarding macros. In this case, we want to forward a trait implemented by a
member, so we write:
```rust
# use forward_traits::{forwardable, forward_receiver, forward_traits_via_member};
# #[forwardable]
# trait FooTrait { type Bar; fn foo (&self) -> &Self::Bar; const BAZ: u32; }
# struct A {}
# impl FooTrait for A { type Bar = Self; fn foo (&self) -> &Self::Bar { self } const BAZ: u32 = 42; }
# #[forward_receiver]
# struct B (A);
forward_traits_via_member! (B . 0, FooTrait);
```
And now we can see that the trait is properly forwarded.
```rust
# use forward_traits::{forwardable, forward_receiver, forward_traits_via_member};
# #[forwardable]
# trait FooTrait { type Bar; fn foo (&self) -> &Self::Bar; const BAZ: u32; }
# struct A {}
# impl FooTrait for A { type Bar = Self; fn foo (&self) -> &Self::Bar { self } const BAZ: u32 = 42; }
# #[forward_receiver]
# struct B (A);
# forward_traits_via_member! (B . 0, FooTrait);
assert_eq! (<B as FooTrait>::BAZ, 42);
```
# Re-Exporting Forwardable Traits
When re-exporting forwardable traits, the `#[forwardable]` attribute should be
applied to the use statement as well. Note that the attribute will interpret
every item in the use tree as a trait that should be forwardable. If you want
to re-export items that aren't forwardable traits from the same module(s),
you'll need to separate those re-exports out into another use statement;
```rust
use forward_traits::forwardable;
mod inner
{
use forward_traits::forwardable;
#[forwardable]
pub trait Foo {}
pub struct Bar {}
}
#[forwardable]
pub use inner::Foo;
pub use inner::Bar;
```
# Traits in Other Crates
Forwarding traits works with traits in other crates, so long as those trait
definitions are annotated with `#[forwardable]`.
If not, then annotations must be supplied separately. When supplying
annotations in this way, the trait is imported (or re-exported if a visibility
modifier is supplied) at the location of the annotation macro. When forwarding
this trait, you must refer to this import/re-export (or a re-export thereof).
```rust
use forward_traits
::{
supply_forwarding_info_for_trait,
forward_receiver,
forward_traits_via_member
};
// This has the side-effect of importing IntoIterator into the current scope.
supply_forwarding_info_for_trait!
(
std::iter::IntoIterator,
trait
{
type Item;
type IntoIter;
fn into_iter (self) -> Self::IntoIter;
}
);
#[forward_receiver]
struct VecWrapper <T> (Vec <T>);
// Note that we are referring to the IntoIterator in the current scope.
forward_traits_via_member! (VecWrapper . 0, IntoIterator);
// Now we can call the trait method on the wrapper type.
VecWrapper (vec! (1, 2, 3)) . into_iter ();
```
*/
mod generics;
mod partial_eval;
mod mangle;
mod uncurry;
mod transform_use;
mod type_def_info;
mod trait_def_info;
mod forwarded_trait_info;
mod member;
mod transformer;
mod conversion_transformer;
mod member_transformer;
mod forwardable;
mod supply_trait_info;
mod forward_receiver;
mod forward_via_conversion;
mod forward_via_member;
use proc_macro::TokenStream;
/**
This attribute primarily annotates trait definitions with forwarding
information. Secondarily, it is also used to make sure that the forwarding info
is properly re-exported along with the traits that it belongs to.
# Mechanism
The way that this attribute works is by defining a macro which can be used to
uncurry the trait forwarding information into another macro.
Due to limitations of macro export rules, a mangled version of that macro's name
is also created and exported into the crate root. While these names are mangled
so that they're unlikely to cause name collisions, annotating trait definitions
of the same name in two different modules of the same crate will _definitely_
cause a problem. Please keep trait names within a single crate unique.
# Annotating Trait Definitions
Use on trait definitions is pretty simple. Just apply the attribute.
```rust
# use forward_traits::forwardable;
#[forwardable]
trait Foo
{
// ...
}
```
The only consideration is that any types used for method arguments or associated
constants should be named by their fully-qualified paths. This will prevent
name-resolution errors from occurring in the macro-generated implementations.
# Annotating Re-Exports
When re-exporting a trait that has been annotated, the use statement that does
the re-export should also be annotated.
```rust
# use forward_traits::forwardable;
mod foo
{
# use forward_traits::forwardable;
#[forwardable]
pub trait Foo
{
// ...
}
}
#[forwardable]
pub use foo::Foo;
```
The forwarding information is located by modifying the path of the trait passed
into the forwarding macro. If the forwarding information isn't re-exported
alongside the trait, it won't be properly located if a path to the un-annotated
re-export is used in the forwarding macro.
*/
#[proc_macro_attribute]
pub fn forwardable (attr: TokenStream, item: TokenStream) -> TokenStream
{
forwardable::forwardable_impl (attr, item)
}
/**
This attribute annotates type definitions with forwarding information.
# Mechanism
The way that this attribute works is by defining a macro which can be used to
uncurry the type information into another macro.
Due to limitations of macro export rules, a mangled version of that macro's name
is also created and exported into the crate root. While these names are mangled
so that they're unlikely to cause name collisions, annotating type definitions
of the same name in two different modules of the same crate will _definitely_
cause a problem. Please keep type names within a single crate unique.
# Usage
Usage of this attribute is pretty simple. Just apply it to type definitions.
```rust
# use forward_traits::forward_receiver;
#[forward_receiver]
struct Foo
{
// ...
}
```
Both regular structs and tuple-structs are supported.
# Limitations
The only types that are supported are structs. Forwarding methods for enums can
be done in some circumstances easily enough, but figuring out what type to use
as the base for the associated types and constants is not as straightforward.
Solving those sorts of problems is beyond the scope of this crate.
```rust,compile_fail
# use forward_traits::forward_receiver;
// Error: expected `struct`
#[forward_receiver]
enum Foo
{
// ...
}
```
*/
#[proc_macro_attribute]
pub fn forward_receiver (attr: TokenStream, item: TokenStream) -> TokenStream
{
forward_receiver::forward_receiver_impl (attr, item)
}
/**
This macro allows the user to supply forwarding information for a trait in an
external crate that they do not control.
# Usage
The macro takes two arguments. The first is a path to the trait that we're
providing annotations for. The second is the annotation information.
The annotation information is basically just a subset of the parts that make up
a full trait definition.
* `pub` or `pub (restriction)` - An optional visibility specification. This
isn't strictly a part of the trait's info, but will determine the visibility of
the generated macro and trait re-export that is generated as a side-effect of
this macro.
* `trait` - just the keyword `trait`.
* `<'a, T, const N: usize, ...>` - generic parameters, as would be found after
the type identifier in a normal trait definition. Any default values will be
ignored, and should not be provided.
* `where T: 'a, ...` - (optional) a where clause, as would be found in the
trait definition.
* `{type Error; fn try_from (x: T) -> Result <Self, Self::Error>; ...}` - A
block containing the definitions of the trait items. Again, any default values
(or implementations) will be ignored, and should not be provided.
All types included should be named by their fully-qualified paths whenever
applicable.
# Mechanism
The way that this attribute works is by defining a macro which can be used to
uncurry the trait forwarding information into another macro.
Due to limitations of macro export rules, a mangled version of that macro's name
is also created and exported into the crate root. While these names are mangled
so that they're unlikely to cause name collisions, annotating trait definitions
of the same name in two different modules of the same crate will _definitely_
cause a problem. Please keep trait names within a single crate unique.
# Example
```rust
# use forward_traits::{supply_forwarding_info_for_trait, forward_receiver, forward_traits_via_conversion};
supply_forwarding_info_for_trait!
(
std::iter::FromIterator,
pub (crate) trait <A>
{
fn from_iter <T> (iter: T) -> Self
where T: IntoIterator <Item = A>;
}
);
# #[forward_receiver]
# struct VecWrapper <T> (Vec <T>);
# impl <T> From <Vec <T>> for VecWrapper <T> { fn from (vec: Vec <T>) -> Self { Self (vec) } }
# forward_traits_via_conversion! (VecWrapper -> Vec <T>, FromIterator <T>);
```
*/
#[proc_macro]
pub fn supply_forwarding_info_for_trait (input: TokenStream) -> TokenStream
{
supply_trait_info::supply_forwarding_info_for_trait_impl (input)
}
#[doc (hidden)]
#[proc_macro]
pub fn __forward_trait_via_conversion (input: TokenStream) -> TokenStream
{
forward_via_conversion::__forward_trait_via_conversion_impl (input)
}
/**
This macro generates trait implementations based on conversions from the
implementing type to a delegated type which already implements the trait.
# Usage
The first argument to the macro is a specification of the base type and the
delegated type. This specification has the form `BaseTypeIdent ->
path::to::DelegatedType`.
The remaining arguments are descriptions of traits that should be forwarded.
The trait generic arguments, if any, will be interpreted as if the generic
parameters from the base type are in scope.
If a trait would need additional generic arguments to be introduced in order to
correctly specify the trait's generic parameters, these arguments can be
provided by prefixing the trait path with a quantifier over those parameters.
The syntax is similar to that of
Higher-Ranked Trait Bounds, except that all forms of generic parameters are
supported. These parameters will be introduced into the `impl` scope along with
the generic parameters of the receiver type, so make sure that their names don't
collide with the receiver type's generic parameters.
Additionally, if additional where predicates need to be provided on top of those
found in the type definition and trait definition (and besides those which could
be provided automatically by the forwarding macro), then those may also be
introduced by suffixing the trait path with a where clause.
Putting that all together, a description of a trait to be forwarded might look
like this: `for <'a> path::to::Trait <&'a [T]> where T: 'a`.
# Example
```rust
# use forward_traits::supply_forwarding_info_for_trait;
#
# supply_forwarding_info_for_trait!
# (
# std::iter::IntoIterator,
# trait
# {
# type Item;
# type IntoIter;
#
# fn into_iter (self) -> Self::IntoIter;
# }
# );
#
# supply_forwarding_info_for_trait!
# (
# std::convert::TryFrom,
# trait <T>
# {
# type Error;
#
# fn try_from (value: T) -> std::result::Result <Self, Self::Error>;
# }
# );
#
use forward_traits::{forward_receiver, forward_traits_via_conversion};
#[derive (Debug)]
#[forward_receiver]
struct Point
{
x: f32,
y: f32
}
impl From <Point> for [f32; 2]
{
fn from (p: Point) -> [f32; 2]
{
[p . x, p . y]
}
}
impl From <[f32; 2]> for Point
{
fn from (a: [f32; 2]) -> Self
{
Self {x: a [0], y: a [1]}
}
}
// Make sure that the traits we want are annotated. In this case, we've
// annotated some std traits and imported them into the local scope.
forward_traits_via_conversion! (Point -> [f32; 2], for <'a> TryFrom <&'a [f32]>, IntoIterator);
// Now we can do weird stuff, life try to construct Point from slices.
Point::try_from ([1f32, 2f32] . as_slice ()) . unwrap () . into_iter ();
Point::try_from ([1f32] . as_slice ()) . unwrap_err ();
```
# Conversions
Up to 4 different conversions may be used. If `BaseType` were to forward an
implementation by `DelegatedType`, those conversions would be:
* `<BaseType as std::borrow::Borrow <DelegatedType>>::borrow ()` for function
arguments of type `&Self`.
* `<BaseType as std::borrow::BorrowMut <DelegatedType>>::borrow_mut ()` for
function arguments of type `&mut Self`.
* `<BaseType as std::convert::Into <DelegatedType>>::into ()` for function
arguments of type `Self`.
* `<BaseType as std::convert::From <DelegatedType>>::from ()` for a return type
of `Self`.
Any conversion that is actually used to forward a trait implementation will need
to be implemented for the receiving type. Any conversion that is not used does
not need to be implemented.
In practice, if a trait implementation would only use borrowing conversions, it
might make more sense to use a member forward instead, as that doesn't require
that the receiver type implement any conversion traits.
Note that forwarding via conversion is the only way to forward a trait that has
a method that returns `Self` in any form.
All arguments to a trait method that have a type of some form of self are
converted, not just the method receiver. This also allows traits to be
forwarded that require/provide methods that don't take a receiver, but still
take arguments of the receiver type.
Self types in container types like `Result` and `Box` are also converted.
*/
#[proc_macro]
pub fn forward_traits_via_conversion (input: TokenStream) -> TokenStream
{
forward_via_conversion::forward_traits_via_conversion_impl (input)
}
#[doc (hidden)]
#[proc_macro]
pub fn __forward_trait_via_member (input: TokenStream) -> TokenStream
{
forward_via_member::__forward_trait_via_member_impl (input)
}
/**
This macro generates trait implementations for a type where a member of that
type implements the trait.
# Usage
The first argument to the macro is a specification of which member should
provide the implementation of the forwarded trait. This specification takes the
form `BaseTypeIdent . member`, where `member` is either an identifier or an
index, as appropriate for the type.
The remaining arguments are descriptions of traits that should be forwarded.
The trait generic arguments, if any, will be interpreted as if the generic
parameters from the base type are in scope.
If a trait would need additional generic arguments to be introduced in order to
correctly specify the trait's generic parameters, these arguments can be
provided by prefixing the trait path with a quantifier over those parameters.
The syntax is similar to that of
Higher-Ranked Trait Bounds, except that all forms of generic parameters are
supported. These parameters will be introduced into the `impl` scope along with
the generic parameters of the receiver type, so make sure that their names don't
collide with the receiver type's generic parameters.
Additionally, if additional where predicates need to be provided on top of those
found in the type definition and trait definition (and besides those which could
be provided automatically by the forwarding macro), then those may also be
introduced by suffixing the trait path with a where clause.
Putting that all together, a description of a trait to be forwarded might look
like this: `for <'a> path::to::Trait <&'a [T]> where T: 'a`.
# Example
```rust
# use forward_traits::supply_forwarding_info_for_trait;
#
# supply_forwarding_info_for_trait!
# (
# std::ops::Index,
# trait <Idx>
# {
# type Output;
#
# fn index (&self, index: Idx) -> &Self::Output;
# }
# );
#
# supply_forwarding_info_for_trait!
# (
# std::ops::IndexMut,
# trait <Idx>
# where Self: Index <Idx>
# {
# fn index_mut (&mut self, index: Idx) -> &mut Self::Output;
# }
# );
#
use forward_traits::{forward_receiver, forward_traits_via_member};
#[forward_receiver]
struct Foo
{
header: [u8; 4],
items: Vec <u8>
}
forward_traits_via_member! (Foo . items, Index <usize>, IndexMut <usize>);
```
# Conversions
Conversions are performed via member access. Return types cannot be converted,
as member access has no inverse.
All arguments to a trait method that have a type of some form of self are
converted, not just the method receiver. This also allows traits to be
forwarded that require/provide methods that don't take a receiver, but still
take arguments of the receiver type.
Self types in container types like `Result` and `Box` are also converted.
*/
#[proc_macro]
pub fn forward_traits_via_member (input: TokenStream) -> TokenStream
{
forward_via_member::forward_traits_via_member_impl (input)
}