inherent/lib.rs
1//! [![github]](https://github.com/dtolnay/inherent) [![crates-io]](https://crates.io/crates/inherent) [![docs-rs]](https://docs.rs/inherent)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! <br>
8//!
9//! ##### An attribute macro to make trait methods callable without the trait in scope.
10//!
11//! # Example
12//!
13//! ```rust
14//! mod types {
15//! use inherent::inherent;
16//!
17//! trait Trait {
18//! fn f(self);
19//! }
20//!
21//! pub struct Struct;
22//!
23//! #[inherent]
24//! impl Trait for Struct {
25//! pub fn f(self) {}
26//! }
27//! }
28//!
29//! fn main() {
30//! // types::Trait is not in scope, but method can be called.
31//! types::Struct.f();
32//! }
33//! ```
34//!
35//! Without the `inherent` macro on the trait impl, this would have failed with the
36//! following error:
37//!
38//! ```console
39//! error[E0599]: no method named `f` found for type `types::Struct` in the current scope
40//! --> src/main.rs:18:19
41//! |
42//! 8 | pub struct Struct;
43//! | ------------------ method `f` not found for this
44//! ...
45//! 18 | types::Struct.f();
46//! | ^
47//! |
48//! = help: items from traits can only be used if the trait is implemented and in scope
49//! = note: the following trait defines an item `f`, perhaps you need to implement it:
50//! candidate #1: `types::Trait`
51//! ```
52//!
53//! The `inherent` macro expands to inherent methods on the `Self` type of the trait
54//! impl that forward to the trait methods. In the case above, the generated code
55//! would be:
56//!
57//! ```rust
58//! # trait Trait {
59//! # fn f(self);
60//! # }
61//! #
62//! # pub struct Struct;
63//! #
64//! # impl Trait for Struct {
65//! # fn f(self) {}
66//! # }
67//! #
68//! impl Struct {
69//! pub fn f(self) {
70//! <Self as Trait>::f(self)
71//! }
72//! }
73//! ```
74
75#![doc(html_root_url = "https://docs.rs/inherent/1.0.13")]
76#![allow(
77 clippy::default_trait_access,
78 clippy::module_name_repetitions,
79 clippy::needless_doctest_main,
80 clippy::needless_pass_by_value,
81 clippy::uninlined_format_args
82)]
83
84extern crate proc_macro;
85
86mod expand;
87mod parse;
88mod verbatim;
89
90use proc_macro::TokenStream;
91use syn::parse::Nothing;
92use syn::parse_macro_input;
93
94use crate::parse::TraitImpl;
95
96#[proc_macro_attribute]
97pub fn inherent(args: TokenStream, input: TokenStream) -> TokenStream {
98 parse_macro_input!(args as Nothing);
99 let input = parse_macro_input!(input as TraitImpl);
100 expand::inherent(input).into()
101}