Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: argotorg/fe
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: argotorg/fe
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: derive-lowering
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 15 commits
  • 65 files changed
  • 1 contributor

Commits on May 17, 2026

  1. Implement derive codegen via HirBuilder during lowering

    Add #[derive(Eq, Default, Ord, Hash, Abi)] support that generates impl
    bodies during the lowering phase using HirBuilder — same pipeline as
    msg/event/error desugaring. Derived impls land in the scope graph with
    proper DeriveDesugared origins and pass type checking normally.
    
    Architecture:
    - CodegenSink trait bridges BodyBuilder ↔ derive evaluator (no SymbolicExpr)
    - eval_derive_strategy_into interprets strategy patterns via field metadata
    - Capability-based design: Reflect<T>, Builder<T>, Hasher, Compare<T>
    - Fe strategies in core use capabilities, never trait methods on field values
    - Parser extended with .{expr} comptime field access (ComptimeFieldExpr)
    - SExpr::DynField + Expr::DynField in semantic/HIR IR
    - HirAnalysisDb view registered via zalsa_register_downcaster for CTFE access
    - #[derive_strategy] functions filtered from type checking and const checking
    
    Core Fe infrastructure:
    - ingots/core/src/reflect.fe — Reflect<T> capability type
    - ingots/core/src/builder.fe — Builder<T> capability type
    - Hash + Hasher traits, Compare<T> trait in ops.fe
    - __derive_eq, __derive_hash, __derive_ord, __derive_default strategies
    
    Test coverage:
    - 8 standalone capability unit tests (field_count, field_name, Builder,
      Hasher, Compare, composition)
    - 11 uitest fixtures (Eq, Default, Ord, Hash, Abi, empty struct, single
      field, many fields, multi-trait, generic error, unknown trait error)
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    7fbfa26 View commit details
    Browse the repository at this point in the history
  2. Wire CTFE machine derive mode: Symbolic ExprId handling at BinOp/Fiel…

    …d/DynField
    
    Add eval_derive_with_machine function that sets up the CTFE machine with
    derive_sink (CodegenSink via lifetime-erased pointer) and symbolic params.
    
    Machine operation handlers now check for Symbolic values:
    - BinOp on two Symbolics → emit Expr::Bin to sink, return new Symbolic
    - Field on Symbolic base → emit Expr::Field to sink, return new Symbolic
    - DynField with Symbolic base + Name field → emit Expr::Field with IdentId
    
    Also:
    - Register HirAnalysisDb view via zalsa_register_downcaster in DriverDataBase
    - Add Hash/Hasher/Compare traits to core Fe (capability-based strategies)
    - Thread ingot through derive impl generation for strategy lookup
    - Validate strategy func exists via find_strategy_func before attempting CTFE
    
    The machine path currently falls through to the pattern evaluator because
    strategy SMIR bodies aren't accessible yet (type checking filtered).
    Next step: enable relaxed type checking for strategies to produce valid SMIR.
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    262ffec View commit details
    Browse the repository at this point in the history
  3. Fix salsa cycle: use TyId::unit placeholder for strategy T parameter

    The CTFE machine's derive_strategy_instance was calling lower_adt on the
    user's struct during scope_graph_impl, causing a salsa query cycle. Fixed
    by using TyId::unit as placeholder for T — the machine intercepts reflect
    intrinsics directly from field_names, never resolving T's actual structure.
    
    Also removed catch_unwind band-aid. The machine now runs cleanly (no panic)
    and falls through to pattern evaluator via Err when strategy SMIR evaluation
    doesn't complete (remaining: reflect interception, branch/return on symbolic).
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    b31902a View commit details
    Browse the repository at this point in the history
  4. Add CTFE machine interception points for derive mode

    Three interception points wired into the existing CtfeMachine:
    - Call: intercepts reflect.field_count()/field_name() → returns concrete
      values from derive_field_names
    - Branch: when condition is Symbolic(ExprId), emits if-guard to sink
      and skips to else_bb
    - Return: when value is Symbolic or Bool, emits return statement to sink
    
    Also adds derive_strategy_instance (ported from const-reflect) which
    builds SemanticInstance with proper generic arg padding for effect
    provider params via collect_generic_params.
    
    The CTFE path is blocked on SMIR lowering: strategy bodies use DynField
    which gets invalid type, causing path resolution panic in SMIR lower.
    Fix: teach type checker that DynField has a deferred type (next commit).
    Pattern evaluator remains active until that's resolved.
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    91abb8e View commit details
    Browse the repository at this point in the history
  5. Replace blanket type-check filter with surgical DynField deferred typing

    Instead of blanket-filtering #[derive_strategy] functions from type
    checking (hiding real bugs), teach the type checker to handle DynField:
    - DynField now gets a fresh type variable (deferred type)
    - Strategy functions ARE type-checked (SMIR bodies generated for CTFE)
    - Strategy diagnostics suppressed in analysis pass (DynField vars unresolved)
    - Force check_func_body on strategies so SMIR is available for CTFE
    
    CTFE machine path still blocked: BinOps on DynField fresh vars can't
    resolve to trait methods, causing SMIR call lowering to panic. Fix
    requires deferred call sites in SMIR for unresolved ops in strategy
    context. Pattern evaluator remains active pending that fix.
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    a1475c1 View commit details
    Browse the repository at this point in the history
  6. Add deferred BinOp lowering for strategy bodies in SMIR

    When SMIR lowering encounters an unresolved call-like expression in a
    strategy body (operators on DynField-typed values that couldn't resolve
    to trait methods), fall back to emitting SExpr::Binary directly from
    the HIR BinOp. This allows the CTFE machine to handle them symbolically.
    
    Also removes the blanket type-checking filter: strategies are now
    type-checked (DynField gets fresh type var), their diagnostics suppressed
    in the analysis pass, and check_func_body is forced so SMIR is available.
    
    CTFE path still blocked: strategy bodies hit path value classification
    panic for path expressions whose types couldn't be fully resolved.
    Next: teach SMIR path lowering to accept unresolved paths in strategy
    context (emit as Forward/UseValue instead of panicking).
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    9271050 View commit details
    Browse the repository at this point in the history
  7. Add SMIR relaxed lowering for strategy bodies (partial)

    Two SMIR lowering panics fixed for strategy bodies:
    - Unresolved call-like expressions (operator desugaring that can't
      resolve to trait methods on fresh type vars): fallback to emitting
      SExpr::Binary from the HIR BinOp directly
    - Unresolved path value classification: fallback to ReadPlace when
      the path has a known local binding
    
    Strategy bodies still have more unresolved expressions (e.g., range
    expressions, for loop desugaring) that need similar treatment. The
    pattern evaluator remains active. Next: systematic SMIR relaxation
    for all expression kinds that strategy bodies use.
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    673b755 View commit details
    Browse the repository at this point in the history
  8. CTFE drives Eq derive output end-to-end via HIR walker

    Implement HirStrategyInterp — a HIR-level strategy interpreter that walks
    the __derive_eq strategy's Body AST directly. The Fe strategy function IS
    the source of truth: the interpreter resolves reflect intrinsics concretely
    (field_count → len, field_name(i) → field_names[i]) and emits symbolic
    operations (BinOp, Field, if-guards) via CodegenSink.
    
    derive_eq passes with CTFE driving output — no pattern evaluator fallback.
    derive_ord also passes (same pattern: for loop + comparison + guard).
    
    Remaining: Default (needs Builder set_field/finish → RecordInit),
    Hash (needs Hasher.feed → .hash() accumulation).
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    113844e View commit details
    Browse the repository at this point in the history
  9. Configuration menu
    Copy the full SHA
    b0f9fe5 View commit details
    Browse the repository at this point in the history
  10. All 11 derive tests pass via CTFE HIR walker

    The HirStrategyInterp now handles all derive patterns:
    - Eq: for loop + DynField + BinOp(!=) + if-guard → works
    - Ord: for loop + DynField + BinOp(<) + if-guard → works
    - Default: Builder.set_field/finish → RecordInit → works
    - Hash: Hasher.feed/finish → accumulation chain → works
    - Abi: const computation (unchanged) → works
    
    Key fixes:
    - Local variable lookup (loop vars) via pat name matching
    - Builder.finish with empty fields (empty struct Default)
    - Hasher accumulator: feed() builds hash chain, finish() returns it
    - Distinguish Builder vs Hasher finish via hash_accum presence
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    ca9de9d View commit details
    Browse the repository at this point in the history
  11. Delete pattern evaluator from production path

    The pattern-based evaluator (eval_derive_strategy_into) is now #[cfg(test)]
    only — used by unit tests that validate CodegenSink output shape.
    
    Production path: eval_strategy_from_hir drives ALL derives (Eq, Ord, Hash,
    Default, Abi) by walking the Fe strategy function's HIR body directly.
    The Fe strategy code IS the source of truth — no hardcoded Rust fallback.
    
    Ord's lt method also goes through the HIR walker now (was the last holdout).
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    50bfb2e View commit details
    Browse the repository at this point in the history
  12. Configuration menu
    Copy the full SHA
    21325c1 View commit details
    Browse the repository at this point in the history
  13. Remove dead SMIR machine derive mode — HIR walker is sole path

    Delete all derive-mode code from CtfeMachine:
    - derive_strategy_instance, eval_derive_with_machine
    - derive_sink/derive_field_names fields
    - derive_sink_ref helper
    - All BinOp/Field/DynField/Branch/Return/Call interception blocks
    
    The HIR walker (eval_strategy_from_hir) handles all derive evaluation.
    No dead code, no #[allow(dead_code)] on derive infrastructure.
    Only CtfeConstKind::Name/Symbolic variants remain (harmless, future use).
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    c90b0f3 View commit details
    Browse the repository at this point in the history
  14. Fix Ord lexicographic ordering + add correctness tests

    - Fix __derive_ord strategy: add `if a > b { return false }` guard
      for correct lexicographic comparison (was missing, only had `< → true`)
    - Add multi-field Ord test (Coordinate{x,y,z} with lt/le/gt/ge)
    - Add CTFE-driven verification test (Triple struct proves strategy
      body evaluation produces correct output for 3-field structs)
    
    13 derive tests now pass, all driven by the HIR walker.
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    7973f4a View commit details
    Browse the repository at this point in the history
  15. Add tests proving strategy body drives output

    Two new unit tests:
    - strategy_body_drives_output_not_hardcoded: proves field_count scales
      output (1 field → 1 guard, 3 fields → 3 guards)
    - different_strategies_produce_different_output: proves Eq/Ord/Default
      produce structurally different HIR (!=  vs < vs RecordInit)
    
    These would fail if the evaluator used hardcoded logic instead of
    reading the strategy function's Body AST.
    micahscopes committed May 17, 2026
    Configuration menu
    Copy the full SHA
    2996f0f View commit details
    Browse the repository at this point in the history
Loading