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
//! Typestate and conversions for the prop builder the `Component` derive
//! generates.
//!
//! A call site in a template names only the props the author wrote, and it is
//! compiled in a different crate from the struct it is building — so it cannot
//! know which fields it left out, nor what those fields default to. The derive
//! knows both, and answers by generating a builder: one setter per field, and a
//! `__damask_build` that is reachable only once every *required* prop has been set.
//!
//! Nothing here is meant to be named by hand.
//!
//! # Which props may be skipped
//!
//! The builder carries one type parameter per required prop. Setting the prop
//! swaps that parameter from a marker the derive named after it to [`Set`], and
//! `__damask_build` requires every one of them to be [`Provided`]. A forgotten prop
//! is therefore a trait-bound error naming the prop, at the call site.
//!
//! A prop whose type is `Option<_>` needs no marker: leaving it out yields
//! `None`. Neither does any prop of a struct marked `#[component(default)]`,
//! whose builder starts from `Default::default()`.
//!
//! # Reaching an `Option` prop with a quoted value
//!
//! A setter takes its prop's type exactly, so that passing a value to it behaves
//! as assigning to the field did — `&Vec<T>` still coerces to a `&[T]` prop,
//! `count={2 + 8}` still infers to whatever integer the prop is. That leaves the
//! conversion a quoted value needs to happen on the *value* side, where the
//! prop's type is what the result is inferred from:
//!
//! ```text
//! detail: Option<String> detail="check the log" → Some("check the log")
//! detail="row {self.n}" → Some("row 3")
//! detail={self.detail} → passed through
//! (omitted) → None
//! ```
//!
//! An interpolated value is already a `String`, and `String` reaches both a
//! `String` prop and an `Option<String>` one through `Into`. Static text is the
//! case `Into` cannot serve — no `From<&'static str> for Option<String>` exists,
//! and adding one is not ours to do — so [`literal`] stands in for it.
/// A required prop that has been supplied.
;
/// Satisfied only by [`Set`] — the bound `__damask_build` places on each required
/// prop's marker.
///
/// The unsatisfied case is the diagnostic, so it is phrased here: the failing
/// type is the marker the derive named after the missing prop, and `{Self}`
/// puts that name in the message.
/// A string type buildable from *either* form a quoted attribute value arrives
/// in: static text, or an interpolated `String`.
///
/// Requiring both is not incidental. It is what makes [`literal`] resolve to
/// exactly one conversion, because it excludes — by construction rather than by
/// a list — the one type that would otherwise fit both of [`FromLiteral`]'s
/// impls: `&'static str`, which no `String` converts into.
///
/// Blanket-implemented, so `String`, `Cow<'static, str>`, `Box<str>`, `Rc<str>`,
/// `Arc<str>` and any type of your own with both conversions qualify.
/// The value is the prop's own type.
;
/// The value is what the prop's `Option` wraps.
;
/// How static attribute text becomes a prop, given the prop's type.
///
/// `M` is what keeps the two impls from overlapping — a prop is reached either
/// as itself or through its `Option` — and is always inferred.
// Reached only where the prop's `Option` wraps a type static text converts into
// *and* an interpolated one would — the pair that rules out `&'static str`,
// whose `Option` the impl above already serves through `From<T> for Option<T>`.
/// Convert the static text of a quoted attribute into the prop it is being
/// passed to. Emitted by the template lowering.
/// How the assembled text of an *interpolating* quoted attribute becomes a prop.
///
/// The same shape as [`FromLiteral`] and for the same reason: the value arrives
/// as a `String`, and the prop it is going to is either that type or an `Option`
/// of it. `M` is what keeps those two cases from overlapping.
// [`FromText`] rather than `From<String>` alone, and for the same reason
// `FromLiteral` asks for it: `Option<String>` converts from a `String` — that is
// `From<T> for Option<T>` — so a bound of `From<String>` here would let an
// `Option` prop match this impl as readily as the one below, and neither would
// win. No `Option` converts from static text, which is what tells the two apart.