Repository navigation
File path helpers convert arguments the way CRuby does, and raise TypeError where CRuby does (fixes #57) - #148
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
… raise `TypeError` where CRuby does
The four path helpers coerced every argument with `to_s`, so a non-String
path answered a value where CRuby raises `TypeError`:
File.dirname(123) model "." CRuby TypeError: no implicit conversion of Integer into String
File.basename(123) model "123" CRuby TypeError: no implicit conversion of Integer into String
File.extname(:sym) model "" CRuby TypeError: no implicit conversion of Symbol into String
File.join(1, 2) model "1/2" CRuby TypeError: no implicit conversion of Integer into String
`AGENTS.md` rule 3 says the model declines rather than approximates. Here it
answered, which is the wrong direction: a program outside the domain ran to a
value on the model and to an exception on CRuby, so a differential test counted
it as a disagreement rather than a named `Unsupported`.
CRuby resolves a path through `FilePathValue` (`rb_get_path`): a String stands;
otherwise `to_path`, and failing that `to_str`, must answer a String; anything
else is `TypeError: no implicit conversion of X into String`, where X is the
*converted* value's class when a conversion answered a non-String, and `nil`,
`true` or `false` for those immediates. `File.basename`'s suffix uses the
narrower `StringValue` (a String or `to_str`, never `to_path`), and an omitted
suffix now differs from an explicit `nil`, which raises. An object whose class
has no faithful name -- an anonymous class prints a native address -- gates
with a named reason instead of raising a message the model cannot reproduce.
`File.join` needed the rest of its CRuby contract so that this change does not
trade one wrong answer for another. CRuby joins each nested array to a String
*first* and then joins the results, so `join([[], []])` is "/" (two empty
strings), and it raises `ArgumentError: recursive array` on a cycle rather than
recursing forever. It also drops every trailing separator of the accumulated
result when the next name starts with one, so `join("a/", "/b")` is "a/b" while
`join("a//", "//b")` keeps two; the model previously produced "a////b" for
both. The rule is `rb_file_join` as written in CRuby 4.0.5.
The String cases and a modeled `Pathname` argument (`to_path`) answer exactly as
before, and unmodeled `File.` class methods still gate through the prelude's
`method_missing`.
Validation, from a toolchain built for this run (Lean v4.32.2, CRuby 4.0.5,
Python 3.12):
* `make check` -> `make check: ALL CHECKS PASSED`: lint, the generated sources
fresh, the model, every proof book (the booted-heap metatheory, the soundness
theorem and its controls, the comparator), the desugarer and emitter suites,
difftest's own tests at their coverage baseline, conformance
(`ran 1287, agree 1087, sut_unsupported 194, not_compared 6, disagree 0` --
exactly the recorded baseline; the regressions and tier-3 tiers agree), the
feature-loading check, the program books and the docs.
* `make check-not-weakened` -> `CHECKS NOT WEAKENED`.
* The new `difftest/corpus/regressions/file-path-argument-conversion.rb` pins 49
rows and is byte-identical under CRuby and the model. The separator rule was
also checked against CRuby over all 819 one-, two- and three-element tuples of
a nine-string separator alphabet, and the nested-array and recursion cases
over 374 more, with no disagreement.
Fixes #57
Authored by Jiro, an autonomous agent (Nori sessions), on behalf of @sam-xif.
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.
Problem
File.basename,File.dirname,File.extnameandFile.joincoerced every path argument withto_s, so a program whose argument was not a String ran to a value where CRuby raises:File.dirname(123)"."TypeError: no implicit conversion of Integer into StringFile.basename(123)"123"TypeError: no implicit conversion of Integer into StringFile.extname(:sym)""TypeError: no implicit conversion of Symbol into StringFile.join(1, 2)"1/2"TypeError: no implicit conversion of Integer into StringAGENTS.mdrule 3 says the model declines rather than approximates, so this is the wrong direction: a program outside the modeled domain answered instead of gating or raising.The change
ruby-lean/prelude/prelude.rbonly; the generatedPreludeJson.lean/Prelude.leanfollow.FilePathValue(rb_get_path): a String stands, otherwiseto_pathand thento_strmust answer a String, and anything else raises CRuby's byte-exactTypeError. The message names the converted value's class when a conversion answers a non-String, andnil/true/falsefor those immediates. An object whose class has no faithful name (an anonymous class prints a native address) gates with a namedUnsupportedinstead of a message the model cannot reproduce.File.basename's suffix uses the narrowerStringValue(String orto_str, neverto_path), and an omitted suffix now differs from an explicitnil, which raises.File.joingained the rest ofrb_file_joinso the coercion change does not trade one wrong answer for another: nested arrays are joined to Strings first (join([[], []])is"/", not""), a cycle raisesArgumentError: recursive array, and the separator rule is CRuby's (join("a/", "/b")is"a/b",join("a//", "//b")keeps two — the model produced"a////b"for both before).String arguments and the modeled
Pathname(viato_path) answer exactly as before, and unmodeledFile.class methods still gate through the prelude'smethod_missing.Test plan
difftest/corpus/regressions/file-path-argument-conversion.rb(sidecarstatus: "fixed"), run bymake conformance's regressions tier: 49 rows covering the four defect rows, the immediate/class naming,to_pathoverto_str, a badto_pathresult,to_s-only refusal, the suffix rules, the empty/nested-array cases, the separator rule and the recursive arrays.Validation
Toolchain built for this run: Lean
v4.32.2, CRuby4.0.5, Python3.12.make check→make check: ALL CHECKS PASSED(lint; generated sources fresh; the model; every proof book including the booted-heap metatheory, the soundness theorem and controls, and the comparator; the desugarer and emitter suites; difftest's own tests at their coverage baseline;conformance: ran 1287, agree 1087, sut_unsupported 194, not_compared 6, disagree 0— exactly the recorded baseline, with the regressions and tier-3 tiers agreeing; feature-loading; the program books; the docs).make check-not-weakened→CHECKS NOT WEAKENED.Fixes #57
Authored by Jiro, an autonomous agent (Nori sessions), including this description. Reviewed changes are welcome from @sam-xif.