-
Notifications
You must be signed in to change notification settings - Fork 16
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
Poor diagnostics due to CompileTimeAssert
and weird try_from
/ try_new
#36
Comments
Hello, The reason for the awkward from/tryfrom semantics is because of a Rust limitation: A type can not implement both From and TryFrom at the same time. Ideally, we'd want The const asserts are a workaround for this - if some future compiler version does support this, we can switch over without the risk of breaking client code. |
Ah that's a shame. What do you think about generalizing the input parameter of Just as an example of how that might look like I tested fn try_new<T, E>(value: T) -> Result<Self, TryNewError>
where
T: TryInto<Self::UnderlyingType, Error = E>,
E: Into<TryNewError>; with impls like fn try_new<T,E>(value: T) -> Result<Self, TryNewError>
where
T: TryInto<Self::UnderlyingType, Error = E>,
E: Into<TryNewError>
{
value.try_into().map_err(E::into).and_then(|value| if value <= Self::MAX.value {
Ok(Self { value })
} else {
Err(TryNewError{})
})
} which requires two impls for the error types of the primitive type conversions impl From<Infallible> for TryNewError {
fn from(_: Infallible) -> Self {
unreachable!() // Infallible is an empty type
}
}
impl From<TryFromIntError> for TryNewError {
fn from(_: TryFromIntError) -> Self {
TryNewError
}
} and is a strict generalization of the current API if I'm not mistaken. (I didn't manage to get it working with the |
Hey, sorry for the late response! try_new being non-const is a step down, but maybe not a massive one, given how Result isn't exactly full of const functions either. So if someone wants a const new, they can probably just use regular It would have to be a major version bump though - which would be a good idea anyway as there are a couple of other changes that require that as well. |
just ran into some trouble caused by this const assertion, and i think this really is not the way to solve the problem, since it has terrible debuggability:
i propose that the implementations should be specific to every type instead of generic over the bit length, probably using a macro to auto generate them. that is, the only downside i can see here is that this would generate a lot of implementations: a type with N bits will have 127 implementations, N of them edit: alright, this is not viable at all! did a simple test and compilation times get a real big hit from that many implementations. oh well. |
Thanks for trying this out. Reducing the number of classes in other crates that implement similar types was the big motivation for arbitrary_int in the first place. As Rust's const generics get more powerful, things like this issue can hopefully be addressed in a cleaner way. |
I just ran into some problems when trying to do something like
This induced an error
from deep inside
arbitrary-int
's source without any source spans for the user code, which made finding the problem rather hard. I don't see why there's a compile time assert like that on an explicitly fallible conversion. Judging from the error message it seems like thetry_from
is internally usingfrom
which seems rather odd to me.I also tried using
try_new
rather thantry_from
, however this would requires chaining multiple conversions when a single one should do: try to getu16
fromu32
and then try to getu10
fromu16
. Since the error types betweenu10::try_new
andu16::try_from
don't match up this requires some rather ugly code (even when discarding the errors):The text was updated successfully, but these errors were encountered: