derive_deftly_macros/
macros.rs

1#![allow(clippy::style, clippy::complexity)]
2#![doc=include_str!("README.md")]
3//
4// This is the actual proc-macro crate.
5//
6// All it exports (or can export) are the proc macros themselves.
7// Everything else that is `pub` could be written `pub(crate)`.
8
9mod prelude;
10
11pub(crate) use prelude::*;
12
13// Implementation - common parts
14#[macro_use]
15pub(crate) mod utils;
16#[macro_use]
17pub(crate) mod adviseable;
18pub(crate) mod framework;
19pub(crate) mod general_context;
20
21// Implementation - specific areas
22pub(crate) mod accum;
23pub(crate) mod approx_equal;
24pub(crate) mod boolean;
25pub(crate) mod concat;
26pub(crate) mod dbg_allkw;
27pub(crate) mod expand;
28pub(crate) mod meta;
29pub(crate) mod modules;
30pub(crate) mod options;
31pub(crate) mod paste;
32pub(crate) mod repeat;
33pub(crate) mod syntax;
34
35#[cfg_attr(not(feature = "beta"), path = "beta_disabled.rs")]
36pub(crate) mod beta;
37
38// Implementations of each proc-macros
39pub(crate) mod adhoc;
40pub(crate) mod define;
41pub(crate) mod derive;
42pub(crate) mod engine;
43pub(crate) mod semver;
44
45pub(crate) mod compat_syn_2;
46pub(crate) mod compat_syn_common;
47
48#[doc=include_str!("HACKING.md")]
49mod _doc_hacking {}
50
51#[doc=include_str!("NOTES.md")]
52mod _doc_notes {}
53
54/// Dummy of proc_macro for use when compiling outside of proc macro context
55#[cfg(not(proc_macro))]
56pub(crate) mod proc_macro {
57    pub(crate) use proc_macro2::TokenStream;
58}
59
60//========== `expect`, the `check` module (or dummy version) ==========
61
62// "expect" feature; module named check.rs for tab completion reasons
63#[cfg(feature = "expect")]
64mod check;
65#[cfg(not(feature = "expect"))]
66mod check {
67    use super::prelude::*;
68    #[derive(Debug, Clone, Copy, PartialEq)]
69    pub struct Target(Void);
70
71    impl FromStr for Target {
72        type Err = Void;
73        fn from_str(_: &str) -> Result<Self, Void> {
74            panic!("output syntax checking not supported, enable `expect` feature of `derive-deftly`")
75        }
76    }
77
78    pub fn check_expected_target_syntax(
79        _ctx: &framework::Context,
80        _output: &mut TokenStream,
81        target: DdOptVal<Target>,
82    ) {
83        void::unreachable(target.value.0)
84    }
85
86    pub fn check_expect_opcontext(
87        op: &DdOptVal<Target>,
88        _context: OpContext,
89    ) -> syn::Result<()> {
90        void::unreachable(op.value.0)
91    }
92}
93impl DdOptValDescribable for check::Target {
94    const DESCRIPTION: &'static str =
95        "expected output syntax (`expect` option)";
96}
97
98//========== actual macro entrypoints ==========
99
100/// Wraps an actual macro implementation function that uses a proc_macro2
101/// implementation to expose a proc_macro implementation instead.
102//
103// Clippy gives false positives for converting between proc_macro[2]::TokenStream.
104#[allow(clippy::useless_conversion)]
105fn wrap_macro_func<F>(
106    func: F,
107    input: proc_macro::TokenStream,
108) -> proc_macro::TokenStream
109where
110    F: FnOnce(
111        proc_macro2::TokenStream,
112    ) -> Result<proc_macro2::TokenStream, syn::Error>,
113{
114    let input = proc_macro2::TokenStream::from(input);
115    let output = func(input).unwrap_or_else(|e| e.into_compile_error());
116    proc_macro::TokenStream::from(output)
117}
118
119/// Template expansion engine, internal
120///
121/// <!-- @dd-navbar macros . -->
122/// <!-- this line automatically maintained by update-navbars --><nav style="text-align: right; margin-bottom: 12px;">[ <em>docs: <a href="index.html">crate top-level</a> | <a href="index.html#overall-toc">overall toc, <strong>macros</strong></a> | <a href="doc_reference/index.html">template etc. reference</a> | <a href="https://diziet.pages.torproject.net/rust-derive-deftly/latest/guide/">guide/tutorial</a></em> ]</nav>
123///
124/// Normally you do not need to mention this macro.
125///
126/// derive-deftly does its work by
127/// (defining and then) invoking various interrelated macros
128/// including `macro_rules` macros and proc macros.
129/// These ultimately end up calling this macro,
130/// which takes a template and a data structure,
131/// and expands the template for that data structure.
132///
133/// This macro's behvaiour is not currently stable or documented.
134/// If you invoke it yourself, you get to keep all the pieces.
135#[cfg_attr(proc_macro, proc_macro)]
136pub fn derive_deftly_engine(
137    input: proc_macro::TokenStream,
138) -> proc_macro::TokenStream {
139    wrap_macro_func(engine::derive_deftly_engine_func_macro, input)
140}
141
142/// Expand an ad-hoc template, on a data structure decorated `#[derive_deftly_adhoc]`
143///
144/// <!-- @dd-navbar macros . -->
145/// <!-- this line automatically maintained by update-navbars --><nav style="text-align: right; margin-bottom: 12px;">[ <em>docs: <a href="index.html">crate top-level</a> | <a href="index.html#overall-toc">overall toc, <strong>macros</strong></a> | <a href="doc_reference/index.html">template etc. reference</a> | <a href="https://diziet.pages.torproject.net/rust-derive-deftly/latest/guide/">guide/tutorial</a></em> ]</nav>
146///
147/// ```
148// We're in the macro crate, where the facade crate is not available.
149// So we must do some namespace-swizzling.
150/// # use derive_deftly_macros as derive_deftly;
151// `proc-macro-crate` says `Itself` so generates ::derive_deftly_engine,
152// which is wrong for a doctest.  Fudge that.  We must also make sure
153// we're not inside main here, so we must define a main.
154/// # use derive_deftly::derive_deftly_engine;
155/// # fn main(){}
156/// use derive_deftly::{Deftly, derive_deftly_adhoc};
157/// #[derive(Deftly)]
158/// #[derive_deftly_adhoc]
159/// struct DdtaStructureType { }
160///
161// Smoke and mirrors so we can use metasyntactic OPTIONS and TEMPLATE.
162/// # macro_rules! derive_deftly_adhoc { {
163/// #     $x:ident OPTIONS,..: TEMPLATE
164/// # } => { derive_deftly_macros::derive_deftly_adhoc! {
165/// #     $x expect items: fn x(){}
166/// # } } }
167/// derive_deftly_adhoc! {
168///     DdtaStructureType OPTIONS,..:
169///     TEMPLATE
170/// }
171/// ```
172///
173/// Expands the template `TEMPLATE` for the type `DdtaStructureType`,
174///
175/// `OPTIONS,..` is an optional comma-separated list of
176/// [expansion options](doc_reference/index.html#expansion-options).
177///
178/// The definition of `DdtaStructureType` must have been decorated
179/// with [`#[derive(Deftly)]`](crate::Deftly),
180/// and `#[derive_deftly_adhoc]`,
181/// and the resulting `derive_deftly_driver_TYPE` macro must be
182/// available in scope.
183///
184/// `derive_deftly_adhoc!` can be used in any context
185/// where the Rust language permits macro calls.
186/// For example, it can expand to expressions, statements,
187/// types, or patterns.
188#[cfg_attr(proc_macro, proc_macro)]
189pub fn derive_deftly_adhoc(
190    input: proc_macro::TokenStream,
191) -> proc_macro::TokenStream {
192    wrap_macro_func(adhoc::derive_deftly_adhoc, input)
193}
194
195/// Define a reuseable template
196///
197/// <!-- @dd-navbar macros . -->
198/// <!-- this line automatically maintained by update-navbars --><nav style="text-align: right; margin-bottom: 12px;">[ <em>docs: <a href="index.html">crate top-level</a> | <a href="index.html#overall-toc">overall toc, <strong>macros</strong></a> | <a href="doc_reference/index.html">template etc. reference</a> | <a href="https://diziet.pages.torproject.net/rust-derive-deftly/latest/guide/">guide/tutorial</a></em> ]</nav>
199///
200/// ```text
201/// define_derive_deftly! {
202///     [use SomeModule; ..]
203///     [/// DOCS]
204///     [export] MyMacro OPTIONS,..:
205///     TEMPLATE
206/// }
207/// ```
208///
209/// Then, `MyMacro` can be used with
210/// [`#[derive(Deftly)]`](crate::Deftly)
211/// `#[derive_deftly(MyMacro)]`.
212///
213/// <span id="options-in-define">`OPTIONS,..`</span>
214/// is an optional comma-separated list of
215/// [expansion options](doc_reference/index.html#expansion-options),
216/// which will be applied whenever this template is expanded.
217///
218/// <span id="docs-in-define">`DOCS`</span>,
219/// if supplied, are used as the rustdocs
220/// for the captured template macro `derive_deftly_template_MyMacro`.
221/// derive-deftly will then also append a note about
222/// how to invoke the template.
223/// (The `#[doc]` attribute syntax can also be used here.)
224///
225/// `use` in the preamble refers not to a Rust language module (`mod`)
226/// but to a module defined with [`define_derive_deftly_module!`].
227///
228/// ## Template definition macro `derive_deftly_template_MyMacro`
229///
230/// The template is made into a `macro_rules` macro
231/// named `derive_deftly_template_MyMacro`,
232/// which is referenced when the template is applied.
233///
234/// The template definition macro
235/// from `define_derive_deftly!`
236/// must be in scope at the point where you try to use it
237/// (with `#[derive(Deftly)] #[derive_deftly(MyMacro)]`).
238/// If the template definition is in another module,
239/// you may need to annotate that module with `#[macro_use]`.
240/// See the
241/// [documentation for `#[derive(Deftly)]`](derive.Deftly.html#scoping-and-ordering-within-the-same-crate).
242///
243/// ## Exporting a template for use by other crates
244///
245/// With `export MyMacro`, `define_derive_deftly!` exports the template
246/// for use by other crates.
247/// Then, it is referred to in other crates
248/// with `#[derive_ahdoc(this_crate::MyMacro)]`.
249///
250/// I.e., `export MyMacro` causes the `derive_deftly_template_MyMacro`
251/// pattern macro to be exported with `#[macro_export]`.
252///
253/// Note that a template is always exported at the crate top level,
254/// not in a sub-module,
255/// even if it is *defined* in a sub-module.
256/// Also, note that `export` does not have any effect on
257/// visibility of the template *within the same crate*.
258/// You may still need `#[macro_use]`.
259///
260/// ### You must re-export `derive_deftly`; semver implications
261///
262/// When exporting a template to other crates, you must also
263/// re-export `derive_deftly`,
264/// at the top level of your crate:
265///
266/// ```ignore
267/// #[doc(hidden)]
268/// pub use derive_deftly;
269/// ```
270/// This is used to find the template expansion engine,
271/// and will arrange that your template is expanded
272/// by the right version of derive-deftly.
273/// The template syntax is that for *your* version of `derive-deftly`,
274/// even if the depending crate uses a different version of derive-deftly.
275///
276/// You should *not* treat a breaking change
277/// to derive-deftly's template syntax
278/// (which is a major change to derive-deftly),
279/// nor a requirement to use a newer template feature,
280/// as a breaking changes in the API of your crate.
281/// (You *should* use `#[doc(hidden)]`, or other approaches,
282/// to discourage downstream crates from using
283/// the derive-deftly version you re-export.
284/// Such use would be outside the semver guarantees.)
285///
286/// You *should* call
287/// [`derive_deftly::template_export_semver_check!`](macro@template_export_semver_check)
288/// once in each crate that exports macros.
289/// This will notify you, by breaking your build,
290/// if you update to a derive-deftly version
291/// that has semver implications for other crates that use your macros.
292///
293/// Changes that would require a semver bump
294/// for all libraries that export templates,
295/// will be rare, and specially marked in the derive-deftly changelog.
296/// Search for sections with titles containing "template export semver".
297///
298/// ## Namespacing within a template
299///
300/// Within the template,
301/// items within your crate can be referred to with
302/// [`$crate`](doc_reference/index.html#x:crate).
303///
304/// For other items,
305/// including from the standard library e.g., `std::option::Option`,
306/// you may rely on the context which uses the template
307/// to have a reasonable namespace,
308/// or use a explicit paths starting with `std` or `::std` or `::core`
309/// or `$crate` (perhaps naming a re-export).
310///
311/// Overall, the situation is similar to defining
312/// an exported `macro_rules` macro.
313#[cfg_attr(proc_macro, proc_macro)]
314pub fn define_derive_deftly(
315    input: proc_macro::TokenStream,
316) -> proc_macro::TokenStream {
317    wrap_macro_func(define::define_derive_deftly_func_macro, input)
318}
319
320/// Perform ad-hoc templating driven by a data structure
321///
322/// <!-- @dd-navbar macros . -->
323/// <!-- this line automatically maintained by update-navbars --><nav style="text-align: right; margin-bottom: 12px;">[ <em>docs: <a href="index.html">crate top-level</a> | <a href="index.html#overall-toc">overall toc, <strong>macros</strong></a> | <a href="doc_reference/index.html">template etc. reference</a> | <a href="https://diziet.pages.torproject.net/rust-derive-deftly/latest/guide/">guide/tutorial</a></em> ]</nav>
324///
325/// This macro does two things:
326///
327///  1. If `#[derive_deftly(MyMacro)]` attributes are also specified,
328///     they are taken to refer to reuseable templates
329///     defined with
330///     [`define_derive_deftly!`](macro@crate::define_derive_deftly).
331///     Each such `MyMacro` is applied to the data structure.
332///
333///     <span id="expansion-options">You can specify
334///     [expansion options](doc_reference/index.html#expansion-options)
335///     for each such template application, by writing
336///     `#[derive_deftly(MyMacro[OPTIONS,..])]`, where
337///     `[OPTIONS,..]` is a comma-separated list of expansion options
338///     contained within `[ ]`.</span>
339///
340///  2. If `#[derive_deftly_adhoc]` is specified,
341///     captures the data structure definition,
342///     so that it can be used with calls to
343///     [`derive_deftly_adhoc!`](macro@crate::derive_deftly_adhoc).
344///
345/// ## `#[deftly]` attribute
346///
347/// The contents of `#[deftly]` attributes are made available
348/// to templates via the
349/// [`${Xmeta}`](doc_reference/index.html#tmeta-vmeta-fmeta--deftly-attributes)
350/// expansions.
351///
352/// If none of the template(s) recognise them,
353/// [it is an error](doc_reference/index.html#unrecognisedunused-deftly-attributes),
354/// (unless `#[derive_deftly_adhoc]` is specified).
355///
356/// `derive-deftly`
357/// [does not impose any namespacing](doc_reference/index.html#attribute-namespacing)
358/// within `#[deftly]`:
359///
360/// ## Scoping and ordering within the same crate
361///
362/// **Summary of required ordering**
363///
364///  1. `define_derive_deftly! { MyMacro = ... }`
365///  2. `#[derive(Deftly)] #[derive_deftly(MyMacro)] struct MyStruct { ... }`
366///  3. `derive_deftly_adhoc! { MyStruct: ... }`
367///
368/// Any reusable templates defined with
369/// `define_derive_deftly!` must lexically their precede
370/// uses with `#[derive(Deftly) #[derive_deftly(...)]`.
371///
372/// And, for one-off templates (`derive_deftly_adhoc!`),
373/// the data structure with its `#[derive(Deftly)]`
374/// must lexically precede
375/// the references in `derive_deftly_adhoc!`,
376/// so that the data structure definition macro
377/// is in scope.
378///
379/// In each case,
380/// if the definition is in another module
381/// in the same crate,
382/// the defining module's `mod` statement must come before
383/// the reference,
384/// and
385/// the `mod` statement will need `#[macro_use]`.
386/// So the placement and order of `mod` statements can matter.
387/// Alternatively, it is possible to use path-based scoping;
388/// there is
389/// [an example in the Guide](https://diziet.pages.torproject.net/rust-derive-deftly/latest/guide/templates-in-modules.html#path-scope).
390///
391/// ## Applying a template (derive-deftly macro) from another crate
392///
393/// `#[derive_deftly(some_crate::MyMacro)]`
394/// applies an exported template
395/// defined and exported by `some_crate`.
396///
397/// You can import a template from another crate,
398/// so you can apply it with an unqualified name,
399/// with `use`,
400/// but the `use` must refer to
401/// the actual pattern macro name `derive_deftly_template_MyMacro`:
402/// ```
403// See the doc comment for `derive_deftly_adhoc`.
404/// # use derive_deftly_macros as derive_deftly;
405/// # use derive_deftly::derive_deftly_engine;
406/// # fn main(){}
407// We can't make another crate.  Fake up the macro definition
408/// # derive_deftly::define_derive_deftly! { TheirMacro: }
409/// use derive_deftly::Deftly;
410// and don't really try to import it, then
411/// # #[cfg(any())]
412/// use other_crate::derive_deftly_template_TheirMacro;
413/// #[derive(Deftly)]
414/// #[derive_deftly(TheirMacro)]
415/// struct MyStruct { // ...
416/// # }
417/// ```
418///
419/// ## Captured data structure definition `derive_deftly_driver_TYPE`
420///
421/// With `#[derive_deftly_adhoc]`,
422/// the data structure is captured
423/// for use by
424/// [`derive_deftly_adhoc!`](macro@crate::derive_deftly_adhoc).
425///
426/// Specifically, by defining
427/// a `macro_rules` macro called `derive_deftly_driver_TYPE`,
428/// where `TYPE` is the name of the type
429/// that `#[derive(Deftly)]` is applied to.
430///
431/// ### Exporting the driver for downstream crates' templates
432///
433// Really, the documentation about this in `pub-a.rs` and `pub-b.rs`,
434// should be somewhere in our rustdoc output.
435// But I don't want to put it *here* because it would completely
436// dominate this macro documentation.
437// So for now just reference the source tree docs.
438// (We can't really easily provide even a link.)
439// I think this is such a minority feature,
440// that hiding the docs like this is OK.
441//
442/// To cause the macro embodying the driver struct to be exported,
443/// write:
444/// `#[derive_deftly_adhoc(export)]`.
445/// The driver can then be derived from in other crates,
446/// with `derive_deftly_adhoc! { exporting_crate::DriverStruct: ... }`.
447///
448/// #### Semver hazards
449///
450/// This is a tricky feature,
451/// which should only be used by experts
452/// who fully understand the implications.
453/// It effectively turns the body of the struct into a macro,
454/// with a brittle API
455/// and very limited support for namespacing or hygiene.
456///
457/// See `pub mod a_driver` in the example file `pub-a.rs`,
458/// in the source tree,
459/// for a fuller discussion of the implications,
460/// and some advice.
461///
462/// If you do this, you must **pin your derive-deftly** to a minor version,
463/// as you may need to treat *minor* version updates in derive-deftly
464/// as semver breaks for your crate.
465/// And every time you update, you must read the `CHANGELOG.md`,
466/// since there is nothing that will warn you automatically
467/// about breaking changes.
468//
469// This is the implementation of #[derive(Deftly)]
470#[cfg_attr(
471    proc_macro,
472    proc_macro_derive(
473        Deftly,
474        attributes(deftly, derive_deftly, derive_deftly_adhoc)
475    )
476)]
477pub fn derive_deftly(
478    input: proc_macro::TokenStream,
479) -> proc_macro::TokenStream {
480    wrap_macro_func(derive::derive_deftly, input)
481}
482
483/// Define a module with reuseable template definitions (**beta**)
484///
485/// <!-- @dd-navbar macros . -->
486/// <!-- this line automatically maintained by update-navbars --><nav style="text-align: right; margin-bottom: 12px;">[ <em>docs: <a href="index.html">crate top-level</a> | <a href="index.html#overall-toc">overall toc, <strong>macros</strong></a> | <a href="doc_reference/index.html">template etc. reference</a> | <a href="https://diziet.pages.torproject.net/rust-derive-deftly/latest/guide/">guide/tutorial</a></em> ]</nav>
487///
488/// ```text
489/// define_derive_deftly_module! {
490///     [/// DOCS]
491///     [export] MyModule OPTIONS,..:
492///     [use SubModule; ..]
493///     TEMPLATE_DEFINITIONS
494/// }
495/// ```
496///
497/// Then, `use MyModule` can be used in [`define_derive_deftly!`]
498/// (and, in another `define_derive_deftly_module!`).
499///
500/// TEMPLATE_DEFINITIONS may contain *only* `${define ..}` and `${defcond }`.
501/// (So it cannot define derives as-such, but it could contain
502/// the whole *body* of a derive as a `${define}`.)
503///
504/// This feature is [**beta**](doc_changelog/index.html#t:beta).
505/// It requires the `beta` cargo feature
506/// (but **not** any
507/// [`beta_deftly` template option](doc_reference/index.html#eo:beta_deftly)).
508///
509/// ## Scope and (lack of) namespacing
510///
511/// All names defined in a module are accessible within
512/// any tamplate or module that uses the module (directly or indirectly).
513///
514/// So there is no namespacing: names are "global".
515/// Like all `${define }` and `${defcond }`, scope is dynamic, not lexical.
516///
517/// Definitions in imported modules can be shadowed by subsequent definitions,
518/// including subsequent modules, and the importing template or module.
519///
520/// So definitions in general-purpose modules should usually
521/// have a namespace component within their name.
522/// This applies especially to "internal" definitions,
523/// which the module user is not intended to use or redefine.
524///
525/// ## Documentation expansions in `define_derive_deftly!`
526///
527/// In `define_derive_deftly!`, `DOCS` can contain both literal
528/// `#[doc]` attributes, and template expansions
529/// that expand to `#[doc]` attributes.
530/// The template expansions can refer to `${define}`s from imported modules.
531/// This allows re-use of documentation fragments.
532///
533/// The documentation for a *module* cannot contain expansions.
534///
535/// ## Placement of `use`
536///
537/// In `define_derive_deftly!` `use Module` appears in the preamble,
538/// before the name of the template being defined.
539/// `use` statements in the body become part of the expansion,
540/// so will refer to Rust modules.
541///
542/// In `define_derive_deftly_module!`,
543/// `use Module` appears within the body, before the definitions.
544/// (This reflects the fact that the imported module becomes part
545/// of the module being defined, and that imported definitions
546/// cannot be used in the module's documentation.)
547///
548/// ## Options
549///
550/// The only `OPTION` supported is `beta_deftly`.
551///
552/// Beta features can be used in a module, if `beta_deftly` is specified
553/// in the *module definition*.  A module which uses beta features
554/// can be imported by a template or module which does not itself
555/// specify `beta_deftly.`
556///
557/// `use` statements do not themselves require specifying `beta_deftly`;
558/// the cargo feature is sufficient.
559///
560/// ## Module definition macro `derive_deftly_module_MyModule`
561///
562/// The module's definitions are made into a `macro_rules` macro
563/// named `derive_deftly_module_MyModule`,
564/// which is referenced where the module is imported.
565///
566/// The module needs to be in Rust macro scope where it's `use`d.
567/// It does not need to be in scope for `derive` whose template uses it.
568/// (The module's definitions are bodily incorporated into the
569/// importing template (or module) macro_rules macro.)e
570///
571/// ### Semver implications of `export`:
572///
573/// Normally, template code present in different crates can be processed
574/// by different, perhaps semver-incompatible, versions of derive-deftly.
575///
576/// But, a whole derive must be processed by *one* version of
577/// derive-deftly.  Ie, when you `use` a module from another crate, that
578/// other crate's module's template text gets processed with *your*
579/// version of derive-deftly.
580///
581/// Additionally, the lack of namespacing provides ample opportunity
582/// for unintended interactions and uncontrolled dependencies on internals.
583///
584/// There are no features in derive-deftly for helping make
585/// an exported module with a stable API, whatever that means.
586#[cfg_attr(proc_macro, proc_macro)]
587pub fn define_derive_deftly_module(
588    input: proc_macro::TokenStream,
589) -> proc_macro::TokenStream {
590    wrap_macro_func(modules::define_derive_deftly_module, input)
591}
592
593/// Check semver compatibility, for a crate which exports macros
594///
595/// <!-- @dd-navbar macros . -->
596/// <!-- this line automatically maintained by update-navbars --><nav style="text-align: right; margin-bottom: 12px;">[ <em>docs: <a href="index.html">crate top-level</a> | <a href="index.html#overall-toc">overall toc, <strong>macros</strong></a> | <a href="doc_reference/index.html">template etc. reference</a> | <a href="https://diziet.pages.torproject.net/rust-derive-deftly/latest/guide/">guide/tutorial</a></em> ]</nav>
597///
598/// Causes a compilation error
599/// if and only if the specified version of `derive-deftly`
600/// is prior to the last *relevant change*,
601/// compared to the currently-running one.
602///
603/// A *relevant change* is one which has semver implications
604/// for the API of a crate which exports derive-deftly templates.
605///
606/// ## When and how to call this
607///
608/// If you export templates, with `define_derive_deftly! { export ... }`,
609/// call this macro too, once in your crate.
610///
611/// Pass it the version of `derive-deftly` that was current,
612/// when you last read the `derive-deftly` changelog
613/// and considered breaking changes.
614///
615/// (The argument must be a string literal, containing a
616/// 2- or 3-element version number.
617/// If the 3rd element is omitted, 0 is used.)
618///
619/// ## Guarantee
620///
621/// You can upgrade your derive-deftly version,
622/// even across a semver-breaking change to derive-deftly,
623/// without making any consequential update to your crate's own semver.
624///
625/// If a new version of derive-adhoc means *your* crate's
626/// API has semver-relevant changes, this macro will throw an error.
627/// (Of course that will only happen across semver-breaking
628/// updates of derive-deftly.)
629///
630/// (Exporting a *driver* struct for derivation in downstream crates,
631/// `#[derive_deftly_adhoc(export)]`, is not covered by this promise.)
632///
633/// ## Example
634///
635/// ```
636/// # use derive_deftly_macros as derive_deftly;
637/// derive_deftly::template_export_semver_check!("0.13.0");
638/// ```
639#[cfg_attr(proc_macro, proc_macro)]
640pub fn template_export_semver_check(
641    input: proc_macro::TokenStream,
642) -> proc_macro::TokenStream {
643    wrap_macro_func(semver::template_export_semver_check_func_macro, input)
644}