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
//! [`zoet`](https://docs.rs/zoet/)'s proc-macro implementation. See that crate for documentation,
//! and do not use this crate directly.

/* Firstly, if we have the "clippy-insane" feature and a dev build -- it's assumed that a release
 * build has taken the diagnostics into account -- we turn on far too many warnings. */
#![cfg_attr(
    all(feature = "clippy-insane", debug_assertions),
    warn(
        /* Turn the "allow" lints listed by `rustc -W help` ["rustc 1.77.1 (7cf61ebde 2024-03-27)"]
         * into warn lints: */

        absolute_paths_not_starting_with_crate, box_pointers, deprecated_in_future,
        elided_lifetimes_in_paths, explicit_outlives_requirements, ffi_unwind_calls,
        keyword_idents_2018, keyword_idents_2024, let_underscore_drop, macro_use_extern_crate,
        meta_variable_misuse, missing_abi, missing_copy_implementations,
        missing_debug_implementations, missing_docs, non_ascii_idents, non_local_definitions,
        redundant_lifetimes, rust_2021_incompatible_closure_captures,
        rust_2021_incompatible_or_patterns, rust_2021_prefixes_incompatible_syntax,
        rust_2021_prelude_collisions, single_use_lifetimes, trivial_casts, trivial_numeric_casts,
        unit_bindings, unnameable_types, unreachable_pub, unsafe_code, unsafe_op_in_unsafe_fn,
        unstable_features, unused_crate_dependencies, unused_extern_crates, unused_import_braces,
        unused_lifetimes, unused_macro_rules, unused_qualifications, unused_results,
        variant_size_differences,

        //// stable compiler claims this is unstable, but unstable compiler claims it doesn't exist.
        // dereferencing_mut_binding,

        /* Ditto for clippy lint categories (see https://github.com/rust-lang/rust-clippy): */
        clippy::all, clippy::nursery, clippy::pedantic, clippy::restriction,
        // clippy::cargo,
    ),
    /* Sometimes there are lints listed in the stable compiler's -W help output which are actually
     * nightly-only. If there are any, they get listed here instead of above. */
    cfg_attr(
        feature = "nightly",
        feature(
            multiple_supertrait_upcastable,
            must_not_suspend,
            non_exhaustive_omitted_patterns_lint,
            strict_provenance,
        ),
        warn(
            fuzzy_provenance_casts,
            lossy_provenance_casts,
            multiple_supertrait_upcastable,
            must_not_suspend,
            non_exhaustive_omitted_patterns,
        )
    ),
    /* Now go back and turn back off any lints which turned out to be too noisy or annoying. In
     * particular, clippy::all and clippy::restriction are "blanket" lints which turn on a lot of
     * things, not all of which are useful. */
    allow(
        clippy::blanket_clippy_restriction_lints,
        /* Turn off individual noisy/buggy lints enabled by broader categories above: */
        box_pointers,           //// obsolete/don't care

        clippy::allow_attributes, //// the recommended "expect" does not have the desired behaviour
        clippy::implicit_return,  //// not idiomatic Rust
        clippy::min_ident_chars,  //// single character idents are okay
        clippy::missing_docs_in_private_items, //// don't care
        clippy::needless_borrowed_reference,   //// can't decide if this is good or bad
        clippy::option_if_let_else,            //// `.map_or{_else}` is not the same thing.
        clippy::pub_with_shorthand,            //// demands `pub(in crate)` but rustfmt disagrees
        clippy::question_mark_used,            ////
        clippy::redundant_pub_crate,           //// conflicts with unreachable_pub
        clippy::ref_patterns,                  ////
        clippy::shadow_reuse,                  //// e.g. `let foo = bar(foo)`
        clippy::single_call_fn,                //// What am I expected to do with this information?
        clippy::single_char_lifetime_names,    ////
        clippy::std_instead_of_alloc,          //// don't care
        clippy::std_instead_of_core,           //// `proc_macro_error` again; also don't care
        clippy::wildcard_enum_match_arm,       //// excessively pedantic
        elided_lifetimes_in_paths,              //// demands adding <'_> noise
        non_exhaustive_omitted_patterns,        //// TODO: Sort of useful but loads of noise.

        reason = "can't see the wood for the trees"
    ))]
/* Any nightly-only features we actually want. This should be relatively small because we want the
 * crate to run on stable, and so nightly-only features can only be used for enhancement, such as
 * better error messages during development. */
// #![cfg_attr(
//     feature = "nightly",
//     // TODO: #[deny(internal_features)] is now the default, which forbids rustc_attrs. Should we
//     // take the hint and find some other way to achieve our ends than rustc_attrs?
//     allow(unstable_features, internal_features),
//     feature(negative_impls, rustc_attrs),
//     feature(doc_auto_cfg, doc_cfg, doc_notable_trait)
// )]
#![cfg_attr(test, feature(test))]
//#![no_std]
#![forbid(unsafe_code)]

macro_rules! diagnostic_error {
    ($SPAN:expr, $($REST:tt)+) => {
        ::proc_macro_error::diagnostic!($SPAN, ::proc_macro_error::Level::Error, $($REST)+)
    }
}

mod function_args;
mod self_replacer;
mod traits;
mod with_tokens;
mod zoet;

pub(crate) type Error = proc_macro_error::Diagnostic;
pub(crate) type Result<T, E = Error> = core::result::Result<T, E>;

/// The `#[zoet]` macro.
#[proc_macro_error::proc_macro_error]
#[proc_macro_attribute]
pub fn zoet(
    attr: proc_macro::TokenStream, item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    zoet::zoet(&attr.into(), &item.into()).into()
}