Repository navigation
Fix byte/char index desync in last_two_items_of_path_match - #4828
Conversation
feliperodri
left a comment
There was a problem hiding this comment.
Approving — this is a clean fix for a real defect, and the tests earn their place.
Verified rather than read: I extracted the old and new splitting loops into a standalone binary and ran them side by side.
- Both new tests fail on
main:café::núm::NonZero::<u32>::unchecked_addpanics on the char-boundary slice (0..4), andéa::NonZero::<u32>::unchecked_addsilently mis-splits and returnsfalse. So each pins a distinct failure mode, which is what your description claims. - The existing ASCII fixtures are bit-identical before and after, which is the important non-regression: this function decides every
proof_for_contractandstubtarget. - Three further multibyte shapes also go from broken to correct:
é::…andaé::bé::…panicked, andm::S::<'🦀'>::fand🦀::S::<u32>::freturned the wrong answer. cargo test -p kani-compiler resolveis green on the branch merged with currentmain(6/6, including your two).
GitHub currently shows this as conflicting, but git merge upstream/main applies cleanly here, so I think that status is stale — a merge or rebase should clear it. Note main has moved to nightly-2026-09-22 since you opened this.
Nothing blocking. Two suggestions inline: a note on why the remaining i - 1 byte arithmetic is still safe, and a third test for the char const-generic shape your description names as the realistic trigger.
One heads-up: #4778 rewrites the same comparison (it adds normalization on both sides of both paths and factors the splitting out). Whichever lands second will need a small rebase, and it would be worth making sure the prev fix survives into the normalized helper rather than being reintroduced from the old code.
53885c9 to
98b8947
Compare
|
Rebased onto current On the merge you flagged: I checked the rebased tree. The CI runs The one case this string layer still can't reach, a trait object nested inside another argument, stays tracked in #4830. I left it out to keep this PR focused on the fix. |
98b8947 to
b6559d3
Compare
last_two_items_of_path_match's::-splitting loop iteratedchar_indices()(byteoffsets) but guarded with
chars().nth(i - 1)(a char count). A multibyte characterin an item path desyncs the two, so the guard fires at the first colon of a
::—producing a char-boundary panic or a silently dropped path component depending on the
byte layout (both traces are in the issue). Item paths can carry multibyte characters
via unicode identifiers or non-ASCII
charconst-generics.The guard now carries the previous character from the loop's own iteration and all
slice bounds stay byte-derived. On pure-ASCII paths byte offsets and char counts
coincide, so the old guard already read exactly the previous character there — the
check is equivalent and behavior is unchanged. Two multibyte regression tests added
to the existing
simple_last_two_items_of_path_matchmodule.Manual test: the original and fixed loops were extracted verbatim into a standalone
binary and compared — identical output on 10 ASCII paths (including this module's
fixture paths and an arrow-bearing form), correct splits on 4 multibyte paths that
previously panicked or mis-split.
Resolves #4827
By submitting this pull request, I confirm that my contribution is made under the
terms of the Apache 2.0 and MIT licenses.