Skip to content

SimpleSirToUplcLowering ignores lazy flags on let bindings from pattern matching optimization #125

@rssh

Description

@rssh

Problem

The pattern matching optimization (implemented to avoid redundant let bindings for Var scrutinees) uses SIR.LetFlags.Lazy to defer evaluation of match scrutinees. However, the SimpleSirToUplcLowering backend ignores lazy flags and always evaluates let bindings eagerly.

Impact

This causes a 10-byte increase in UPLC size (846 → 856 bytes) for the optimized minting policy test when using SimpleSirToUplcLowering backend.

Current Behavior

  • Pattern matching optimization creates let bindings with SIR.LetFlags.Lazy when scrutinee is not a Var
  • SimpleSirToUplcLowering ignores this flag and evaluates eagerly
  • Results in slightly larger UPLC bytecode (856 bytes instead of expected 846)

Expected Behavior with V3 Backend

SirToUplcV3Lowering correctly handles lazy flags and produces more optimal code:

  • V3 backend: 1652 bytes (properly uses lazy evaluation)
  • SimpleSirToUplcLowering: 856 bytes (ignores lazy flags)

Decision

Accept the small size increase for SimpleSirToUplcLowering as it's the legacy backend.

Files Affected

  • scalus-plugin/src/main/scala/scalus/PatternMatchingCompiler.scala - Creates lazy let bindings
  • scalus-core/shared/src/main/scala/scalus/sir/lowering/Lowering.scala - SimpleSirToUplcLowering ignores lazy flags
  • scalus-examples/shared/src/test/scala/scalus/examples/MintingPolicyExampleTest.scala - Test shows 10-byte size increase

Future Work

Consider one of:

  1. Make the pattern matching optimization backend-aware (don't use lazy flags with SimpleSirToUplcLowering)
  2. Migrate fully to V3 backend and deprecate SimpleSirToUplcLowering
  3. Update SimpleSirToUplcLowering to understand lazy flags (significant refactoring)

Related Code

Pattern matching optimization in PatternMatchingCompiler.scala:185-194:

val decisionsWithScrutinee = if needsScrutineeLet then
    SIR.Let(
      List(Binding(ctx.scrutineeName, parsedMatch.scrutineeTp, parsedMatch.scrutinee)),
      decisions,
      SIR.LetFlags.Lazy,  // <-- SimpleSirToUplcLowering ignores this
      AnnotationsDecl.fromSrcPos(ctx.topLevelPos)
    )
else
    decisions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions