-
Notifications
You must be signed in to change notification settings - Fork 214
Comparing changes
Open a pull request
base repository: argotorg/fe
base: master
head repository: argotorg/fe
compare: derive-lowering
- 15 commits
- 65 files changed
- 1 contributor
Commits on May 17, 2026
-
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)Configuration menu - View commit details
-
Copy full SHA for 7fbfa26 - Browse repository at this point
Copy the full SHA 7fbfa26View commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for 262ffec - Browse repository at this point
Copy the full SHA 262ffecView commit details -
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).
Configuration menu - View commit details
-
Copy full SHA for b31902a - Browse repository at this point
Copy the full SHA b31902aView commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for 91abb8e - Browse repository at this point
Copy the full SHA 91abb8eView commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for a1475c1 - Browse repository at this point
Copy the full SHA a1475c1View commit details -
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).
Configuration menu - View commit details
-
Copy full SHA for 9271050 - Browse repository at this point
Copy the full SHA 9271050View commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for 673b755 - Browse repository at this point
Copy the full SHA 673b755View commit details -
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).
Configuration menu - View commit details
-
Copy full SHA for 113844e - Browse repository at this point
Copy the full SHA 113844eView commit details -
Configuration menu - View commit details
-
Copy full SHA for b0f9fe5 - Browse repository at this point
Copy the full SHA b0f9fe5View commit details -
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
Configuration menu - View commit details
-
Copy full SHA for ca9de9d - Browse repository at this point
Copy the full SHA ca9de9dView commit details -
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).
Configuration menu - View commit details
-
Copy full SHA for 50bfb2e - Browse repository at this point
Copy the full SHA 50bfb2eView commit details -
Configuration menu - View commit details
-
Copy full SHA for 21325c1 - Browse repository at this point
Copy the full SHA 21325c1View commit details -
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).
Configuration menu - View commit details
-
Copy full SHA for c90b0f3 - Browse repository at this point
Copy the full SHA c90b0f3View commit details -
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.Configuration menu - View commit details
-
Copy full SHA for 7973f4a - Browse repository at this point
Copy the full SHA 7973f4aView commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for 2996f0f - Browse repository at this point
Copy the full SHA 2996f0fView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff master...derive-lowering