Skip to content

fix(lang): resolve policy field references for lowering#336

Merged
scarmuega merged 1 commit into
mainfrom
fix/analyze-policy-fields
Jun 8, 2026
Merged

fix(lang): resolve policy field references for lowering#336
scarmuega merged 1 commit into
mainfrom
fix/analyze-policy-fields

Conversation

@scarmuega

@scarmuega scarmuega commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Problem

A policy whose hash/ref references an env var (or any symbol) parses and analyzes cleanly but fails to lower with MissingAnalyzePhase:

env { policy_hash: Bytes, script_ref: UtxoRef }
policy P { hash: policy_hash, ref: script_ref }   // ❌ MissingAnalyzePhase("policy_hash") at lowering

Only literal-field policies worked — which is why the ref-backed-policy feature (#332/#333/#335) passed its tests but couldn't be used by a real protocol, where the hash and ref are network-specific and supplied via env.

Root cause

Program::analyze tracks every policy into the symbol table (track_policy_def) before running self.policies.analyze(). track_policy_def stores a clone, so the symbol-table copy keeps its field identifiers unresolved. Lowering resolves a referenced policy through that symbol-table entry (Symbol::PolicyDef), so its field expressions have no attached symbols → MissingAnalyzePhase.

Fix

After policies.analyze(), re-track the analyzed policy definitions into the scope — the same re-track-after-analyze pattern resolve_types_and_aliases already uses. The symbol table then holds policies with resolved fields. One pass suffices (policy fields reference env/fn/other-policy symbols already in scope; no fixpoint needed).

Test

policy_def_fields_resolved_in_symbol_table (in the analyzing module) analyzes a program with an env-backed policy P, resolves P from the program scope, and asserts the stored PolicyDef::is_resolved() — i.e. the symbol-table copy has resolved fields. Verified it fails without the fix and passes with it. cargo test -p tx3-lang: 168 passed, 0 failed.

This unblocks env-parameterized ref-backed policies (e.g. the GitHoney bounties simplification).

🤖 Generated with Claude Code

A `policy` is tracked in the symbol table before the policies are
analyzed, so the stored copy keeps unresolved field expressions. Lowering
resolves a policy through that symbol-table entry, so a `hash`/`ref` that
references an env var (or any symbol) failed with `MissingAnalyzePhase` —
only literal-field policies worked.

Re-track the analyzed policy definitions into the scope after
`policies.analyze()`, mirroring the type/alias resolution pass, so the
symbol table holds policies with resolved fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@scarmuega scarmuega force-pushed the fix/analyze-policy-fields branch from df6af7b to 1b11c56 Compare June 8, 2026 00:18
@scarmuega scarmuega merged commit 22a4021 into main Jun 8, 2026
6 checks passed
@scarmuega scarmuega deleted the fix/analyze-policy-fields branch June 8, 2026 00:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant