Skip to main content

interned

Attribute Macro interned 

Source
#[interned]
Expand description

Defines an interned struct.

All fields jointly determine the struct’s identity. Within a revision, every occurrence of equal field values maps to the same compact handle. Interned fields are immutable.

The annotated item must be a struct with named fields. It may declare one lifetime parameter, which Salsa treats as the database lifetime, but no type or const parameters. The generated struct is Copy and provides a constructor and field getters. Every field type must implement Clone + Eq + Hash + Send + Sync. A field whose type is unconditionally 'static is accepted directly; any other field must implement salsa::SalsaValue.

See interned structs in the salsa crate documentation for their identity and lifecycle.

§Options

Options are comma-separated inside the attribute:

  • constructor = IDENT renames the generated constructor from new to IDENT.
  • debug implements Debug using the field values when a database is attached to the current thread. The generated default_debug_fmt method can also be called from a manual Debug implementation.
  • revisions = EXPR sets the minimum number of active revisions an unused value is retained before its slot may be reused. The default is 3. The value must be nonzero; usize::MAX disables reuse.
  • heap_size = PATH records heap use for Salsa’s unstable memory-usage reporting. PATH must accept a reference to the tuple of all fields and return its heap allocation size in bytes.
  • persist enables persistent caching when Salsa’s persistence feature is enabled. Fields are serialized as a tuple with serde by default.
  • persist(serialize = PATH, deserialize = PATH) enables persistence with custom tuple serialization functions. Either path may be omitted to use the corresponding serde implementation.

§Legacy adapters

These options exist to adapt older code or external representations to Salsa. New code should use the default lifetime-bearing struct and salsa::Id, and its field types should implement salsa::SalsaValue.

  • id = PATH uses PATH as a legacy ID adapter instead of salsa::Id. The custom type must implement Copy + Clone + PartialEq + Eq + Hash as well as salsa::plumbing::AsId and salsa::plumbing::FromId.
  • Unsafe: unsafe(no_lifetime) is strongly discouraged. It adapts code that cannot carry the database lifetime by generating a struct without one. This bypasses the compile-time guarantee that an interned handle cannot outlive its database. It must be combined with revisions = usize::MAX so that interned slots are never reclaimed or reused.
  • Unsafe: unsafe(non_salsa_values) is strongly discouraged. It adapts field types that do not implement salsa::SalsaValue by suppressing the generated checks. The caller becomes responsible for ensuring retained values remain valid across revisions. Prefer adapting only the affected field with #[salsa_value(unsafe(prove_safe_to_retain_manually))].

§Field attributes

Every field generates a getter with the same name and visibility as the field. These helper attributes configure that getter:

  • #[returns(MODE)] selects how the getter returns the field. ref (the default) returns &FieldTy; clone returns an owned FieldTy using Clone; copy returns an owned FieldTy using Copy; and deref uses Deref to return &<FieldTy as Deref>::Target. as_ref and as_deref use salsa::SalsaAsRef and salsa::SalsaAsDeref to return borrowed forms such as Option<&T> and Option<&T::Target>. Every borrowed result is tied to the database borrow.
  • #[get(IDENT)] renames the generated getter.
  • Unsafe: #[salsa_value(unsafe(prove(Predicate, ...)))] replaces the retention check with predicates that must hold for every database lifetime. The compiler verifies the predicates, but the caller must ensure they imply that Salsa can retain the field and expose it with a later database lifetime.
  • Unsafe: #[salsa_value(unsafe(prove_safe_to_retain_manually))] suppresses the retention check for this field without adding predicates. The caller must ensure Salsa can retain the field and expose it with a later database lifetime.

Other attributes, including documentation and lint attributes, are copied to the generated getter.

§Example

#[salsa::interned(debug)]
struct Name<'db> {
    #[returns(deref)]
    text: String,
    #[returns(copy)]
    #[get(disambiguator)]
    index: u32,
}