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