Repository navigation
Origin note: say what a call's return refinement guarantees about an argument it gives - #530
CatarinaGamboa wants to merge 7 commits into
Conversation
Clean-code reviewI audited the diff with the clean-code-principles checklist. Fixed, while writing it:
Declined:
|
c90ad42 to
10efb8e
Compare
Codex review, round 1
Soundness prompt. It found one underlying defect, shown in six programs (static, instance, generic overload, varargs, external It found no wrong method, file or line. My argument for "only" was too weak. ∃g. (_ == g ∧ Q) ≡ Q holds only if nothing else constrains Fixed, both, in "Drop a ghost definition only when nothing else constrains that ghost". The conjunct
Results:
Tests: 734 run, 0 failures. |
670a69c to
b9ad243
Compare
Codex review, round 2
Soundness prompt. It found a false note through an alias. With It also found the same with Fixed in "Keep a ghost definition when the ghost is applied anywhere else". The equality is dropped only if the ghost function appears, on any arguments, in no other conjunct, not in Expected, and in no fact of Found except the argument's own equality with it.
Tests: 734 run, 0 failures. |
Codex review, round 3Soundness prompt. It found a ghost use hidden in a The other was in Found ( Fixed in "Keep a ghost definition when an alias may apply the ghost". Any alias application in the refinement, Expected or Found now counts as a possible use of the ghost, so the equality is kept.
Tests: 734 run, 0 failures. |
Codex review, round 4
Soundness prompt. It found one case. An unrelated class declares Fixed in "Never take a built-in function for a ghost of the same name". A name the refinement language provides ( Tests: 734 run, 0 failures. |
Codex review, round 5
Soundness prompt: "I found no new Java program that produces a false, misleading, or incorrectly attributed note." Nothing relevant is left, so this ends the Codex loop for this PR. |
…ives A refinement error whose Expected is about a call argument that is a call to a refined method now has the note "From: <call> (<File>:<line>) guarantees only <refinement>", instantiated as the error writes it. An equality _ == g(...) defining a ghost is left out when the ghost is nowhere else in the refinement: then it constrains no value, so what is left is exactly what the refinement says about the value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The conjunct _ == g(...) is left out only when g is a declared ghost (a built-in such as length may be interpreted), g(...) is in no other conjunct and not in Expected, and every fact of Found that mentions it is the argument's own equality with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tees ... Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4757b3b to
51666ee
Compare
7d24ec8 to
1861bb5
Compare
…rameter Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Origin rename (PM review), and Codex review of itWhat changed:
Codex review (one round):
Tests: 737 run, 0 failures. |
Closes #522, part 3: origin note F4, a value returned by a call. Design: #522 (comment)
Stacked on #528 (
CallResultand the Origin rename). Retarget this PR tomainbefore #528 is merged with--delete-branch, or GitHub closes it.A refinement error whose Expected is about a call argument that is itself a call to a refined method now says what that method's return refinement guarantees. This is the UX sign-off's amendment 1 for A2_10: instantiated as the error writes it, with the ghost-defining conjunct dropped.
When it is printed
For each variable of Expected that is an argument instance with no variable of its own (shown as the call), holding the
CallResultof a refined method whose refinement has a source position. Locals assigned from a call are left to #528's state notes. A refinement-error form for them (Origin: line 44, read() guarantees only n >= -1) is a question for the PM.It is also left out when the refinement still names an argument the verifier calls after the callee's parameter (
twice(0)for_ == b * 2), which would read as that parameter.Text:
Origin: <File>:<line>, <call> guarantees only <R'>, orOrigin: <File>:<line>, <call> guarantees nothing about <call>when nothing is left. This is the shape #528 gives every origin note.Why "only" is sound.
R'is the instantiated return refinement minus each conjunct_ == g(…)where all hold:gis a declared ghost (@Ghost), and never a built-in name likelength, even when some class declares a ghost of that name;g, on any arguments, appears in no other conjunct and not in Expected. Any arguments, because an alias of the receiver may constrain the ghost under another name;gis the argument's own equality with it;g.Then nothing constrains
g(…)but that equality, and ∃g. (_ == g ∧ Q()) ≡ Q(), sinceg := _is a witness. SoR'is exactly what the refinement says about the value. Nothing else is dropped. Otherwise the equality is kept, e.g.Origin: …, count(xs) guarantees only count(xs) == length(xs).A2_10, before and after
Refinement Error: found failures.size() == size(this.failures) && failures.size() >= 0 but expected failures.size() > 0 + Origin: ArrayListRefinements.java:162, failures.size() guarantees only failures.size() >= 0 75 | public Failure get() {This is the amended mock-up, in the Origin shape. The other notes are unchanged from #528, and every task still gives one error on its
reportedLine.Across all refinement-error fixtures, the only new notes are the two call arguments in
classes/found_binders_error:items.size()andcount().Test
TestOriginNotes.callArgumentIsTracedToWhatItsReturnRefinementGuaranteesAboutIt, on the existingclasses/found_binders_error(the A2_10 reproducer, line 25):Origin: ArrayListRefinements.java:13, items.size() guarantees only items.size() >= 0. It fails without the change.mvn test: 737 run, 0 failures.Conflicts
RefinementErrorheadline): none in the files changed here.MethodsFunctionsChecker.createVariableRepresentingArgumentgets one line, andUtilsgetsisBuiltin(name)over its existingDEFAULT_NAMES.🤖 Generated with Claude Code