Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in from_str_radix if radix > 18; avoid unfortunate interaction #90

Merged
merged 1 commit into from
Apr 26, 2022

Conversation

bluss
Copy link
Contributor

@bluss bluss commented Jul 2, 2021

from_str_radix: Error if radix is > 18

Radix 19 and 20 introduce 'i' and 'j' as digits and this conflicts with
how complex are parsed. Before this fix, it could parse
Num::from_str_radix("1ij + 1ij", 20) in a pretty surprising way.

The Num docs already describe a rule for our situation - we might not
support every radix in our implementation; we can return an error in
this case instead.

A new (internal) error kind is introduced for this.

It is necessary to preserve the previous panicking behaviour(?) for
radix > 36 (this is what primitive types do - but other types are
allowed to do differently, including never panicking).

@bluss
Copy link
Contributor Author

bluss commented Jul 2, 2021

Where and if to panic and where to check for the error involves some nonobvious choices. I'd prefer if "radix <= 18" is a precondition to calling "from_str_generic", i.e that this function doesn't have to care for possible 'i' as a digit and so on.

I'd also be fine to just have radix <= 16 as the requirement if that just seems easier to understand.

One alternative not explored here is to invent a new format for complex numbers - and use that for radix > 18. I don't have a great suggestion, but imagine if it was something like 1 + 0# where # is the imaginary unit - it needs to be some symbol that's not in ascii alphanumerics, unfortunately.

Playground link - showcase weird parses

As an example of a weird parse, "1i" is 38 as a real number in the type i32 with radix 20. But "1i + 1i" parses as the complex 38 + i in type Complex<i32> radix 20.

radix: 20
input: 1i
i32					Ok(38)
num_complex::Complex<i32>		Ok(Complex { re: 0, im: 1 })

radix: 20
input: 1j
i32					Ok(39)
num_complex::Complex<i32>		Ok(Complex { re: 0, im: 1 })

radix: 20
input: 1i + 1i
i32					Err(ParseIntError { kind: InvalidDigit })
num_complex::Complex<i32>		Ok(Complex { re: 38, im: 1 })

radix: 20
input: 1ij
i32					Ok(779)
num_complex::Complex<i32>		Ok(Complex { re: 0, im: 38 })

radix: 20
input: 1ij + 1ij
i32					Err(ParseIntError { kind: InvalidDigit })
num_complex::Complex<i32>		Ok(Complex { re: 779, im: 38 })

radix: 20
input: 1ji
i32					Ok(798)
num_complex::Complex<i32>		Err(ParseComplexError { kind: ExprError })

radix: 20
input: 1ji + 1ji
i32					Err(ParseIntError { kind: InvalidDigit })
num_complex::Complex<i32>		Err(ParseComplexError { kind: ExprError })

@bluss bluss force-pushed the complex-1ij-plus-1ij branch 3 times, most recently from 66afe4c to fa553ec Compare July 2, 2021 17:30
@cuviper
Copy link
Member

cuviper commented Jul 2, 2021

That's an unfortunate oversight, but I agree that an error is the most reasonable thing we can do.

/// `radix` must be <= 18; Larger radix would include *i* and *j* as digits,
/// which can not be supported.
///
/// The conversion returns an error if 18 <= radix <= 36; it panics if radix > 36.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's note that error/panic conditions are inherited from T as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good point. I don't feel like I have the best formulations today, but I gave it a shot :)

@bluss bluss force-pushed the complex-1ij-plus-1ij branch 6 times, most recently from ecfd081 to ada1db0 Compare July 3, 2021 11:03
Radix 19 and 20 introduce 'i' and 'j' as digits and this conflicts with
how complex are parsed. Before this fix, it could parse
`Num::from_str_radix("1ij + 1ij", 20)` in a pretty surprising way.

The `Num` docs already describe a rule for our situation - we might not
support every radix in our implementation; we can return an error in
this case instead.

A new (internal) error kind is introduced for this.

It is necessary to preserve the previous panicking behaviour for
radix > 36 (this is what primitive types do - but other types are
allowed to do differently, including never panicking).
@cuviper
Copy link
Member

cuviper commented Jul 8, 2021

So I'm curious, how did you come to realize this? If it was in real use, then someone really did want a larger radix?

@bluss
Copy link
Contributor Author

bluss commented Jul 9, 2021

Oh, for some reason I was reading the from_str implementation and looked at how it handles i vs j (it looks hacky, but seems to cover all the cases). So I just noticed it, and I don't know any use case for this. Instead of an annoying bug report I wrote a PR directly.

I have a feeling that the "<= 18" limit is irregular and it would seem better to only support <= 16

@cuviper
Copy link
Member

cuviper commented Apr 26, 2022

bors r+

@bors
Copy link
Contributor

bors bot commented Apr 26, 2022

@bors bors bot merged commit f92c43c into rust-num:master Apr 26, 2022
@bluss bluss deleted the complex-1ij-plus-1ij branch April 27, 2022 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants