Compare commits

...

2 Commits

Author SHA1 Message Date
Kim Morrison
1f24a87065 feat: add TraceData.headerContent? for pre-emoji header access
`withTraceNodeBefore` prepends `TraceResult.toEmoji` to the header
before storing it in the trace tree. This makes it difficult for
programmatic consumers to compare headers across trace runs, since
the same check gets different emoji prefixes depending on
success/failure.

Add `headerContent? : Option MessageData` to `TraceData` that stores
the original pre-emoji header content. This is purely additive — the
emoji-prefixed header continues to be stored as before, and all
existing trace output is unchanged.

Closes #13069

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 23:09:09 +00:00
Henrik Böving
fb1dc9112b perf: forward and backward borrow propagation is non-forced (#13066)
This PR changes the behavior of forward and backward projection
propagation in the context of user defined borrows. The reason to have
them be "forced" override (i.e. override user annotations as well) was
that a user annotated borrowed value can potentially flow into a
reset-reuse transitively through a projection and must thus have
accurate reference count. The reasons that this is no longer necessary
are:
1. Forward never had to be forced anyways, it can only affect the `z` in
`let z := oproj x i` which can't be annotated by a user
2. Backward is no longer necessary as the forward propagator for user
annotations prevents the reset-reuse insertion from working with values
that have user defined borrow annotations entirely.
2026-03-23 21:39:17 +00:00
4 changed files with 18 additions and 8 deletions

View File

@@ -243,13 +243,19 @@ def OwnReason.isForced (reason : OwnReason) : Bool :=
-- All of these reasons propagate through ABI decisions and can thus safely be ignored as they
-- will be accounted for by the reference counting pass.
| .constructorArg .. | .functionCallArg .. | .fvarCall .. | .partialApplication ..
| .jpArgPropagation .. => false
| .jpArgPropagation ..
-- forward propagation can never affect a user-annotated parameter
| .forwardProjectionProp ..
-- backward propagation on a user-annotated parameter is only necessary if the projected value
-- directly flows into a reset-reuse. However, the borrow annotation propagator ensures this
-- situation never arises
| .backwardProjectionProp .. => false
-- Results of functions and constructors are naturally owned.
| .constructorResult .. | .functionCallResult ..
-- We cannot pass borrowed values to reset or have borrow annotations destroy tail calls for
-- correctness reasons.
| .resetReuse .. | .tailCallPreservation .. | .jpTailCallPreservation .. | .ownedAnnotation
| .forwardProjectionProp .. | .backwardProjectionProp .. => true
| .resetReuse .. | .tailCallPreservation .. | .jpTailCallPreservation ..
| .ownedAnnotation => true
/--
Infer the borrowing annotations in a SCC through dataflow analysis.

View File

@@ -97,6 +97,12 @@ structure TraceData where
collapsed : Bool := true
/-- Optional tag shown in `trace.profiler.output` output after the trace class name. -/
tag : String := ""
/-- The trace header content without the leading status emoji.
`withTraceNodeBefore` prepends `TraceResult.toEmoji` to the stored header message;
this field provides the original pre-emoji content for programmatic consumers
that need to compare headers across trace runs (where the same check may have
different emoji prefixes depending on success/failure). -/
headerContent? : Option MessageData := none
/-- Structured message data. We use it for reporting errors, trace messages, etc. -/
inductive MessageData where

View File

@@ -418,8 +418,10 @@ where
modifyTraces (oldTraces ++ ·)
return ( MonadExcept.ofExcept res)
let result := res.toTraceResult
let headerContent := msg
let mut msg := m!"{result.toEmoji} {msg}"
let mut data : TraceData := { cls, collapsed, tag, result? := some result }
let mut data : TraceData := { cls, collapsed, tag, result? := some result,
headerContent? := some headerContent }
if trace.profiler.get opts then
data := { data with startTime := start, stopTime := stop }
addTraceNode oldTraces data ref msg

View File

@@ -139,8 +139,6 @@ structure Quad where
/-- Only traverses → parameter stays borrowed. -/
@[noinline] def measuree (xs : List Nat) : Nat := xs.length
/-
/--
trace: [Compiler.explicitRc] size: 22
def cascadeDemo @&t : tobj :=
@@ -257,5 +255,3 @@ def preserveTailCall (x : @&Prod Nat Nat) (a : Nat) : Nat :=
match a with
| 0 => x.fst
| a + 1 => preserveTailCall (mkNewProd x a) a
-/