zoet_macro/
lib.rs

1//! [`zoet`](https://docs.rs/zoet/)'s proc-macro implementation. See that crate for documentation,
2//! and do not use this crate directly.
3
4/* Firstly, if we have the "clippy-insane" feature and a dev build -- it's assumed that a release
5 * build has taken the diagnostics into account -- we turn on far too many warnings. */
6#![cfg_attr(
7    all(feature = "clippy-insane", debug_assertions),
8    warn(
9        /* Turn the "allow" lints listed by `rustc -W help` ["rustc 1.77.1 (7cf61ebde 2024-03-27)"]
10         * into warn lints: */
11
12        absolute_paths_not_starting_with_crate,deprecated_in_future, elided_lifetimes_in_paths,
13        explicit_outlives_requirements, ffi_unwind_calls, keyword_idents_2018, keyword_idents_2024,
14        let_underscore_drop, macro_use_extern_crate, meta_variable_misuse, missing_abi,
15        missing_copy_implementations, missing_debug_implementations, missing_docs, non_ascii_idents,
16        non_local_definitions, redundant_lifetimes, rust_2021_incompatible_closure_captures,
17        rust_2021_incompatible_or_patterns, rust_2021_prefixes_incompatible_syntax,
18        rust_2021_prelude_collisions, single_use_lifetimes, trivial_casts, trivial_numeric_casts,
19        unit_bindings, unnameable_types, unreachable_pub, unsafe_code, unsafe_op_in_unsafe_fn,
20        unstable_features, unused_crate_dependencies, unused_extern_crates, unused_import_braces,
21        unused_lifetimes, unused_macro_rules, unused_qualifications, unused_results,
22        variant_size_differences,
23
24        //// stable compiler claims this is unstable, but unstable compiler claims it doesn't exist.
25        // dereferencing_mut_binding,
26
27        /* Ditto for clippy lint categories (see https://github.com/rust-lang/rust-clippy): */
28        clippy::all, clippy::nursery, clippy::pedantic, clippy::restriction,
29        // clippy::cargo,
30    ),
31    /* Sometimes there are lints listed in the stable compiler's -W help output which are actually
32     * nightly-only. If there are any, they get listed here instead of above. */
33    cfg_attr(
34        feature = "nightly",
35        feature(
36            multiple_supertrait_upcastable,
37            must_not_suspend,
38            non_exhaustive_omitted_patterns_lint,
39            strict_provenance,
40        ),
41        warn(
42            fuzzy_provenance_casts,
43            lossy_provenance_casts,
44            multiple_supertrait_upcastable,
45            must_not_suspend,
46            non_exhaustive_omitted_patterns,
47        )
48    ),
49    /* Now go back and turn back off any lints which turned out to be too noisy or annoying. In
50     * particular, clippy::all and clippy::restriction are "blanket" lints which turn on a lot of
51     * things, not all of which are useful. */
52    allow(
53        clippy::blanket_clippy_restriction_lints,
54        /* Turn off individual noisy/buggy lints enabled by broader categories above: */
55        clippy::allow_attributes, // recommended "expect" does not have the desired behaviour
56        clippy::allow_attributes_without_reason, // #(allow, reason="...") is nightly-only
57        clippy::implicit_return,                 // not idiomatic Rust
58        clippy::min_ident_chars,                 // single character idents are okay
59        clippy::missing_docs_in_private_items,   // don't care
60        clippy::needless_borrowed_reference,     // can't decide if this is good or bad
61        clippy::option_if_let_else,              // `.map_or{_else}` is not the same thing.
62        clippy::pub_with_shorthand,              // demands `pub(in crate)` but rustfmt disagrees
63        clippy::question_mark_used,              //
64        clippy::redundant_pub_crate,             // conflicts with unreachable_pub
65        clippy::ref_patterns,                    //
66        clippy::shadow_reuse,                    // e.g. `let foo = bar(foo)`
67        clippy::single_call_fn,                  // What am I expected to do with this information?
68        clippy::single_char_lifetime_names,      //
69        clippy::std_instead_of_alloc,            // don't care
70        clippy::std_instead_of_core,             // `proc_macro_error` again; also don't care
71        clippy::wildcard_enum_match_arm,         // excessively pedantic
72        elided_lifetimes_in_paths,               // demands adding <'_> noise
73        non_exhaustive_omitted_patterns,         // TODO: Sort of useful but loads of noise.
74
75        // reason = "can't see the wood for the trees"
76    ))]
77/* Any nightly-only features we actually want. This should be relatively small because we want the
78 * crate to run on stable, and so nightly-only features can only be used for enhancement, such as
79 * better error messages during development. */
80// #![cfg_attr(
81//     feature = "nightly",
82//     // TODO: #[deny(internal_features)] is now the default, which forbids rustc_attrs. Should we
83//     // take the hint and find some other way to achieve our ends than rustc_attrs?
84//     allow(unstable_features, internal_features),
85//     feature(negative_impls, rustc_attrs),
86//     feature(doc_auto_cfg, doc_cfg, doc_notable_trait)
87// )]
88//#![cfg_attr(test, feature(test))]
89//#![no_std]
90#![forbid(unsafe_code)]
91
92macro_rules! diagnostic_error {
93    ($SPAN:expr, $($REST:tt)+) => {
94        ::proc_macro_error::diagnostic!($SPAN, ::proc_macro_error::Level::Error, $($REST)+)
95    }
96}
97
98mod function_args;
99mod self_replacer;
100mod traits;
101mod with_tokens;
102mod zoet;
103
104pub(crate) type Error = proc_macro_error::Diagnostic;
105pub(crate) type Result<T, E = Error> = core::result::Result<T, E>;
106
107/// The `#[zoet]` macro.
108#[proc_macro_error::proc_macro_error]
109#[proc_macro_attribute]
110pub fn zoet(
111    attr: proc_macro::TokenStream, item: proc_macro::TokenStream,
112) -> proc_macro::TokenStream {
113    zoet::zoet(&attr.into(), &item.into()).into()
114}