Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions components/salsa-macro-rules/src/setup_input_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ macro_rules! setup_input_struct {
type $Configuration = $Struct;

impl $zalsa_struct::Configuration for $Configuration {
const LOCATION: $zalsa::Location = $zalsa::Location {
file: file!(),
line: line!(),
};
const DEBUG_NAME: &'static str = stringify!($Struct);
const FIELD_DEBUG_NAMES: &'static [&'static str] = &[$(stringify!($field_id)),*];
type Singleton = $zalsa::macro_if! {if $is_singleton {$zalsa::input::Singleton} else {$zalsa::input::NotSingleton}};
Expand Down
4 changes: 4 additions & 0 deletions components/salsa-macro-rules/src/setup_interned_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ macro_rules! setup_interned_struct {
}

impl salsa::plumbing::interned::Configuration for $StructWithStatic {
const LOCATION: $zalsa::Location = $zalsa::Location {
file: file!(),
line: line!(),
};
const DEBUG_NAME: &'static str = stringify!($Struct);
type Fields<'a> = $StructDataIdent<'a>;
type Struct<'db> = $Struct< $($db_lt_arg)? >;
Expand Down
8 changes: 8 additions & 0 deletions components/salsa-macro-rules/src/setup_tracked_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ macro_rules! setup_tracked_fn {
}

impl $zalsa::interned::Configuration for $Configuration {
const LOCATION: $zalsa::Location = $zalsa::Location {
file: file!(),
line: line!(),
};
const DEBUG_NAME: &'static str = "Configuration";

type Fields<$db_lt> = ($($input_ty),*);
Expand Down Expand Up @@ -177,6 +181,10 @@ macro_rules! setup_tracked_fn {
}

impl $zalsa::function::Configuration for $Configuration {
const LOCATION: $zalsa::Location = $zalsa::Location {
file: file!(),
line: line!(),
};
const DEBUG_NAME: &'static str = stringify!($fn_name);

type DbView = dyn $Db;
Expand Down
4 changes: 4 additions & 0 deletions components/salsa-macro-rules/src/setup_tracked_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ macro_rules! setup_tracked_struct {
type $Configuration = $Struct<'static>;

impl $zalsa_struct::Configuration for $Configuration {
const LOCATION: $zalsa::Location = $zalsa::Location {
file: file!(),
line: line!(),
};
const DEBUG_NAME: &'static str = stringify!($Struct);

const TRACKED_FIELD_NAMES: &'static [&'static str] = &[
Expand Down
15 changes: 10 additions & 5 deletions src/accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::sync::Arc;
use accumulated::{Accumulated, AnyAccumulated};

use crate::function::VerifyResult;
use crate::ingredient::{fmt_index, Ingredient, Jar};
use crate::ingredient::{Ingredient, Jar};
use crate::plumbing::IngredientIndices;
use crate::table::memo::MemoTableTypes;
use crate::zalsa::{IngredientIndex, Zalsa};
Expand Down Expand Up @@ -92,6 +92,15 @@ impl<A: Accumulator> IngredientImpl<A> {
}

impl<A: Accumulator> Ingredient for IngredientImpl<A> {
fn location(&self) -> &'static crate::ingredient::Location {
&const {
crate::ingredient::Location {
file: file!(),
line: line!(),
}
}
}

fn ingredient_index(&self) -> IngredientIndex {
self.index
}
Expand All @@ -105,10 +114,6 @@ impl<A: Accumulator> Ingredient for IngredientImpl<A> {
panic!("nothing should ever depend on an accumulator directly")
}

fn fmt_index(&self, index: crate::Id, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(A::DEBUG_NAME, index, fmt)
}

fn debug_name(&self) -> &'static str {
A::DEBUG_NAME
}
Expand Down
117 changes: 116 additions & 1 deletion src/active_query.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::ops::Not;
use std::sync::atomic::AtomicBool;
use std::{mem, ops};
use std::{fmt, mem, ops};

use crate::accumulator::accumulated_map::{
AccumulatedMap, AtomicInputAccumulatedValues, InputAccumulatedValues,
Expand Down Expand Up @@ -347,3 +347,118 @@ impl QueryStack {
self.stack[self.len].clear()
}
}

struct CapturedQuery {
database_key_index: DatabaseKeyIndex,
durability: Durability,
changed_at: Revision,
cycle_heads: CycleHeads,
iteration_count: u32,
}

impl fmt::Debug for CapturedQuery {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut debug_struct = f.debug_struct("CapturedQuery");
debug_struct
.field("database_key_index", &self.database_key_index)
.field("durability", &self.durability)
.field("changed_at", &self.changed_at);
if !self.cycle_heads.is_empty() {
debug_struct
.field("cycle_heads", &self.cycle_heads)
.field("iteration_count", &self.iteration_count);
}
debug_struct.finish()
}
}

pub struct Backtrace(Box<[CapturedQuery]>);

impl Backtrace {
pub fn capture() -> Option<Self> {
crate::with_attached_database(|db| {
db.zalsa_local().with_query_stack(|stack| {
Backtrace(
stack
.iter()
.rev()
.map(|query| CapturedQuery {
database_key_index: query.database_key_index,
durability: query.durability,
changed_at: query.changed_at,
cycle_heads: query.cycle_heads.clone(),
iteration_count: query.iteration_count,
})
.collect(),
)
})
})
}
}

impl fmt::Debug for Backtrace {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "Backtrace ")?;

let mut dbg = fmt.debug_list();

for frame in &self.0 {
dbg.entry(&frame);
}

dbg.finish()
}
}

impl fmt::Display for Backtrace {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(fmt, "query stacktrace:")?;
let full = fmt.alternate();
let indent = " ";
for (
idx,
&CapturedQuery {
database_key_index,
durability,
changed_at,
ref cycle_heads,
iteration_count,
},
) in self.0.iter().enumerate()
{
write!(fmt, "{idx:>4}: {database_key_index:?}")?;
if full {
write!(fmt, " -> ({changed_at:?}, {durability:#?}")?;
if !cycle_heads.is_empty() || iteration_count > 0 {
write!(fmt, ", iteration = {iteration_count:?}")?;
}
write!(fmt, ")")?;
}
writeln!(fmt)?;
crate::attach::with_attached_database(|db| {
let ingredient = db
.zalsa()
.lookup_ingredient(database_key_index.ingredient_index());
let loc = ingredient.location();
writeln!(fmt, "{indent}at {}:{}", loc.file, loc.line)?;
if !cycle_heads.is_empty() {
write!(fmt, "{indent}cycle heads: ")?;
for (idx, head) in cycle_heads.iter().enumerate() {
if idx != 0 {
write!(fmt, ", ")?;
}
write!(
fmt,
"{:?} -> {:?}",
head.database_key_index, head.iteration_count
)?;
}
writeln!(fmt)?;
}
Ok(())
})
.transpose()?;
}
Ok(())
}
}
14 changes: 11 additions & 3 deletions src/durability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@ pub struct Durability(DurabilityVal);

impl std::fmt::Debug for Durability {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Durability")
.field(&(self.0 as usize))
.finish()
if f.alternate() {
match self.0 {
DurabilityVal::Low => f.write_str("Durability::LOW"),
DurabilityVal::Medium => f.write_str("Durability::MEDIUM"),
DurabilityVal::High => f.write_str("Durability::HIGH"),
}
} else {
f.debug_tuple("Durability")
.field(&(self.0 as usize))
.finish()
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::accumulator::accumulated_map::{AccumulatedMap, InputAccumulatedValues
use crate::cycle::{CycleHeadKind, CycleRecoveryAction, CycleRecoveryStrategy};
use crate::function::delete::DeletedEntries;
use crate::function::sync::{ClaimResult, SyncTable};
use crate::ingredient::{fmt_index, Ingredient};
use crate::ingredient::Ingredient;
use crate::key::DatabaseKeyIndex;
use crate::plumbing::MemoIngredientMap;
use crate::salsa_struct::SalsaStructInDb;
Expand Down Expand Up @@ -37,6 +37,7 @@ pub type Memo<C> = memo::Memo<<C as Configuration>::Output<'static>>;

pub trait Configuration: Any {
const DEBUG_NAME: &'static str;
const LOCATION: crate::ingredient::Location;

/// The database that this function is associated with.
type DbView: ?Sized + crate::Database;
Expand Down Expand Up @@ -228,6 +229,10 @@ impl<C> Ingredient for IngredientImpl<C>
where
C: Configuration,
{
fn location(&self) -> &'static crate::ingredient::Location {
&C::LOCATION
}

fn ingredient_index(&self) -> IngredientIndex {
self.index
}
Expand Down Expand Up @@ -313,10 +318,6 @@ where
self.deleted_entries.clear();
}

fn fmt_index(&self, index: crate::Id, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(C::DEBUG_NAME, index, fmt)
}

fn debug_name(&self) -> &'static str {
C::DEBUG_NAME
}
Expand Down
10 changes: 9 additions & 1 deletion src/ingredient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,14 @@ pub trait Jar: Any {
Self: Sized;
}

pub struct Location {
pub file: &'static str,
pub line: u32,
}

pub trait Ingredient: Any + std::fmt::Debug + Send + Sync {
fn debug_name(&self) -> &'static str;
fn location(&self) -> &'static Location;

/// Has the value for `input` in this ingredient changed after `revision`?
///
Expand Down Expand Up @@ -136,7 +142,9 @@ pub trait Ingredient: Any + std::fmt::Debug + Send + Sync {

fn memo_table_types(&self) -> Arc<MemoTableTypes>;

fn fmt_index(&self, index: crate::Id, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
fn fmt_index(&self, index: crate::Id, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(self.debug_name(), index, fmt)
}
// Function ingredient methods

/// If this ingredient is a participant in a cycle, what is its cycle recovery strategy?
Expand Down
10 changes: 6 additions & 4 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use input_field::FieldIngredientImpl;

use crate::function::VerifyResult;
use crate::id::{AsId, FromId, FromIdWithDb};
use crate::ingredient::{fmt_index, Ingredient};
use crate::ingredient::Ingredient;
use crate::input::singleton::{Singleton, SingletonChoice};
use crate::key::DatabaseKeyIndex;
use crate::plumbing::{Jar, Stamp};
Expand All @@ -23,6 +23,7 @@ use crate::{Database, Durability, Id, Revision, Runtime};
pub trait Configuration: Any {
const DEBUG_NAME: &'static str;
const FIELD_DEBUG_NAMES: &'static [&'static str];
const LOCATION: crate::ingredient::Location;

/// The singleton state for this input if any.
type Singleton: SingletonChoice + Send + Sync;
Expand Down Expand Up @@ -199,6 +200,10 @@ impl<C: Configuration> IngredientImpl<C> {
}

impl<C: Configuration> Ingredient for IngredientImpl<C> {
fn location(&self) -> &'static crate::ingredient::Location {
&C::LOCATION
}

fn ingredient_index(&self) -> IngredientIndex {
self.ingredient_index
}
Expand All @@ -213,9 +218,6 @@ impl<C: Configuration> Ingredient for IngredientImpl<C> {
// Their *fields* are stored in function ingredients elsewhere.
VerifyResult::unchanged()
}
fn fmt_index(&self, index: Id, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(C::DEBUG_NAME, index, fmt)
}

fn debug_name(&self) -> &'static str {
C::DEBUG_NAME
Expand Down
4 changes: 4 additions & 0 deletions src/input/input_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ impl<C> Ingredient for FieldIngredientImpl<C>
where
C: Configuration,
{
fn location(&self) -> &'static crate::ingredient::Location {
&C::LOCATION
}

fn ingredient_index(&self) -> IngredientIndex {
self.index
}
Expand Down
12 changes: 7 additions & 5 deletions src/interned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::durability::Durability;
use crate::function::VerifyResult;
use crate::hash::FxDashMap;
use crate::id::{AsId, FromId};
use crate::ingredient::{fmt_index, Ingredient};
use crate::ingredient::Ingredient;
use crate::plumbing::{IngredientIndices, Jar};
use crate::revision::AtomicRevision;
use crate::table::memo::{MemoTable, MemoTableTypes};
Expand All @@ -24,6 +24,8 @@ use crate::zalsa::{IngredientIndex, Zalsa};
use crate::{Database, DatabaseKeyIndex, Event, EventKind, Id, Revision};

pub trait Configuration: Sized + 'static {
const LOCATION: crate::ingredient::Location;

const DEBUG_NAME: &'static str;

/// The fields of the struct being interned.
Expand Down Expand Up @@ -379,6 +381,10 @@ impl<C> Ingredient for IngredientImpl<C>
where
C: Configuration,
{
fn location(&self) -> &'static crate::ingredient::Location {
&C::LOCATION
}

fn ingredient_index(&self) -> IngredientIndex {
self.ingredient_index
}
Expand Down Expand Up @@ -416,10 +422,6 @@ where
VerifyResult::unchanged()
}

fn fmt_index(&self, index: crate::Id, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(C::DEBUG_NAME, index, fmt)
}

fn debug_name(&self) -> &'static str {
C::DEBUG_NAME
}
Expand Down
Loading