9797//! `Outer::ACCOUNT.field(EncryptedAccount::ADDRESS).field(EncryptedAddress::STREET)`.
9898//! The inner record must list no scope of its own, stored or supplied: a
9999//! query of it would take two scopes, and `field` takes a marker whose
100- //! scope is [`NoScope`].
100+ //! scope is [`NoScope`] ([`NestedScope`]) .
101101//!
102102//! # The type a query takes
103103//!
109109//! type alone ([`Takes`]), and the derive checks it against the plaintext
110110//! struct's field, which is that type or an `Option` of it. An order marker
111111//! fixes the type without the attribute, since `OreTerm<S>` names it.
112+ //!
113+ //! A nullable field's marker without the attribute also takes an `Option`,
114+ //! since the equality index accepts one. `NICK.eq(&None::<String>)`
115+ //! compiles and derives a term that no stored row holds: a `None` field
116+ //! stores no term, and a marker query is never `IS NULL`. Mark the field
117+ //! `#[stash(query = String)]` to refuse it.
112118use std:: marker:: PhantomData ;
113119
114120use stack_kms:: MaybeSend ;
@@ -158,7 +164,7 @@ impl<W: Place, T, C, P> std::fmt::Debug for Marker<W, T, C, P> {
158164 . field ( "name" , & self . name )
159165 . field ( "scope" , & self . scope )
160166 . field ( "identity" , & self . identity )
161- . field ( "within" , & self . place . outers ( ) )
167+ . field ( "within" , & outers ( & self . place ) )
162168 . finish_non_exhaustive ( )
163169 }
164170}
@@ -221,8 +227,12 @@ impl<W: Place, T, C, P> Marker<W, T, C, P> {
221227 ///
222228 /// `inner` must be a marker of the record `T` this field holds, so a
223229 /// marker of another record does not compile. That record must list no
224- /// scope of its own ([`NoScope`]): a query of it would take two scopes.
225- pub fn field < U , Q > ( self , inner : Marker < Root < T > , U , NoScope , Q > ) -> Marker < Nested < W > , U , C , Q > {
230+ /// scope of its own ([`NestedScope`]): a query of it would take two
231+ /// scopes.
232+ pub fn field < U , C2 : NestedScope , Q > (
233+ self ,
234+ inner : Marker < Root < T > , U , C2 , Q > ,
235+ ) -> Marker < Nested < W > , U , C , Q > {
226236 Marker {
227237 name : inner. name ,
228238 scope : inner. scope ,
@@ -246,7 +256,7 @@ impl<W: Place, T, C, P> Marker<W, T, C, P> {
246256 {
247257 MarkedQuery {
248258 label : self . label ( ) ,
249- outers : self . place . outers ( ) ,
259+ outers : outers ( & self . place ) ,
250260 value : Some ( value) ,
251261 wipe,
252262 scopes : DeclaredContext :: default ( ) ,
@@ -263,16 +273,40 @@ fn label(scope: &'static str, identity: &'static str) -> Label {
263273 } )
264274}
265275
266- /// Where a marked field sits: [`Root`] for a field of the record a marker
267- /// was emitted for, [`Nested`] for one reached through a record field.
268- /// Sealed: [`Marker::field`] makes the one, the derive the other.
276+ /// The labels of the record fields that hold a field at `place`,
277+ /// outermost first: empty for a field of the record itself.
278+ fn outers ( place : & impl Place ) -> Vec < Label > {
279+ let mut outers = Vec :: new ( ) ;
280+ place. push_outers ( & mut outers) ;
281+ outers
282+ }
283+
284+ /// The scope a record lists for its own caller, where the record is the
285+ /// type of another record's field: [`NoScope`] alone. A query of a field of
286+ /// a record with its own scope would take that scope and the outer
287+ /// record's.
288+ #[ diagnostic:: on_unimplemented(
289+ message = "`field` takes a marker of a record that lists no scope of its own, not `{Self}`" ,
290+ label = "a query of this field would take two scopes" ,
291+ note = "the inner record's fields are reached by `field` only when the inner record has no `scope(..)` of its own, stored or supplied"
292+ ) ]
293+ pub trait NestedScope : nested_sealed:: Sealed { }
294+ mod nested_sealed {
295+ pub trait Sealed { }
296+ }
297+ impl nested_sealed:: Sealed for NoScope { }
298+ impl NestedScope for NoScope { }
299+
300+ /// Where a marked field sits: [`Root`] for a field of the record the
301+ /// derive emitted the marker for, [`Nested`] for one that
302+ /// [`Marker::field`] reached through a record field. Sealed.
269303pub trait Place : Copy + place_sealed:: Sealed {
270304 /// The outermost record's contexts, narrowed to the record that holds
271305 /// the field.
272306 fn narrow ( & self , contexts : Contexts ) -> Contexts ;
273- /// The labels of the record fields that hold the field, outermost
274- /// first: empty for a field of the record itself.
275- fn outers ( & self ) -> Vec < Label > ;
307+ /// Push the labels of the record fields that hold the field, outermost
308+ /// first: none for a field of the record itself.
309+ fn push_outers ( & self , outers : & mut Vec < Label > ) ;
276310}
277311mod place_sealed {
278312 pub trait Sealed { }
@@ -292,9 +326,7 @@ impl<R> Place for Root<R> {
292326 fn narrow ( & self , contexts : Contexts ) -> Contexts {
293327 contexts
294328 }
295- fn outers ( & self ) -> Vec < Label > {
296- Vec :: new ( )
297- }
329+ fn push_outers ( & self , _: & mut Vec < Label > ) { }
298330}
299331
300332/// A field of a record that is itself the field named here, which sits at
@@ -311,38 +343,37 @@ impl<W: Place> Place for Nested<W> {
311343 fn narrow ( & self , contexts : Contexts ) -> Contexts {
312344 self . outer . narrow ( contexts) . narrowed ( self . name )
313345 }
314- fn outers ( & self ) -> Vec < Label > {
315- let mut outers = self . outer . outers ( ) ;
346+ fn push_outers ( & self , outers : & mut Vec < Label > ) {
347+ self . outer . push_outers ( outers ) ;
316348 outers. push ( label ( self . scope , self . identity ) ) ;
317- outers
318349 }
319350}
320351
321352/// The type a marker's queries take: [`TakesAny`], any type the field's
322353/// index accepts, or [`Takes<V>`], `V` alone. A field marked
323- /// `#[stash(query = V)]` is `Takes<V>`.
324- #[ diagnostic:: on_unimplemented(
325- message = "this field's queries take `{Self}`, not `{V}`" ,
326- label = "a query of another type matches nothing" ,
327- note = "the record states the field's query type with `#[stash(query = ..)]`"
328- ) ]
329- pub trait QueryValue < V > : value_sealed:: Sealed { }
354+ /// `#[stash(query = V)]` is `Takes<V>`. Sealed, for every `V`.
355+ pub trait QueryValue < V > : value_sealed:: Sealed < V > { }
330356mod value_sealed {
331- pub trait Sealed { }
357+ pub trait Sealed < V > { }
332358}
333359
334360/// A marker whose queries take any type the field's index accepts: the
335361/// default, where the record does not state the field's query type.
336362#[ derive( Debug ) ]
337363pub enum TakesAny { }
338- impl value_sealed:: Sealed for TakesAny { }
364+ impl < V > value_sealed:: Sealed < V > for TakesAny { }
339365impl < V > QueryValue < V > for TakesAny { }
340366
341367/// A marker whose queries take `V` alone: a field marked
342368/// `#[stash(query = V)]`. A query value is copied from its borrowed form,
343369/// so a marker of `Takes<String>` accepts `"ada"` as well as a `&String`.
370+ ///
371+ /// A value of another type is refused at compile time. Since `V` is the one
372+ /// type the marker accepts, the compiler reports it as a mismatch of the
373+ /// value's owned form: "type mismatch resolving `<u64 as ToOwned>::Owned
374+ /// == String`".
344375pub struct Takes < V > ( PhantomData < fn ( ) -> V > ) ;
345- impl < V > value_sealed:: Sealed for Takes < V > { }
376+ impl < V > value_sealed:: Sealed < V > for Takes < V > { }
346377impl < V > QueryValue < V > for Takes < V > { }
347378
348379/// A plaintext field whose queries take `V`: `V` itself, or `Option<V>`
0 commit comments