Repository navigation
The fragment refuses a define_method that displaces a sig-annotated method (fixes #44) - #155
Open
jiro-by-nori[bot] wants to merge 1 commit into
Open
jiro-by-nori[bot] wants to merge 1 commit into
jiro-by-nori[bot] wants to merge 1 commit into
Conversation
…ed method D10 admits a method redefinition because the pre-ratchet checker used to prove that the replacement conformed to the declaration it displaced. That checker was removed, so `define_method(:f)` over a sig-annotated `f` was admitted while nothing checked it: `escape-hatches/002.rb` was a Sorbet-accepted program that reaches `NoMethodError` while sitting inside the fragment, and therefore inside `theorem_scope`, making the fragment's load-bearing property false for it (issue #44). `scan` now carries the sig-annotated names declared so far in the current class or module body — from `def`, `def self.`, a visibility-wrapped `def`, and the names `attr_*` generates — and refuses a literal `define_method` / `define_singleton_method` whose target is one of them, as a `redefinition` violation. Everything D10 admitted for a reason it still has stays admitted: a computed name, `alias`/`alias_method` and `prepend` are untouched, and the sig wrapper lives in the prelude rather than in the scanned program, so an annotated method's own wrapper is not refused. Exclusion is the only direction the fragment may move, so this cannot turn a rejected program into an accepted one. On the Sorbet corpus the fragment goes from 13 to 12 programs, `theorem_scope` from 6 to 5, and no unsoundness witness is in the fragment, so `test_no_unsoundness_witness_is_in_the_fragment` now asserts the property with no pinned exception. The `Fragment.lean` header no longer cites `infer`, and names the per-body scope as the third known gap in criterion 3. Co-authored-by: Jiro <jiro@nori.ai>
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.
What this fixes
An unsoundness witness was in the typed fragment, and therefore in
theorem_scope(issue #44).escape-hatches/002.rbis Sorbet-accepted, and it reaches an uncaughtNoMethodError:Fragment.lean's criterion 3 (D10) admits a method redefinition because the pre-ratchet checker used to discharge the obligation that the replacement conforms to the declaration it displaces. That checker was removed in5ee6b034, so the admission stayed while the proof behind it did not:rubycore --fragmentsaidin_fragment: true, and nothing downstream ever checked the displacedsig.The change
scannow tracks thesig-annotated names declared so far in the current body — fromdef,def self., a visibility-wrappeddef(private def), and the namesattr_*generates (attr_writerdeclaresname=,attr_accessorboth) — and refuses a literaldefine_method/define_singleton_methodwhose target is one of them, reporting aredefinitionviolation.Everything D10 admitted for a reason it still has stays admitted:
define_method(name)) stays in the fragment — nothing syntactic can match it;alias/alias_method/prependkeep D10's conditional admission;prelude.rb, not in the scanned program, so an annotated method's own wrapper is not refused.The check only ever excludes, so it cannot turn a rejected program into an accepted one.
Fragment.lean's header no longer citesinferas the handler for a displaced declaration, and now names the per-body scope as the third known gap in criterion 3 (asigin oneclass Cbody and adefine_methodin a reopenedclass Cbody are still not matched).Measurements on the corpus
run_checkoverdifftest/corpus/sorbet, before → after:theorem_scopeescape-hatches/002.rb)Every other program's classification is unchanged; no cell of the static-oracle two-by-two moved.
Tests
make difftest-test— 202 passed (201 before), coverage held.difftest/tests/test_sorbet_check.py:test_no_unsoundness_witness_is_in_the_fragmentasserts the property outright —witnesses & in_fragment == ∅— instead of pinningescape-hatches/002.rbas a named exception;test_fragment_checker_classifies_the_hatchesgains the block, explicit-Proc(define_method(:f, proc { … }), whose installed name is the first argument, not a one-element argument list) and singleton forms, plus bothattr_*shapes;test_fragment_checker_admits_a_non_displacing_define_methodpins the other side: a fresh name and a computed name stay in the fragment.Validation
Run locally on the branch, from a cold toolchain (Lean
v4.32.2, CRuby4.0.5):Highlights:
make lean,make books(1405 jobs),make metatheory— every proof book builds; the audited axioms are stillpropext,Classical.choice,Quot.sound;make soundness,make comparator—OK: the comparator accepts — statements match, axioms are Lean's three, the kernel replays the closure;make conformance— CRuby4.0.5over the 1287-program bootstraptest corpus:ran 1287, agree 1087, sut_unsupported,disagree 0, exactly the recorded baseline, and the regressions tier and tier3 agree;make difftest-test— 202 passed,COVERAGE OK -- the baseline holds;make gen-check,make lint,make docs— generated sources fresh, no lint finding, docs build.No recorded result fell, no check or theorem was dropped, no
sorry/native_decide/axiom/lint suppression/test skip was added.Provenance
Authored by Jiro, an autonomous agent, including this description.
Closes #44