diff --git a/packages/effect/src/Cause.ts b/packages/effect/src/Cause.ts index 8632dd4fe8..1873303505 100644 --- a/packages/effect/src/Cause.ts +++ b/packages/effect/src/Cause.ts @@ -1055,9 +1055,3 @@ export const FailureSpan: Context.Tag<"FailureSpan", Span> = internal.FailureSpa * @category annotations */ export const InterruptorSpan: Context.Tag<"InterruptorSpan", Span> = internal.InterruptorSpan - -/** - * @since 3.8.0 - * @category annotations - */ -export const withAnnotationPropagationDisabled: (f: () => A) => A = internal.withAnnotationPropagationDisabled diff --git a/packages/effect/src/internal/cause.ts b/packages/effect/src/internal/cause.ts index 04080bfce2..c7bdb24718 100644 --- a/packages/effect/src/internal/cause.ts +++ b/packages/effect/src/internal/cause.ts @@ -94,7 +94,7 @@ export const fail = (error: E): Cause.Cause => { const o = Object.create(proto) o._tag = OpCodes.OP_FAIL o.error = error - return rehydrateAnnotations(o, error) + return o } /** @internal */ @@ -102,7 +102,7 @@ export const die = (defect: unknown): Cause.Cause => { const o = Object.create(proto) o._tag = OpCodes.OP_DIE o.defect = defect - return rehydrateAnnotations(o, defect) + return o } /** @internal */ @@ -987,95 +987,91 @@ export const reduce = dual< export const reduceWithContext = dual< (context: C, reducer: Cause.CauseReducer) => (self: Cause.Cause) => Z, (self: Cause.Cause, context: C, reducer: Cause.CauseReducer) => Z ->( - 3, - (self: Cause.Cause, context: C, reducer: Cause.CauseReducer) => - withAnnotationPropagationDisabled(() => { - let annotations = Context.empty() - const input: Array> = [self] - const output: Array> = [] - while (input.length > 0) { - const cause = input.pop()! - switch (cause._tag) { - case OpCodes.OP_EMPTY: { - output.push(Either.right(reducer.emptyCase(context, annotations))) - break - } - case OpCodes.OP_FAIL: { - output.push(Either.right(reducer.failCase(context, cause.error, annotations))) - break - } - case OpCodes.OP_DIE: { - output.push(Either.right(reducer.dieCase(context, cause.defect, annotations))) - break - } - case OpCodes.OP_INTERRUPT: { - output.push(Either.right(reducer.interruptCase(context, cause.fiberId, annotations))) - break - } - case OpCodes.OP_SEQUENTIAL: { - input.push(cause.right) - input.push(cause.left) - output.push(Either.left({ _tag: OP_SEQUENTIAL_CASE, annotations })) - break - } - case OpCodes.OP_PARALLEL: { - input.push(cause.right) - input.push(cause.left) - output.push(Either.left({ _tag: OP_PARALLEL_CASE, annotations })) - break - } - case OpCodes.OP_ANNOTATED: { - input.push(cause.cause) - output.push(Either.left({ _tag: OP_ANNOTATED_CASE, context: cause.context, annotations })) - annotations = Context.merge(annotations, cause.context) +>(3, (self: Cause.Cause, context: C, reducer: Cause.CauseReducer) => { + let annotations = Context.empty() + const input: Array> = [self] + const output: Array> = [] + while (input.length > 0) { + const cause = input.pop()! + switch (cause._tag) { + case OpCodes.OP_EMPTY: { + output.push(Either.right(reducer.emptyCase(context, annotations))) + break + } + case OpCodes.OP_FAIL: { + output.push(Either.right(reducer.failCase(context, cause.error, annotations))) + break + } + case OpCodes.OP_DIE: { + output.push(Either.right(reducer.dieCase(context, cause.defect, annotations))) + break + } + case OpCodes.OP_INTERRUPT: { + output.push(Either.right(reducer.interruptCase(context, cause.fiberId, annotations))) + break + } + case OpCodes.OP_SEQUENTIAL: { + input.push(cause.right) + input.push(cause.left) + output.push(Either.left({ _tag: OP_SEQUENTIAL_CASE, annotations })) + break + } + case OpCodes.OP_PARALLEL: { + input.push(cause.right) + input.push(cause.left) + output.push(Either.left({ _tag: OP_PARALLEL_CASE, annotations })) + break + } + case OpCodes.OP_ANNOTATED: { + input.push(cause.cause) + output.push(Either.left({ _tag: OP_ANNOTATED_CASE, context: cause.context, annotations })) + annotations = Context.merge(annotations, cause.context) + break + } + } + } + const accumulator: Array = [] + while (output.length > 0) { + const either = output.pop()! + switch (either._tag) { + case "Left": { + switch (either.left._tag) { + case OP_SEQUENTIAL_CASE: { + const left = accumulator.pop()! + const right = accumulator.pop()! + const value = reducer.sequentialCase(context, left, right, either.left.annotations) + accumulator.push(value) break } - } - } - const accumulator: Array = [] - while (output.length > 0) { - const either = output.pop()! - switch (either._tag) { - case "Left": { - switch (either.left._tag) { - case OP_SEQUENTIAL_CASE: { - const left = accumulator.pop()! - const right = accumulator.pop()! - const value = reducer.sequentialCase(context, left, right, either.left.annotations) - accumulator.push(value) - break - } - case OP_PARALLEL_CASE: { - const left = accumulator.pop()! - const right = accumulator.pop()! - const value = reducer.parallelCase(context, left, right, either.left.annotations) - accumulator.push(value) - break - } - case OP_ANNOTATED_CASE: { - const out = accumulator.pop()! - const value = reducer.annotatedCase(context, out, either.left.context, either.left.annotations) - accumulator.push(value) - break - } - } + case OP_PARALLEL_CASE: { + const left = accumulator.pop()! + const right = accumulator.pop()! + const value = reducer.parallelCase(context, left, right, either.left.annotations) + accumulator.push(value) break } - case "Right": { - accumulator.push(either.right) + case OP_ANNOTATED_CASE: { + const out = accumulator.pop()! + const value = reducer.annotatedCase(context, out, either.left.context, either.left.annotations) + accumulator.push(value) break } } + break } - if (accumulator.length === 0) { - throw new Error( - "BUG: Cause.reduceWithContext - please report an issue at https://github.com/Effect-TS/effect/issues" - ) + case "Right": { + accumulator.push(either.right) + break } - return accumulator.pop()! - }) -) + } + } + if (accumulator.length === 0) { + throw new Error( + "BUG: Cause.reduceWithContext - please report an issue at https://github.com/Effect-TS/effect/issues" + ) + } + return accumulator.pop()! +}) // ----------------------------------------------------------------------------- // Pretty Printing @@ -1285,9 +1281,6 @@ export const InterruptorSpan = Context.GenericTag<"InterruptorSpan", Span>("effe const originalAnnotationsSymbol = Symbol.for("effect/Cause/originalAnnotationsSymbol") const originalInstanceSymbol = Symbol.for("effect/Cause/originalInstanceSymbol") -const annotationState = globalValue("effect/Cause/annotationState", () => ({ - disablePropagation: false -})) /* @internal */ export const originalAnnotations = (obj: E): Context.Context | undefined => { @@ -1328,36 +1321,17 @@ function addOriginalAnnotations(obj: E, annotations: Context.Context): }) } -const AnnotationsReducer: Cause.CauseReducer, unknown, Cause.Cause> = { - emptyCase: (_) => empty, - failCase: (context, error, annotations) => fail(addOriginalAnnotations(error, Context.merge(context, annotations))), - dieCase: (context, defect, annotations) => die(addOriginalAnnotations(defect, Context.merge(context, annotations))), - interruptCase: (_, fiberId) => interrupt(fiberId), - sequentialCase: (_, left, right) => sequential(left, right), - parallelCase: (_, left, right) => parallel(left, right), - annotatedCase: (context, cause, annotations) => annotated(cause, Context.merge(context, annotations)) -} - -const propagateAnnotations = (self: Cause.Cause, context: Context.Context): Cause.Cause => - annotationState.disablePropagation ? self : reduceWithContext(self, context, AnnotationsReducer) - -const rehydrateAnnotations = (self: Cause.Cause, obj: unknown): Cause.Cause => { - if (annotationState.disablePropagation) { - return self - } - if (hasProperty(obj, originalAnnotationsSymbol)) { - return annotated(self, (obj as any)[originalAnnotationsSymbol]) - } - return self -} - -/** @internal */ -export const withAnnotationPropagationDisabled = (f: () => A): A => { - try { - annotationState.disablePropagation = true - return f() - } finally { - annotationState.disablePropagation = false +const propagateAnnotations = (self: Cause.Cause, context: Context.Context): Cause.Cause => { + switch (self._tag) { + case "Die": { + return die(addOriginalAnnotations(self.defect, context)) + } + case "Fail": { + return fail(addOriginalAnnotations(self.error, context)) + } + default: { + return self + } } } diff --git a/packages/effect/src/internal/core.ts b/packages/effect/src/internal/core.ts index 37494521ec..b874298966 100644 --- a/packages/effect/src/internal/core.ts +++ b/packages/effect/src/internal/core.ts @@ -662,14 +662,19 @@ export const checkInterruptible = ( f: (isInterruptible: boolean) => Effect.Effect ): Effect.Effect => withFiberRuntime((_, status) => f(_runtimeFlags.interruption(status.runtimeFlags))) -const capture = (cause: Cause.Cause): Effect.Effect => +const capture = (cause: Cause.Cause, obj?: unknown): Effect.Effect => withFiberRuntime((fiber) => { - const span = currentSpanFromFiber(fiber) - let context = Context.empty() - if (span._tag === "Some") { - context = Context.add(context, internalCause.FailureSpan, span.value) + const originalAnnotations = internalCause.originalAnnotations(obj) + if (originalAnnotations) { + cause = internalCause.annotated(cause, originalAnnotations) + } else { + const span = currentSpanFromFiber(fiber) + let context = Context.empty() + if (span._tag === "Some") { + context = Context.add(context, internalCause.FailureSpan, span.value) + } + cause = Context.isEmpty(context) ? cause : internalCause.annotated(cause, context) } - cause = Context.isEmpty(context) ? cause : internalCause.annotated(cause, context) const effect = new EffectPrimitiveFailure(OpCodes.OP_FAILURE) as any effect.effect_instruction_i0 = cause return effect @@ -709,10 +714,11 @@ export const failSync = (evaluate: LazyArg): Effect.Effect => fl export const failCause = (cause: Cause.Cause): Effect.Effect => { switch (cause._tag) { case "Fail": + return capture(cause, cause.error) case "Die": - case "Interrupt": { + return capture(cause, cause.defect) + case "Interrupt": return capture(cause) - } default: { const effect = new EffectPrimitiveFailure(OpCodes.OP_FAILURE) as any effect.effect_instruction_i0 = cause