Skip to content

Annotated fail constant panics during evaluation #1314

Description

@researchzero-sec

What Git revision are you using?

5538a42b

What operating system are you using, and which version?

  • Linux / Ubuntu Jammy

Describe what the problem is?

A Bool-annotated module constant that calls a Bool-annotated fail/todo helper reaches codegen constant evaluation and panics the compiler with Failed to evaluate constant: EvaluationFailure, instead of letting the test runner report the expected failure of the fail-marked test that references it.

Minimal reproduction:

fn helper_fail_bool() -> Bool {
  fail @"constant helper bool"
}

const broken_fail: Bool =
  helper_fail_bool()

test use_fail_constant() fail {
  broken_fail
}

Running aiken check panics with:

Failed to evaluate constant: EvaluationFailure

Source-level evidence:

  • Module constants pass their optional annotation into assignment inference (crates/aiken-lang/src/tipo/infer.rs:705).

  • Function return annotations similarly constrain the helper body (crates/aiken-lang/src/tipo/expr.rs:381).

  • When the constant is referenced, codegen evaluates the generated program and panics if evaluation fails (crates/aiken-lang/src/gen_uplc.rs:3769):

    .unwrap_or_else(|e| panic!("Failed to evaluate constant: {e:#?}"))

Explicit annotations change the unannotated helper-constant behavior from the older banner-only exit into a fatal compiler bug report. The helper return annotation and constant annotation are accepted during typing, but when the constant is referenced from a fail-marked test, codegen evaluates the constant and panics on the evaluation failure before the test runner can report the expected failure.

Notes:

  • The same panic reproduces with a todo helper in place of fail; either is enough to reach the constant-evaluation panic.
  • Adjacent follow-up: whether annotated constant expressions with a local let x: Bool = fail follow the same panic path without going through a helper call.

Related (not duplicates):

  • compiler crash on division after todo #855 (closed) — same EvaluationFailure family from an annotated todo/fail helper, but the trigger is arithmetic on the helper return and the panic fires at gen_uplc.rs:4194 with the older Result::unwrap() message, not the constant-evaluation call site at gen_uplc.rs:3769.
  • compile time assertions #1262 (closed, converted to discussion) — a const : Bool = { expect ...; True } causes "an ungraceful exit"; same constant-evaluation panic path, but the failing expression is an inline expect rather than a call to an annotated fail/todo helper.

What should be the expected behavior?

The fail-marked test use_fail_constant should be reported as an expected failure by the test runner. Referencing a constant whose initializer evaluates to fail/todo from a fail-marked test should not panic the compiler; at minimum, codegen should surface a structured diagnostic instead of an aiken::fatal::error panic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    code genUntyped Plutus Core code generation

    Type

    Fields

    No fields configured for Bug.

    Projects

    Status
    🔨 Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions