Salsa In More Depth (2019.01)
#[salsa::query_group(InputsStorage)]
pub trait MyQueryGroup {
  #[salsa::input] // `set_manifest` is auto-generated
  fn manifest(&self) -> Manifest;

  #[salsa::input] // `set_source_text` is auto-generated
  fn source_text(&self, name: String) -> String;

  fn ast(&self, name: String) -> Ast;

  fn whole_program_ast(&self) -> Ast;
}

fn ast(db: &dyn MyQueryGroup, name: String) -> Ast {
  let source_text: String = db.source_text(name);
  
  // do the actual parser on `source_text`
  
  return ast;
}

fn whole_program_ast(db: &dyn MyQueryGroup, name: String) -> Ast {
  let mut ast = Ast::default();
  for source_file in db.manifest() {
    let ast_source_file = db.ast(name);
    ast.extend(ast_source_file);
  }
  return ast;
}


Database storage

  • Database has internally a shared storage with:
  • revision (R0)
  • one struct per query group
  • one map per query
  • db.set_input_file("a.rs", "fn main() { }")
  • storing into the input_file map with the key a.rs and the value given
  • store the (new) revision R1
  • increment the revision (R1)
  • db.set_input_file("b.rs", "fn foo() { }")
  • go to revision R2
  • setters are &mut self
  • db.type_check() // &self

Query storage

  • Input query:
  • (Key) → (Value, Revision)