v0.35.0 Phase 3 Character-property and Borrowed-trim Review
Result: complete with no open Phase 3 finding (2026-09-05). Unicode 17.0.0 character properties and borrowed Unicode whitespace trimming are implemented as ordinary standard-library source over the Phase 2 lookup product. No parser, checker, backend, editor, or operating-system locale gained Unicode behavior.
Closed Product
The public char root declares five allocation-free property methods. A dedicated property source converts each scalar to its code point and calls one package-visible semantic function in std/internal/unicode. Only those five lookup functions gained package visibility; casing and context helpers remain module-local until Phase 4 has real consumers.
The public str root declares trim_start, trim_end, and trim. Their implementation composes the existing Chars iterator, public character property contract, scalar UTF-8 width, and the one unchecked subview helper already guarded by the borrowed-text module. The implementation neither reads generated ranges nor decodes UTF-8 through another algorithm. Start-only trimming stops at the first retained scalar, end-only trimming makes one complete pass, and two-sided trimming computes both boundaries in one complete pass.
Existing ASCII predicates and trimming implementations are unchanged. They remain independent of the pinned Unicode version and do not reach generated tables.
Findings Closed During Implementation
- The practical string chapter still claimed that
charwas unsupported despite the complete v0.34.0 scalar contract. The obsolete denial now points to the owning Unicode chapters without duplicating their APIs. - An initial internal trim helper accepted a caller-supplied lower boundary. That contract could produce an invalid range if reused incorrectly and made two-sided trim rescan its leading prefix. It was replaced before completion by self-contained start, end, and single-pass bounds computations.
- A proposed duplicate character-property test module repeated cases already owned by the exhaustive generated-data oracle and native public-API test. It was removed; each layer now tests a distinct boundary rather than preserving an unexecuted duplicate suite.
Evidence
- the Phase 2 generator compares every Unicode scalar with the independently parsed property corpus before accepting generated ranges;
- the internal lookup native test crosses static data, slice projection, binary search, MIR, machine layout, ARM64, and Mach-O execution;
- the public scalar native test exercises all five
charmethods with Unicode members and property complements; - standard
strtests cover leading, trailing, two-sided, all-whitespace, and non-White_Space inputs containing multi-byte scalars; - complete native text execution verifies exact results and returned pointer offsets into the original text;
- standard source checking proves the public
noallocdeclarations against their transitive implementation calls and validates the exact newchar -> internal/unicodemodule edge; - the complete workspace, warnings-denied Clippy, no-default-features, Rustdoc, generated-data, documentation, and repository-integrity gates pass at the reviewed commit.
Boundary Result
The Unicode generator owns UCD interpretation, the internal Unicode module owns generated lookup, char owns public property meaning, and str owns borrowed byte boundaries. Each consumer sees only the preceding contract. There is one UTF-8 decoder, one property lookup authority, one borrowed subview construction boundary, and no allocation path in the new APIs.