Skip to content

Commit

Permalink
Merge pull request #543 from MichaReiser/input-builder
Browse files Browse the repository at this point in the history
Introduce `Input::builder` API
  • Loading branch information
MichaReiser authored Aug 6, 2024
2 parents d6df21f + 547663f commit 4c8e52a
Show file tree
Hide file tree
Showing 15 changed files with 353 additions and 12 deletions.
1 change: 1 addition & 0 deletions components/salsa-macro-rules/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
mod macro_if;
mod maybe_backdate;
mod maybe_clone;
mod maybe_default;
mod setup_accumulator_impl;
mod setup_input_struct;
mod setup_interned_struct;
Expand Down
4 changes: 2 additions & 2 deletions components/salsa-macro-rules/src/maybe_backdate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#[macro_export]
macro_rules! maybe_backdate {
(
($maybe_clone:ident, no_backdate),
($maybe_clone:ident, no_backdate, $maybe_default:ident),
$field_ty:ty,
$old_field_place:expr,
$new_field_place:expr,
Expand All @@ -20,7 +20,7 @@ macro_rules! maybe_backdate {
};

(
($maybe_clone:ident, backdate),
($maybe_clone:ident, backdate, $maybe_default:ident),
$field_ty:ty,
$old_field_place:expr,
$new_field_place:expr,
Expand Down
8 changes: 4 additions & 4 deletions components/salsa-macro-rules/src/maybe_clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
#[macro_export]
macro_rules! maybe_clone {
(
(no_clone, $maybe_backdate:ident),
(no_clone, $maybe_backdate:ident, $maybe_default:ident),
$field_ty:ty,
$field_ref_expr:expr,
) => {
$field_ref_expr
};

(
(clone, $maybe_backdate:ident),
(clone, $maybe_backdate:ident, $maybe_default:ident),
$field_ty:ty,
$field_ref_expr:expr,
) => {
Expand All @@ -23,15 +23,15 @@ macro_rules! maybe_clone {
#[macro_export]
macro_rules! maybe_cloned_ty {
(
(no_clone, $maybe_backdate:ident),
(no_clone, $maybe_backdate:ident, $maybe_default:ident),
$db_lt:lifetime,
$field_ty:ty
) => {
& $db_lt $field_ty
};

(
(clone, $maybe_backdate:ident),
(clone, $maybe_backdate:ident, $maybe_default:ident),
$db_lt:lifetime,
$field_ty:ty
) => {
Expand Down
32 changes: 32 additions & 0 deletions components/salsa-macro-rules/src/maybe_default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// Generate either `field_ref_expr` or `field_ty::default`
///
/// Used when generating an input's builder.
#[macro_export]
macro_rules! maybe_default {
(
($maybe_clone:ident, $maybe_backdate:ident, default),
$field_ty:ty,
$field_ref_expr:expr,
) => {
<$field_ty>::default()
};

(
($maybe_clone:ident, $maybe_backdate:ident, required),
$field_ty:ty,
$field_ref_expr:expr,
) => {
$field_ref_expr
};
}

#[macro_export]
macro_rules! maybe_default_tt {
(($maybe_clone:ident, $maybe_backdate:ident, default) => $($t:tt)*) => {
$($t)*
};

(($maybe_clone:ident, $maybe_backdate:ident, required) => $($t:tt)*) => {

};
}
103 changes: 99 additions & 4 deletions components/salsa-macro-rules/src/setup_input_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ macro_rules! setup_input_struct {
// Indices for each field from 0..N -- must be unsuffixed (e.g., `0`, `1`).
field_indices: [$($field_index:tt),*],

// Fields that are required (have no default value). Each item is the fields name and type.
required_fields: [$($required_field_id:ident $required_field_ty:ty),*],

// Names for the field durability methods on the builder (typically `foo_durability`)
field_durability_ids: [$($field_durability_id:ident),*],

// Number of fields
num_fields: $N:literal,

Expand All @@ -48,6 +54,7 @@ macro_rules! setup_input_struct {
$zalsa:ident,
$zalsa_struct:ident,
$Configuration:ident,
$Builder:ident,
$CACHE:ident,
$Db:ident,
]
Expand Down Expand Up @@ -123,14 +130,18 @@ macro_rules! setup_input_struct {
}

impl $Struct {
pub fn $new_fn<$Db>(db: &$Db, $($field_id: $field_ty),*) -> Self
#[inline]
pub fn $new_fn<$Db>(db: &$Db, $($required_field_id: $required_field_ty),*) -> Self
where
// FIXME(rust-lang/rust#65991): The `db` argument *should* have the type `dyn Database`
$Db: ?Sized + salsa::Database,
{
let current_revision = $zalsa::current_revision(db);
let stamps = $zalsa::Array::new([$zalsa::stamp(current_revision, Default::default()); $N]);
$Configuration::ingredient(db.as_dyn_database()).new_input(($($field_id,)*), stamps)
Self::builder($($required_field_id,)*).new(db)
}

pub fn builder($($required_field_id: $required_field_ty),*) -> <Self as $zalsa_struct::HasBuilder>::Builder
{
builder::new_builder($($zalsa::maybe_default!($field_option, $field_ty, $field_id,)),*)
}

$(
Expand Down Expand Up @@ -206,6 +217,90 @@ macro_rules! setup_input_struct {
})
}
}

impl $zalsa_struct::HasBuilder for $Struct {
type Builder = builder::$Builder;
}

// Implement `new` here instead of inside the builder module
// because $Configuration can't be named in `builder`.
impl builder::$Builder {
/// Creates the new input with the set values.
#[must_use]
pub fn new<$Db>(self, db: &$Db) -> $Struct
where
// FIXME(rust-lang/rust#65991): The `db` argument *should* have the type `dyn Database`
$Db: ?Sized + salsa::Database
{
let current_revision = $zalsa::current_revision(db);
let ingredient = $Configuration::ingredient(db.as_dyn_database());
let (fields, stamps) = builder::builder_into_inner(self, current_revision);
ingredient.new_input(fields, stamps)
}
}

mod builder {
use super::*;

use salsa::plumbing as $zalsa;
use $zalsa::input as $zalsa_struct;

// These are standalone functions instead of methods on `Builder` to prevent
// that the enclosing module can call them.
pub(super) fn new_builder($($field_id: $field_ty),*) -> $Builder {
$Builder {
fields: ($($field_id,)*),
durabilities: [salsa::Durability::default(); $N],
}
}

pub(super) fn builder_into_inner(builder: $Builder, revision: $zalsa::Revision) -> (($($field_ty,)*), $zalsa::Array<$zalsa::Stamp, $N>) {
let stamps = $zalsa::Array::new([
$($zalsa::stamp(revision, builder.durabilities[$field_index])),*
]);

(builder.fields, stamps)
}

#[must_use]
pub struct $Builder {
/// The field values.
fields: ($($field_ty,)*),

/// The durabilities per field.
durabilities: [salsa::Durability; $N],
}

impl $Builder {
/// Sets the durability of all fields.
///
/// Overrides any previously set durabilities.
pub fn durability(mut self, durability: salsa::Durability) -> Self {
self.durabilities = [durability; $N];
self
}

$($zalsa::maybe_default_tt! { $field_option =>
/// Sets the value of the field `$field_id`.
#[must_use]
pub fn $field_id(mut self, value: $field_ty) -> Self
{
self.fields.$field_index = value;
self
}
})*

$(
/// Sets the durability for the field `$field_id`.
#[must_use]
pub fn $field_durability_id(mut self, durability: salsa::Durability) -> Self
{
self.durabilities[$field_index] = durability;
self
}
)*
}
}
};
};
}
1 change: 0 additions & 1 deletion components/salsa-macro-rules/src/setup_struct_fn.rs

This file was deleted.

8 changes: 8 additions & 0 deletions components/salsa-macros/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ impl SalsaStructAllowedOptions for InputStruct {
const ALLOW_ID: bool = false;

const HAS_LIFETIME: bool = false;

const ALLOW_DEFAULT: bool = true;
}

struct Macro {
Expand All @@ -85,14 +87,17 @@ impl Macro {
let field_vis = salsa_struct.field_vis();
let field_getter_ids = salsa_struct.field_getter_ids();
let field_setter_ids = salsa_struct.field_setter_ids();
let required_fields = salsa_struct.required_fields();
let field_options = salsa_struct.field_options();
let field_tys = salsa_struct.field_tys();
let field_durability_ids = salsa_struct.field_durability_ids();
let is_singleton = self.args.singleton.is_some();
let generate_debug_impl = salsa_struct.generate_debug_impl();

let zalsa = self.hygiene.ident("zalsa");
let zalsa_struct = self.hygiene.ident("zalsa_struct");
let Configuration = self.hygiene.ident("Configuration");
let Builder = self.hygiene.ident("Builder");
let CACHE = self.hygiene.ident("CACHE");
let Db = self.hygiene.ident("Db");

Expand All @@ -110,13 +115,16 @@ impl Macro {
field_setters: [#(#field_vis #field_setter_ids),*],
field_tys: [#(#field_tys),*],
field_indices: [#(#field_indices),*],
required_fields: [#(#required_fields),*],
field_durability_ids: [#(#field_durability_ids),*],
num_fields: #num_fields,
is_singleton: #is_singleton,
generate_debug_impl: #generate_debug_impl,
unused_names: [
#zalsa,
#zalsa_struct,
#Configuration,
#Builder,
#CACHE,
#Db,
]
Expand Down
2 changes: 2 additions & 0 deletions components/salsa-macros/src/interned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ impl SalsaStructAllowedOptions for InternedStruct {
const ALLOW_ID: bool = false;

const HAS_LIFETIME: bool = true;

const ALLOW_DEFAULT: bool = false;
}

struct Macro {
Expand Down
Loading

0 comments on commit 4c8e52a

Please sign in to comment.