Conversation
d8cf004 to
d33fd5f
Compare
|
| Branch | transpiler-cleanup-final |
| Testbed | ubuntu-latest |
⚠️ WARNING: No Threshold found!Without a Threshold, no Alerts will ever be generated.
Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the--ci-only-thresholdsflag.
Click to view all benchmark results
| Benchmark | leak-build-ms | Measure (units) x 1e3 | leak-count | Measure (units) | leak-run-ms | Measure (units) |
|---|---|---|---|---|---|---|
| benchmarks/concurrent/04_fanout_fanin/bench | 📈 view plot | 5.09 units x 1e3 | 📈 view plot | 0.00 units | 📈 view plot | 3,559.95 units |
| benchmarks/concurrent/09_kvstore/bench | 📈 view plot | 5.06 units x 1e3 | 📈 view plot | 0.00 units | 📈 view plot | 60,004.29 units |
| benchmarks/concurrent/14_nested_lock/bench | 📈 view plot | 4.95 units x 1e3 | 📈 view plot | 0.00 units | 📈 view plot | 415.65 units |
| benchmarks/inter-clear/02_concurrent_fsm_vs_stackful/bench_fsm | 📈 view plot | 4.91 units x 1e3 | 📈 view plot | 0.00 units | 📈 view plot | 164.87 units |
| benchmarks/inter-clear/02_concurrent_fsm_vs_stackful/bench_stackful | 📈 view plot | 4.94 units x 1e3 | 📈 view plot | 0.00 units | 📈 view plot | 316.73 units |
| benchmarks/sequential/11_pipeline_overhead/bench | 📈 view plot | 4.90 units x 1e3 | 📈 view plot | 0.00 units | 📈 view plot | 13,544.31 units |
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #20 +/- ##
==========================================
+ Coverage 89.85% 89.88% +0.02%
==========================================
Files 182 183 +1
Lines 47332 47636 +304
Branches 11766 11598 -168
==========================================
+ Hits 42529 42816 +287
- Misses 4803 4820 +17
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
d33fd5f to
02c786c
Compare
…strap Squashed 3 commits: - 6551d7a Self-host preparation: typed schemas, struct extractions, walker traits, respond_to? cleanup - 02c786c Restore rebase-clobbered cleanup: typed:true, T.bind, dead-check fixes - e8e909a refactor: drop dead respond_to? guards on Locatable/Type attrs What's included: - Typed schemas (Schemas::StructSchema / UnionSchema / ResourceSchema / EnumSchema) replace Hash-as-struct dispatch. Coercion helpers (Schemas.as_struct_schema / as_union_schema / as_resource_schema) bridge consumers that still see raw Hash from the annotator. - PipelineSite struct extraction (PipelineHost / PipelineGenerator / PipelineRewriter). - Formatter::Emitter::EmitterState struct extraction. - MIRPass::WalkState + OwnershipDataflow::DataflowStep struct extractions. - AST is_a? dispatch chains converted to Ruby 3 pattern matching. - FunctionSignature Hash-shim layer eliminated. - Sorbet bootstrap: # typed: true sigils on helper modules, T.bind in mixin methods, RBI overrides for AST Struct fields (Token typed non-nilable on AST::Locatable -- fires srb.help/7034 dead-check signals). - 60 dead respond_to? guards removed where the receiver is always an AST node carrying the attr via AST::Locatable (or always a Type for type-method calls). Three sites needed `&.` instead of unconditional removal (reg / decl_node / decl can be nil). - Memory-leak fix in elem_needs_cleanup? (chained-coercion clobbered elem_schema for struct types). - Transpiler-output fix in control_flow.rb skip_rhs_move (Schemas coercion for union map values restores missing `defer CheatLib.cleanup` emission). Verification: - bundle exec prspec spec/ -> 4294 examples, 0 failures - ./clear test transpile-tests/ -> 0 leaks, 0 errors - module-integration / ffi-integration green Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e8e909a to
e68e8d1
Compare
cuzzo
added a commit
that referenced
this pull request
May 8, 2026
Squashed 14 commits. Builds on the typed-schemas / Sorbet bootstrap from PR #20 (commit f9c81f0 on master) to bring all 90 src/ files to # typed: true with a 0-error Sorbet baseline gated in CI. What's in this PR: CI gate: - New `sorbet` job in .github/workflows/ci.yml runs `bundle exec srb tc` on every PR. Fails on any new typed:true error. Job runs in parallel with ruby-unit, completes in <1s after gem cache warm. Baseline cleanup (83 → 0 errors before any flips): - Added missing `T.bind(self, SemanticAnnotator) rescue nil` to 25 mixin instance methods in fixable_helpers / effects / capabilities whose includer's instance methods were unresolvable. - Replaced `var = nil; var = lambda {...}` recursive-lambda pattern with `var = T.let(nil, T.untyped); var = lambda do ... end` at 4 sites (effects.rb scan_for_calls / scan_for_raises and the mark_fn_value_references! traversal). Sorbet's flow analysis was seeing the inner self-reference as a call-on-nil. - T.let widening on 4 boolean flag arrays / outer-loop changed flags / literal-typed empty-array accumulators where Sorbet inferred too narrow a type for later mutation. - Standard `T.any(FalseClass, Type)` → `is_a?(Type)` narrowing fix applied across 8 sites where the `ti = something rescue nil; ti = Type.new(ti) if ti && !ti.is_a?(Type)` idiom leaks FalseClass through the conjunction's false branch. - Dropped 5 dead `stmt.body || []` / `stmt.cases || []` / `stmt.branches || []` defensive expressions where the RBI guarantees the field is T::Array. - Migrated one raw-string `error!` site to a registry code (RETURN_LIFETIME_NOT_ASSOCIATED) so the call-site audit spec stayed clean. - Per-class :body override in tools/gen_struct_fields_rbi.rb for AST::LambdaLit (single expression, not Array) and AST::HashLit (Hash, not Array) so RBI sigs match runtime. Tranche 1-9 — flip 90 src/ files to # typed: true: Easy flips (T1-T3): 35 files in 75-500 LOC range, mostly clean as-is. Required `T.bind(self, SemanticAnnotator)` on alloc.rb's 3 mixin methods. Stripped 3 dead `&.` operators in string_concat_rewriter.rb flagged by srb.help/7034 — RBI says `node.body` / `node.args` / `node.cases` are non-nilable Arrays. Medium flips (T4): 12 files in 500-2900 LOC range. Stripped 40 more dead `&.` operators across mir_pass.rb / escape_analysis.rb / promotion_plan.rb / pipeline_rewriter.rb (Array attrs proven non- nilable by RBI). Several Type-narrowing fixes. Two real bugs: the 2-arg `CompilerError.new(message, location)` call shape that would have ArgumentError'd if reached (SourceError expects 3 args: token/message/source). Big-file flips (T5-T7): 6 files including annotator.rb (6510), mir_lowering.rb (7235). Required several real-bug fixes uncovered by typing: - annotator.rb: AST::StaticCall's `.name` accessor doesn't exist (the Struct fields are `:token, :type_name, :method_name, :args`); fixed to `.method_name`. Two more 2-arg CompilerError calls fixed. function_analysis.rb's `error!` call missing the node arg. - type.rb: UInt64 max literal `18_446_744_073_709_551_615` rewritten as `(2**64) - 1` (Sorbet 3002 doesn't support 64-bit unsigned). Two more single-arg CompilerError calls fixed. - parser.rb: `Token.new(...)` peek fallback resolved to top-level Token stub instead of `Lexer::Token`; renamed to disambiguate. Module/Kernel deferred-file recovery (T5/T8): 11 files where module-singleton methods called Kernel built-ins (`raise`, `lambda`, `Array()`, `Integer()`) that Sorbet doesn't see on bare modules. Applied uniform `T.bind(self, T.untyped) rescue nil` at the start of every method body — Sorbet then accepts the dispatch. Cost: suppresses per-call type-checking inside those methods. Benefit: the file participates in typed:true and any non-method-dispatch error (T.let mismatches, dead code, return-type contradictions) still fires. Also gets us a clean Sorbet baseline across the whole project. DSL pattern (T9 - parser.rb): The Parser DSL stores blocks for later instance_exec; Sorbet sees `self == T.class_of(Parser)` at definition time and the parse_X instance methods don't resolve on the singleton. Wrapped each block (single-line `{ ... }` and multi-line `do ... end` via Prism walker) with `T.bind(self, Parser) rescue nil`. 79 blocks across stmt/primary/suffix calls + 2 pattern-engine lambdas. Schemas refactor (T9 - schemas.rb): Replaced `Data.define(:fields, ...) do def initialize(kw:, ...); super end end` with plain classes (attr_reader + kwarg initialize + freeze). Sorbet 4010 fired on the kwarg-only override of Data.define's auto-positional initialize. No call site relied on Data's `==` / `hash` / `with` methods so the migration is structural-equivalence. Cumulative dead-check signals fired and cleaned: ~52 dead `&.` operators removed across the project (Sorbet srb.help/7034). All verified by spec + transpile-tests as runtime-equivalent — the RBI sigs match real runtime invariants. Real bugs fixed (would crash if reached at runtime): - 5x `CompilerError.new(message, location)` 2-arg calls (SourceError expects 3 args) - 1x `error!("string")` missing node arg - 1x `n.name.to_s` on AST::StaticCall (no `.name`, should be `.method_name`) - 1x bare `Token.new(...)` resolving to top-level Token stub instead of `Lexer::Token` Verification: - bundle exec srb tc -> No errors! - bundle exec prspec spec/ -> 4300 examples, 0 failures - ./clear test transpile-tests/ -> 0 leaks, 0 errors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cuzzo
added a commit
that referenced
this pull request
May 8, 2026
Squashed 14 commits. Builds on the typed-schemas / Sorbet bootstrap from PR #20 (commit f9c81f0 on master) to bring all 90 src/ files to # typed: true with a 0-error Sorbet baseline gated in CI. What's in this PR: CI gate: - New `sorbet` job in .github/workflows/ci.yml runs `bundle exec srb tc` on every PR. Fails on any new typed:true error. Job runs in parallel with ruby-unit, completes in <1s after gem cache warm. Baseline cleanup (83 → 0 errors before any flips): - Added missing `T.bind(self, SemanticAnnotator) rescue nil` to 25 mixin instance methods in fixable_helpers / effects / capabilities whose includer's instance methods were unresolvable. - Replaced `var = nil; var = lambda {...}` recursive-lambda pattern with `var = T.let(nil, T.untyped); var = lambda do ... end` at 4 sites (effects.rb scan_for_calls / scan_for_raises and the mark_fn_value_references! traversal). Sorbet's flow analysis was seeing the inner self-reference as a call-on-nil. - T.let widening on 4 boolean flag arrays / outer-loop changed flags / literal-typed empty-array accumulators where Sorbet inferred too narrow a type for later mutation. - Standard `T.any(FalseClass, Type)` → `is_a?(Type)` narrowing fix applied across 8 sites where the `ti = something rescue nil; ti = Type.new(ti) if ti && !ti.is_a?(Type)` idiom leaks FalseClass through the conjunction's false branch. - Dropped 5 dead `stmt.body || []` / `stmt.cases || []` / `stmt.branches || []` defensive expressions where the RBI guarantees the field is T::Array. - Migrated one raw-string `error!` site to a registry code (RETURN_LIFETIME_NOT_ASSOCIATED) so the call-site audit spec stayed clean. - Per-class :body override in tools/gen_struct_fields_rbi.rb for AST::LambdaLit (single expression, not Array) and AST::HashLit (Hash, not Array) so RBI sigs match runtime. Tranche 1-9 — flip 90 src/ files to # typed: true: Easy flips (T1-T3): 35 files in 75-500 LOC range, mostly clean as-is. Required `T.bind(self, SemanticAnnotator)` on alloc.rb's 3 mixin methods. Stripped 3 dead `&.` operators in string_concat_rewriter.rb flagged by srb.help/7034 — RBI says `node.body` / `node.args` / `node.cases` are non-nilable Arrays. Medium flips (T4): 12 files in 500-2900 LOC range. Stripped 40 more dead `&.` operators across mir_pass.rb / escape_analysis.rb / promotion_plan.rb / pipeline_rewriter.rb (Array attrs proven non- nilable by RBI). Several Type-narrowing fixes. Two real bugs: the 2-arg `CompilerError.new(message, location)` call shape that would have ArgumentError'd if reached (SourceError expects 3 args: token/message/source). Big-file flips (T5-T7): 6 files including annotator.rb (6510), mir_lowering.rb (7235). Required several real-bug fixes uncovered by typing: - annotator.rb: AST::StaticCall's `.name` accessor doesn't exist (the Struct fields are `:token, :type_name, :method_name, :args`); fixed to `.method_name`. Two more 2-arg CompilerError calls fixed. function_analysis.rb's `error!` call missing the node arg. - type.rb: UInt64 max literal `18_446_744_073_709_551_615` rewritten as `(2**64) - 1` (Sorbet 3002 doesn't support 64-bit unsigned). Two more single-arg CompilerError calls fixed. - parser.rb: `Token.new(...)` peek fallback resolved to top-level Token stub instead of `Lexer::Token`; renamed to disambiguate. Module/Kernel deferred-file recovery (T5/T8): 11 files where module-singleton methods called Kernel built-ins (`raise`, `lambda`, `Array()`, `Integer()`) that Sorbet doesn't see on bare modules. Applied uniform `T.bind(self, T.untyped) rescue nil` at the start of every method body — Sorbet then accepts the dispatch. Cost: suppresses per-call type-checking inside those methods. Benefit: the file participates in typed:true and any non-method-dispatch error (T.let mismatches, dead code, return-type contradictions) still fires. Also gets us a clean Sorbet baseline across the whole project. DSL pattern (T9 - parser.rb): The Parser DSL stores blocks for later instance_exec; Sorbet sees `self == T.class_of(Parser)` at definition time and the parse_X instance methods don't resolve on the singleton. Wrapped each block (single-line `{ ... }` and multi-line `do ... end` via Prism walker) with `T.bind(self, Parser) rescue nil`. 79 blocks across stmt/primary/suffix calls + 2 pattern-engine lambdas. Schemas refactor (T9 - schemas.rb): Replaced `Data.define(:fields, ...) do def initialize(kw:, ...); super end end` with plain classes (attr_reader + kwarg initialize + freeze). Sorbet 4010 fired on the kwarg-only override of Data.define's auto-positional initialize. No call site relied on Data's `==` / `hash` / `with` methods so the migration is structural-equivalence. Cumulative dead-check signals fired and cleaned: ~52 dead `&.` operators removed across the project (Sorbet srb.help/7034). All verified by spec + transpile-tests as runtime-equivalent — the RBI sigs match real runtime invariants. Real bugs fixed (would crash if reached at runtime): - 5x `CompilerError.new(message, location)` 2-arg calls (SourceError expects 3 args) - 1x `error!("string")` missing node arg - 1x `n.name.to_s` on AST::StaticCall (no `.name`, should be `.method_name`) - 1x bare `Token.new(...)` resolving to top-level Token stub instead of `Lexer::Token` Verification: - bundle exec srb tc -> No errors! - bundle exec prspec spec/ -> 4300 examples, 0 failures - ./clear test transpile-tests/ -> 0 leaks, 0 errors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cuzzo
added a commit
that referenced
this pull request
May 8, 2026
Squashed 14 commits. Builds on the typed-schemas / Sorbet bootstrap from PR #20 (commit f9c81f0 on master) to bring all 90 src/ files to # typed: true with a 0-error Sorbet baseline gated in CI. What's in this PR: CI gate: - New `sorbet` job in .github/workflows/ci.yml runs `bundle exec srb tc` on every PR. Fails on any new typed:true error. Job runs in parallel with ruby-unit, completes in <1s after gem cache warm. Baseline cleanup (83 → 0 errors before any flips): - Added missing `T.bind(self, SemanticAnnotator) rescue nil` to 25 mixin instance methods in fixable_helpers / effects / capabilities whose includer's instance methods were unresolvable. - Replaced `var = nil; var = lambda {...}` recursive-lambda pattern with `var = T.let(nil, T.untyped); var = lambda do ... end` at 4 sites (effects.rb scan_for_calls / scan_for_raises and the mark_fn_value_references! traversal). Sorbet's flow analysis was seeing the inner self-reference as a call-on-nil. - T.let widening on 4 boolean flag arrays / outer-loop changed flags / literal-typed empty-array accumulators where Sorbet inferred too narrow a type for later mutation. - Standard `T.any(FalseClass, Type)` → `is_a?(Type)` narrowing fix applied across 8 sites where the `ti = something rescue nil; ti = Type.new(ti) if ti && !ti.is_a?(Type)` idiom leaks FalseClass through the conjunction's false branch. - Dropped 5 dead `stmt.body || []` / `stmt.cases || []` / `stmt.branches || []` defensive expressions where the RBI guarantees the field is T::Array. - Migrated one raw-string `error!` site to a registry code (RETURN_LIFETIME_NOT_ASSOCIATED) so the call-site audit spec stayed clean. - Per-class :body override in tools/gen_struct_fields_rbi.rb for AST::LambdaLit (single expression, not Array) and AST::HashLit (Hash, not Array) so RBI sigs match runtime. Tranche 1-9 — flip 90 src/ files to # typed: true: Easy flips (T1-T3): 35 files in 75-500 LOC range, mostly clean as-is. Required `T.bind(self, SemanticAnnotator)` on alloc.rb's 3 mixin methods. Stripped 3 dead `&.` operators in string_concat_rewriter.rb flagged by srb.help/7034 — RBI says `node.body` / `node.args` / `node.cases` are non-nilable Arrays. Medium flips (T4): 12 files in 500-2900 LOC range. Stripped 40 more dead `&.` operators across mir_pass.rb / escape_analysis.rb / promotion_plan.rb / pipeline_rewriter.rb (Array attrs proven non- nilable by RBI). Several Type-narrowing fixes. Two real bugs: the 2-arg `CompilerError.new(message, location)` call shape that would have ArgumentError'd if reached (SourceError expects 3 args: token/message/source). Big-file flips (T5-T7): 6 files including annotator.rb (6510), mir_lowering.rb (7235). Required several real-bug fixes uncovered by typing: - annotator.rb: AST::StaticCall's `.name` accessor doesn't exist (the Struct fields are `:token, :type_name, :method_name, :args`); fixed to `.method_name`. Two more 2-arg CompilerError calls fixed. function_analysis.rb's `error!` call missing the node arg. - type.rb: UInt64 max literal `18_446_744_073_709_551_615` rewritten as `(2**64) - 1` (Sorbet 3002 doesn't support 64-bit unsigned). Two more single-arg CompilerError calls fixed. - parser.rb: `Token.new(...)` peek fallback resolved to top-level Token stub instead of `Lexer::Token`; renamed to disambiguate. Module/Kernel deferred-file recovery (T5/T8): 11 files where module-singleton methods called Kernel built-ins (`raise`, `lambda`, `Array()`, `Integer()`) that Sorbet doesn't see on bare modules. Applied uniform `T.bind(self, T.untyped) rescue nil` at the start of every method body — Sorbet then accepts the dispatch. Cost: suppresses per-call type-checking inside those methods. Benefit: the file participates in typed:true and any non-method-dispatch error (T.let mismatches, dead code, return-type contradictions) still fires. Also gets us a clean Sorbet baseline across the whole project. DSL pattern (T9 - parser.rb): The Parser DSL stores blocks for later instance_exec; Sorbet sees `self == T.class_of(Parser)` at definition time and the parse_X instance methods don't resolve on the singleton. Wrapped each block (single-line `{ ... }` and multi-line `do ... end` via Prism walker) with `T.bind(self, Parser) rescue nil`. 79 blocks across stmt/primary/suffix calls + 2 pattern-engine lambdas. Schemas refactor (T9 - schemas.rb): Replaced `Data.define(:fields, ...) do def initialize(kw:, ...); super end end` with plain classes (attr_reader + kwarg initialize + freeze). Sorbet 4010 fired on the kwarg-only override of Data.define's auto-positional initialize. No call site relied on Data's `==` / `hash` / `with` methods so the migration is structural-equivalence. Cumulative dead-check signals fired and cleaned: ~52 dead `&.` operators removed across the project (Sorbet srb.help/7034). All verified by spec + transpile-tests as runtime-equivalent — the RBI sigs match real runtime invariants. Real bugs fixed (would crash if reached at runtime): - 5x `CompilerError.new(message, location)` 2-arg calls (SourceError expects 3 args) - 1x `error!("string")` missing node arg - 1x `n.name.to_s` on AST::StaticCall (no `.name`, should be `.method_name`) - 1x bare `Token.new(...)` resolving to top-level Token stub instead of `Lexer::Token` Verification: - bundle exec srb tc -> No errors! - bundle exec prspec spec/ -> 4300 examples, 0 failures - ./clear test transpile-tests/ -> 0 leaks, 0 errors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Self-host preparation cleanup: typed schemas, struct extractions, walker trait migration, and respond_to? duck-typing reduction. Replaces the pre-rebase
transpiler-cleanupbranch after a rebase onto master that pulled in 20 commits of new master work.What's included
P0 (foundational):
Schemas::*typed schemas (StructSchema,UnionSchema,ResourceSchema,EnumSchema) replacing hash-as-struct dispatch insrc/ast/schemas.rbPipelineSitestruct extraction fromPipelineHost/PipelineGenerator/PipelineRewriterFormatter::Emitter::EmitterStateextractionMIRPass::WalkState+OwnershipDataflow::DataflowStepextractionsSchemas.as_*_schemacoercion helpers so consumers handle either typed or raw-Hash schemas without per-siteis_a?chainsP1 (cleanup):
FunctionSignatureHash-shim layer fully removed ([],[]=,key?,is_a?(Hash)override,dig,merge)is_a?dispatch chains converted to Ruby 3 pattern matching&.operators removed via Prism flow analysis# typed: truewith 259T.bind(self, SemanticAnnotator)annotationsTooling added under
tools/:dead_nil_check_finder.rb/dead_nil_check_fixer.rb/dead_trailing_if.rb— Prism-based dead&.detection + auto-fixrespond_to_inventory.rb/respond_to_narrowing.rb— classify defensiverespond_to?sitesgen_struct_fields_rbi.rb/struct_field_nilability.rb— generate typed RBI overrides for Struct accessorssrb_nil_origins.rb— aggregate Sorbet nil-origin traces to find root causesTest plan
bundle exec prspec spec/— 4130 / 4130 pass./clear test transpile-tests/— 520 / 520, 0 memory leaks, 0 errorscd transpile-tests/module-integration && zig build testcd transpile-tests/ffi-integration && zig build testNotes for reviewer
d8cf0048) re-applies the typed:true sigils, T.bind annotations, and one dead-check fix that were lost. Somerespond_to?cleanups need per-site review (task Polymorphic sync v2 #9 follow-on).traverse =patterns Sorbet can't see through.Type#[]and schema dispatch; coercion helpers maintain uniform shape so consumers don't need to know whether a schema came from the annotator (raw Hash) or MIR lowering (Schemas::*).#TRANSPILE_PURE