Rollup merge of #160232 - lazureykis:fix/rustdoc-escape-char-boundary, r=notriddle rustdoc: fix ICE when a grapheme cluster joins a Prepend-class character to `_` or `:` Fixes #160231 `EscapeBodyTextWithWbr` iterates `text.grapheme_indices(true)`, so `i` is the start of a grapheme cluster, but the `_`/`:` word-break arm sliced at `i + 1` — hard-coding the assumption that a cluster containing `_` or `:` is exactly one byte long. UAX#29 GB9b joins a `Prepend`-class character (`U+0600`–`U+0605`, `U+0D4E`, `U+111C2`, …) with the character that follows it, so a cluster can start with a multi-byte character and still contain `_`. `i + 1` then lands inside that character and `str` indexing panics. `U+0D4E` is `XID_Continue`, so this is reachable from an ordinary item name that rustc accepts: ```rust pub struct abcൎ_defgh; ``` rustdoc ICEs on that with `end byte index 4 is not a char boundary; it is inside 'ൎ' (bytes 3..6 of string)`, which means `cargo doc` cannot document the crate at all. Break after the whole cluster (`i + s.len()`) instead. The adjacent CamelCase arm already slices at `i`, which is always a cluster boundary, so it needed no change. The `i + 1` dates to 3bf8bcf (which added the `:` arm) and was extended to `_` by ac303df , both in #126247. This also fixes a smaller, non-panicking case: when a combining mark trails the `_` (`first_◌̀second`), the old code inserted the `<wbr>` between `_` and its combining mark, splitting a grapheme cluster. Tests: unit cases in `src/librustdoc/html/escape/tests.rs` covering a `Prepend`+`_` cluster, a `Prepend`+`:` cluster, and the trailing-combining-mark case; plus an end-to-end regression test in `tests/rustdoc-html/` so the ICE itself stays fixed. The existing tests missed this because they only cover `Extend`-class clusters, which join backwards onto an ASCII base character and so keep `i + 1` on a boundary (`E("ṼẽçÑñéå")`, `E("V\u{0300}e\u{0300}…")`). `Prepend` is the one class that joins forwards. The property test `escape_body_text_with_wbr_makes_sense` can't reach it either — its alphabet is `[b'a', b'A', b'_']`. r? rustdoc