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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! The one place a spec id is derived.
//!
//! Every user-defined thing the spec names — a `#[contract_type]`, a
//! `#[contract_exception]`, a `#[derive(Event)]` — is named by the same id:
//! `CRATE@MAJOR::module::path::Name`. A bare ident cannot tell two of them
//! apart, since two crates, two modules of one crate, or two major versions of
//! one crate may each declare a `Transfer`, and a spec naming both simply
//! cannot say which is which.
//!
//! References resolve through the declaring item rather than by repeating a
//! string: a type reference reads `<T as ContractTypeName>::NAME`, and an
//! interface's `emits(...)` entry reads `<E as ContractEventSpec>::EVENT_DEF
//! .name`. So a reference follows whatever the thing it names calls itself,
//! and this module is the only thing that decides what that is.
use TokenStream;
use quote;
/// A const expression of type [`ContractSpecIdView<'static>`] holding the spec
/// id of an item declared at the expansion site under the name `declared`.
///
/// Every segment is emitted whole, from something already in hand at the
/// declaration -- nothing here takes a string apart. The module path is only
/// known where the item is declared and a macro cannot see it, so
/// `module_path!()` is emitted for the compiler to expand in place, and
/// `env!("CARGO_PKG_NAME")` likewise resolves in the declaring crate. Note
/// that the two spell the crate differently: `module_path!()` leads with the
/// Rust ident (underscored) while `CARGO_PKG_NAME` is the package name
/// (hyphenated), and the id carries both.
///
/// `version` is the identity version the item declares -- `#[contract_exception
/// (version = "...")]` -- or `None` to take the declaring crate's. It must be
/// whatever that item's other identity derivations use, or the same type ends
/// up with a selector pinned to one version and an id tracking another.
///
/// Where `None`, the version is read here: a proc macro reads the environment
/// of the rustc process compiling the crate the macro is *invoked* in, and
/// these macros are invoked on the item's own declaration, so that is the
/// declaring crate. (The same is not true of `#[contract]` on a trait impl,
/// which is why interface versions need an explicit override there.)
///
/// Emit this at a declaration only. Anywhere else `module_path!()` names the
/// wrong module and the id is a lie.
/// The one place an id's shape is written down. Callers supply the module
/// path as tokens because they do not agree on it: a declaration takes
/// `module_path!()`, while a crate's own identity must not vary by module.
/// The declarer id a bare impl or free-function contract records for its
/// interface: the crate itself (see `SpecInterfaceAnchor::declared_by`).
/// `version` is as for [`spec_id_tokens`].
///
/// Both path segments are empty, so the id is exactly (crate, major). One
/// crate may spread an interface over several blocks, so a `module_path!()`
/// here would make two blocks in different modules look like two declarers
/// and get the crate rejected for spreading its own interface. The empty
/// `declared` also keeps this id from ever colliding with a trait's, which
/// always names the trait.
/// The major version, by the same rule interface versions use: the leftmost
/// non-zero component, so semver-compatible releases share an id and only a
/// breaking release changes it. `None` takes the declaring crate's version.