rust-lang / libs-team

The home of the library team
Apache License 2.0
116 stars 18 forks source link

ACP: `char::MIN` #252

Closed clarfonthey closed 1 year ago

clarfonthey commented 1 year ago

Proposal

Problem statement

Several standard primitive types offer MIN and MAX constants, which have a variety of use cases across the ecosystem. Unfortunately, char only offers a MAX constant, and not MIN.

Motivating examples or use cases

While Rust doesn't offer generic traits for minimum/maximum bounds on types, the standard MIN and MAX constants make implementing such functionality across a wide variety of types easy, since macros can simply expect <$t>::MIN and <$t>::MAX to exist. Unfortunately, char only has MAX, not MIN.

One of the arguments for why char::MAX exists is that it's difficult to remember and easy to mess up. For example, the literal '\u{10FFFF}' could easily be accidentally typed as \u{10FFF} and would be easy to miss. However, char::MAX is much harder to mistype without breaking, and is much clearer about its intent.

Compare this to the minimum value '\0' which is substantially easier to remember and a lot clearer. However, keep in mind that unsigned integers have an even simpler minimum, 0, and these also have MIN constants.

Solution sketch

impl char {
    const MIN: char = '\0';
}

Alternatives

The primary alternative is to simply not offer this constant, if the motivation doesn't justify it.

Links and related work

N/A

What happens now?

This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.

Possible responses

The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):

Second, if there's a concrete solution:

BurntSushi commented 1 year ago

SGTM

ChrisDenton commented 1 year ago

I'm wondering where this would be used? Are there any more concrete examples?

I get the point about rounding out the API but I don't think that's enough justification in itself. And all the places where maybe char::MIN could be used I think '\0' is clearer, as you say. More so than a 0 integer even because \0 is usually spelled "nul" or "null" in English rather than "min".

I guess macro use would be the strongest argument but it's not really an integer so it doesn't really make sense to me to have it in a macro with integer types. Maybe there is a real world example of where this would be useful?

BurntSushi commented 1 year ago

I'd probably use it here: https://github.com/rust-lang/regex/blob/a1910244f873e003efbe6e80ad9302c8ea949430/regex-syntax/src/unicode.rs#L708

I suspect there isn't really a case where char::MIN is strictly required.

ChrisDenton commented 1 year ago

You're not even using char::MAX though, which I think is much more justifiable. And arguably char::NULL would make more sense in that case, especially as it's closer to ascii::char::Null.

ChrisDenton commented 1 year ago

Or maybe that's an argument for having an ascii min too.

BurntSushi commented 1 year ago

You're not even using char::MAX though

Because it's IMO weird to write ('\0', char::MAX). See parallelism. (The same concept applies to coding IMO, but because of the confusable word, it's difficult to quickly find a better source.)

ChrisDenton commented 1 year ago

Ah I see, so you'd also want something like ASCII_MAX.

clarfonthey commented 1 year ago

Just earlier I was manually implementing a trait for char that worked with a macro for other integer types because of the presence of MIN and MAX. Even the NonZero* types have MIN and MAX but char doesn't.

ChrisDenton commented 1 year ago

I guess "other integer types" is what I'm not getting. To my mind char is not an integer type.

clarfonthey commented 1 year ago

True, but there are many traits that you would implement for integers that you might implement for char. In my case, I was allow-listing types for something that could represent the state of an automaton, but I know that a lot of other code encapsulating "something integer-like that has strict bounds" also includes char.

Sure, it's one special case, but it's still not clear it's worth putting your foot down and not having a MIN value if people definitely would use it.

ChrisDenton commented 1 year ago

Right but that's why I was asking for examples of where people would actually use it.

Also note that char has a hole in the middle so min and max don't adequately describe its bounds.

BurntSushi commented 1 year ago

Process note: I think you just need sign off from one libs-api member (me in this case) to move forward with creating a PR and a tracking issue. My understanding is that debate carries on there as opposed to here.

(I'm happy to corrected on process. I just wanted to throw this out there as my understanding at present.)

BurntSushi commented 1 year ago

That is, I agree that this is a plausible addition and that it's worth moving forward. But still fully expect to need consensus before stabilizing.

scottmcm commented 1 year ago

Also note that char has a hole in the middle so min and max don't adequately describe its bounds.

I think that argument was already lost with the stabilization of https://doc.rust-lang.org/std/num/struct.NonZeroI32.html#associatedconstant.MIN in 1.70.

char::MIN..=char::MAX would be a thing that would iterate all possible chars.

ChrisDenton commented 1 year ago

Process note: I think you just need sign off from one libs-api member (me in this case) to move forward with creating a PR and a tracking issue. My understanding is that debate carries on there as opposed to here.

(I'm happy to corrected on process. I just wanted to throw this out there as my understanding at present.)

The current process is that you should add the tag "ACP-accepted" and close this issue.

programmerjake commented 1 year ago

Right but that's why I was asking for examples of where people would actually use it.

quick example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2337422cf15e939e0d099b061ae7dc83