Handle character ranges starting at '\x00'

Do not calculate start-1 unless needed; start-1 may not be well-defined.
I think `start-1` should be `convert(T, start-true)` to avoid type instability and unnecessary checked conversion. This seems like it was an oversight in the previous code.

Also if we go this route and keep Char arithmetic checked, then we should check whether there's meaningful overhead to branching here instead of using `ifelse`. My guess is that there isn't, since the branch no longer interferes with inlining, in many cases the branch can be hoisted or eliminated, and in most remaining cases it should be predictable, but if there is meaningful overhead maybe we should keep using `ifelse` for `Union(Signed, Unsigned)`. Or just implement `coerce` and use that.