@@ -32,6 +32,12 @@ macro_rules! setup_input_struct {
32
32
// Indices for each field from 0..N -- must be unsuffixed (e.g., `0`, `1`).
33
33
field_indices: [ $( $field_index: tt) ,* ] ,
34
34
35
+ // Fields that are required (have no default value). Each item is the fields name and type.
36
+ required_fields: [ $( $required_field_id: ident $required_field_ty: ty) ,* ] ,
37
+
38
+ // Names for the field durability methods on the builder (typically `foo_durability`)
39
+ field_durability_ids: [ $( $field_durability_id: ident) ,* ] ,
40
+
35
41
// Number of fields
36
42
num_fields: $N: literal,
37
43
@@ -48,6 +54,7 @@ macro_rules! setup_input_struct {
48
54
$zalsa: ident,
49
55
$zalsa_struct: ident,
50
56
$Configuration: ident,
57
+ $Builder: ident,
51
58
$CACHE: ident,
52
59
$Db: ident,
53
60
]
@@ -82,13 +89,15 @@ macro_rules! setup_input_struct {
82
89
static CACHE : $zalsa:: IngredientCache <$zalsa_struct:: IngredientImpl <$Configuration>> =
83
90
$zalsa:: IngredientCache :: new( ) ;
84
91
CACHE . get_or_create( db, || {
85
- db. add_or_lookup_jar_by_type( & <$zalsa_struct:: JarImpl <$Configuration>>:: default ( ) )
92
+ db. zalsa ( ) . add_or_lookup_jar_by_type( & <$zalsa_struct:: JarImpl <$Configuration>>:: default ( ) )
86
93
} )
87
94
}
88
95
89
96
pub fn ingredient_mut( db: & mut dyn $zalsa:: Database ) -> ( & mut $zalsa_struct:: IngredientImpl <Self >, & mut $zalsa:: Runtime ) {
90
- let index = db. add_or_lookup_jar_by_type( & <$zalsa_struct:: JarImpl <$Configuration>>:: default ( ) ) ;
91
- let ( ingredient, runtime) = db. lookup_ingredient_mut( index) ;
97
+ let zalsa_mut = db. zalsa_mut( ) ;
98
+ let index = zalsa_mut. add_or_lookup_jar_by_type( & <$zalsa_struct:: JarImpl <$Configuration>>:: default ( ) ) ;
99
+ let current_revision = zalsa_mut. current_revision( ) ;
100
+ let ( ingredient, runtime) = zalsa_mut. lookup_ingredient_mut( index) ;
92
101
let ingredient = ingredient. assert_type_mut:: <$zalsa_struct:: IngredientImpl <Self >>( ) ;
93
102
( ingredient, runtime)
94
103
}
@@ -121,14 +130,18 @@ macro_rules! setup_input_struct {
121
130
}
122
131
123
132
impl $Struct {
124
- pub fn $new_fn<$Db>( db: & $Db, $( $field_id: $field_ty) ,* ) -> Self
133
+ #[ inline]
134
+ pub fn $new_fn<$Db>( db: & $Db, $( $required_field_id: $required_field_ty) ,* ) -> Self
125
135
where
126
136
// FIXME(rust-lang/rust#65991): The `db` argument *should* have the type `dyn Database`
127
137
$Db: ?Sized + salsa:: Database ,
128
138
{
129
- let current_revision = $zalsa:: current_revision( db) ;
130
- let stamps = $zalsa:: Array :: new( [ $zalsa:: stamp( current_revision, Default :: default ( ) ) ; $N] ) ;
131
- $Configuration:: ingredient( db. as_salsa_database( ) ) . new_input( ( $( $field_id, ) * ) , stamps)
139
+ Self :: builder( $( $required_field_id, ) * ) . new( db)
140
+ }
141
+
142
+ pub fn builder( $( $required_field_id: $required_field_ty) ,* ) -> <Self as $zalsa_struct:: HasBuilder >:: Builder
143
+ {
144
+ builder:: new_builder( $( $zalsa:: maybe_default!( $field_option, $field_ty, $field_id, ) ) ,* )
132
145
}
133
146
134
147
$(
@@ -137,8 +150,8 @@ macro_rules! setup_input_struct {
137
150
// FIXME(rust-lang/rust#65991): The `db` argument *should* have the type `dyn Database`
138
151
$Db: ?Sized + $zalsa:: Database ,
139
152
{
140
- let fields = $Configuration:: ingredient( db. as_salsa_database ( ) ) . field(
141
- db. as_salsa_database ( ) ,
153
+ let fields = $Configuration:: ingredient( db. as_dyn_database ( ) ) . field(
154
+ db. as_dyn_database ( ) ,
142
155
self ,
143
156
$field_index,
144
157
) ;
@@ -157,9 +170,9 @@ macro_rules! setup_input_struct {
157
170
// FIXME(rust-lang/rust#65991): The `db` argument *should* have the type `dyn Database`
158
171
$Db: ?Sized + $zalsa:: Database ,
159
172
{
160
- let ( ingredient, runtime ) = $Configuration:: ingredient_mut( db. as_salsa_database_mut ( ) ) ;
173
+ let ( ingredient, revision ) = $Configuration:: ingredient_mut( db. as_dyn_database_mut ( ) ) ;
161
174
$zalsa:: input:: SetterImpl :: new(
162
- runtime ,
175
+ revision ,
163
176
self ,
164
177
$field_index,
165
178
ingredient,
@@ -174,7 +187,7 @@ macro_rules! setup_input_struct {
174
187
// FIXME(rust-lang/rust#65991): The `db` argument *should* have the type `dyn Database`
175
188
$Db: ?Sized + salsa:: Database ,
176
189
{
177
- $Configuration:: ingredient( db. as_salsa_database ( ) ) . get_singleton_input( )
190
+ $Configuration:: ingredient( db. as_dyn_database ( ) ) . get_singleton_input( )
178
191
}
179
192
180
193
#[ track_caller]
@@ -204,6 +217,90 @@ macro_rules! setup_input_struct {
204
217
} )
205
218
}
206
219
}
220
+
221
+ impl $zalsa_struct:: HasBuilder for $Struct {
222
+ type Builder = builder:: $Builder;
223
+ }
224
+
225
+ // Implement `new` here instead of inside the builder module
226
+ // because $Configuration can't be named in `builder`.
227
+ impl builder:: $Builder {
228
+ /// Creates the new input with the set values.
229
+ #[ must_use]
230
+ pub fn new<$Db>( self , db: & $Db) -> $Struct
231
+ where
232
+ // FIXME(rust-lang/rust#65991): The `db` argument *should* have the type `dyn Database`
233
+ $Db: ?Sized + salsa:: Database
234
+ {
235
+ let current_revision = $zalsa:: current_revision( db) ;
236
+ let ingredient = $Configuration:: ingredient( db. as_dyn_database( ) ) ;
237
+ let ( fields, stamps) = builder:: builder_into_inner( self , current_revision) ;
238
+ ingredient. new_input( fields, stamps)
239
+ }
240
+ }
241
+
242
+ mod builder {
243
+ use super :: * ;
244
+
245
+ use salsa:: plumbing as $zalsa;
246
+ use $zalsa:: input as $zalsa_struct;
247
+
248
+ // These are standalone functions instead of methods on `Builder` to prevent
249
+ // that the enclosing module can call them.
250
+ pub ( super ) fn new_builder( $( $field_id: $field_ty) ,* ) -> $Builder {
251
+ $Builder {
252
+ fields: ( $( $field_id, ) * ) ,
253
+ durabilities: [ salsa:: Durability :: default ( ) ; $N] ,
254
+ }
255
+ }
256
+
257
+ pub ( super ) fn builder_into_inner( builder: $Builder, revision: $zalsa:: Revision ) -> ( ( $( $field_ty, ) * ) , $zalsa:: Array <$zalsa:: Stamp , $N>) {
258
+ let stamps = $zalsa:: Array :: new( [
259
+ $( $zalsa:: stamp( revision, builder. durabilities[ $field_index] ) ) ,*
260
+ ] ) ;
261
+
262
+ ( builder. fields, stamps)
263
+ }
264
+
265
+ #[ must_use]
266
+ pub struct $Builder {
267
+ /// The field values.
268
+ fields: ( $( $field_ty, ) * ) ,
269
+
270
+ /// The durabilities per field.
271
+ durabilities: [ salsa:: Durability ; $N] ,
272
+ }
273
+
274
+ impl $Builder {
275
+ /// Sets the durability of all fields.
276
+ ///
277
+ /// Overrides any previously set durabilities.
278
+ pub fn durability( mut self , durability: salsa:: Durability ) -> Self {
279
+ self . durabilities = [ durability; $N] ;
280
+ self
281
+ }
282
+
283
+ $( $zalsa:: maybe_default_tt! { $field_option =>
284
+ /// Sets the value of the field `$field_id`.
285
+ #[ must_use]
286
+ pub fn $field_id( mut self , value: $field_ty) -> Self
287
+ {
288
+ self . fields. $field_index = value;
289
+ self
290
+ }
291
+ } ) *
292
+
293
+ $(
294
+ /// Sets the durability for the field `$field_id`.
295
+ #[ must_use]
296
+ pub fn $field_durability_id( mut self , durability: salsa:: Durability ) -> Self
297
+ {
298
+ self . durabilities[ $field_index] = durability;
299
+ self
300
+ }
301
+ ) *
302
+ }
303
+ }
207
304
} ;
208
305
} ;
209
306
}
0 commit comments