I'm a Rust newbie! What's the best way to convert from an Option<T> to a Result<T, ()>?
The TryFrom trait seems prevalent and returns a Result. The popular num_traits' NumCast has many conversions but they all return an Option<T>. Similarly, as do the NonZero* constructors such as NonZeroI32 in the Rust Standard Library. I then noticed that NumCast implements a from() that returns an Option<T> so I was thinking that maybe it had a non-standard way of doing things in general but then I saw the NonZero* implementations and questioned that idea.
Regardless, converting from Options to Results seem frequent and I haven't found a neat way to do yet. E.g.:
/// Add common conversion from an i32 to a non-zero i32.
impl TryFrom<Container<i32>> for Container<NonZeroI32> {
type Error = ();
fn try_from(container: Container<i32>) -> Result<Self, ()> {
// NonZeroI32::new() returns an Option not a Result. Try a helper.
Ok(Self(option_to_result(NonZeroI32::new(container.0))?))
}
}
/// Helper function to convert from an Option to a Result (both types are
/// foreign and so is From).
fn option_to_result<T>(option: Option<T>) -> Result<T, ()> {
if let Some(some) = option {
Ok(some)
} else {
Err(())
}
}
/// Add another common conversion from an i32 to an i16.
impl TryFrom<Container<i32>> for Container<i16> {
type Error = ();
fn try_from(container: Container<i32>) -> Result<Self, ()> {
// NumCast::from() also returns an Option not a Result. Try map_or() instead
// of the helper.
Ok(Self(NumCast::from(container.0).map_or(Err(()), |x| Ok(x))?))
}
}
(Above examples in the Rust Playground.)
These NumCast, NonZero*, and TryFrom conversions seem common enough but my approach feels clumsy as though I'm pitting the Option and Result types against each other. I struggle with these conversions and also miss the fundamental point of the Option type given Result<T,()> feels similar.
So, what's the idiomatic way to convert an Option<T> to Result<T,()> in Rust 2018?
Option has the ok_or method, usable for exactly this (well, for more wide case, in fact, but your request fits here too):
fn option_to_result<T>(option: Option<T>) -> Result<T, ()> {
option.ok_or(())
}
Modified playground
Related
I want to wrap value in Ok like this
12.ok()
Am I able to do this or I can only use Ok(12)?
I would strongly recommend against this. Result is a very well known type in the Rust ecosystem with a lot of conventions, idioms and patterns. This is decidedly not one of them and will be confusing for anyone who comes across it, especially because Result::ok already is a method. So this is doubly terrible.
Just because you can do something, doesn't mean you should.
That warning said, you could do this:
trait Okable<Err> {
fn ok(self) -> Result<Self, Err> where Self: Sized {
Ok(self)
}
}
impl<T, Err> Okable<Err> for T {}
fn main() {
let _x: Result<_, ()> = 12.ok();
}
I want to have something like optional trait bound for function. Where if T implements that type - do something.
fn test<T: Eq + ?Debug>(a:T, b:T){
if a!=b{
println!("Not equal!");
if (T impl Debug){
println!("{:?} != {:?}", a, b);
}
}
}
As #user4815162342 commented, using specialization, this is possible.
I'll provide a slightly different approach from what they specified in their comment, to keep the same if ... { ... } setup that you had in your original code.
The idea is to have a trait AsMaybeDebug with an associated type Debug, which always implements Debug and a function to go from &Self to Option<&Self::Debug>:
trait AsMaybeDebug {
type Debug: Debug;
fn as_maybe_debug(&self) -> Option<&Self::Debug>;
}
After this we make a default impl for all T, with the debug type being !, the never type, and always return None.
impl<T> AsMaybeDebug for T {
default type Debug = !;
default fn as_maybe_debug(&self) -> Option<&Self::Debug> {
None
}
}
Instead of the never type, you could choose any type that always implemented Debug but still returning None.
Afterwards we specialize for T: Debug by returning Self:
impl<T: Debug> AsMaybeDebug for T {
type Debug = Self;
fn as_maybe_debug(&self) -> Option<&Self::Debug> {
Some(self)
}
}
Finally in test we just call as_maybe_debug and check if T: Debug
fn test<T: Eq>(a: T, b: T){
if a != b {
println!("Not equal!");
if let (Some(a), Some(b)) = (a.as_maybe_debug(), b.as_maybe_debug()) {
println!("{:?} != {:?}", a, b);
}
}
}
You can check in the playground both that it works and that the assembly generated for test_non_debug doesn't have any debugging calls, only the single call to std::io::_print.
It unfortunately isn't possible to retrieve the original a or b inside the if after calling as_maybe_debug.
This is due to <Self as AsMaybeDebug>::Debug not being
convertible back to Self.
This can be fixed, but not easily as it requires updates from the standard library.
Requiring AsMaybeDebug::Debug: AsRef<Self> doesn't work for 2 reasons:
There is no impl<T> AsRef<T> for T yet, this is due to specialization still being incomplete, I assume.
There is no impl<T> AsRef<T> for ! yet. Not sure if this impl can be made even with specialization or not, but it would be required.
Also, although the specialization can be unsound, I believe that the trait and it's impls cannot be used for unsoundness, you would need a specific setup to be able to generate unsoundness from it, which this lacks.
As mentioned in the comments, you're looking for the impls crate, which does exactly what you want.
if impls!(T: Debug) {
...
}
Just for the sake of completeness, here's how you do it without an external crate dependency. I'm paraphrasing from the way the impls developer explains the trick.
Let's say we want to check whether some type implements Debug. First, let's define the "base case".
trait NotDebug {
const IMPLS: bool = false;
}
We'll also provide a blanket implementation so that all types (which don't have a better answer) have a IMPLS constant equal to false.
impl<T> NotDebug for T {}
Now, let's make a simple type with a single generic type parameter.
struct IsDebug<T>(std::marker::PhantomData<T>);
PhantomData is conceptually nonexistent and exists only to anchor the generic type T to our IsDebug. We can think of IsDebug as being effectively a singleton struct.
Now, we would like IsDebug::<T>::IMPLS to be true if (and only if) T implements Debug. Currently, IsDebug::<T>::IMPLS is always false, by a blanket implementation of NotDebug. But we can specify an inherent impl that applies conditionally.
impl<T: Debug> IsDebug<T> {
const IMPLS: bool = true;
}
Since this is an impl on IsDebug itself, not on a trait implementation, it takes precedent over the NotDebug blanket implementation. In any case where T: Debug, the inherent impl kicks in and we get true. In any other case, the inherent impl fails, so we get the fallback blanket implementation which gives false.
Try it in the Rust Playground!
This trait is implemented since 1.12.0:
impl<T> From<T> for Option<T> {
fn from(val: T) -> Option<T> {
Some(val)
}
}
How idiomatic is this as an argument? Consider this example:
fn do_things(parameters: &Foo, optional_argument: impl Into<Option<Duration>>) {
let optional_argument = optional_argument.into();
// use it...
}
If you see the documentation, it's (more or less) clear (if you know, that this trait is implemented). But if you see the code, you may be confused:
do_things(params, Duration::from_millis(100));
Is this fine to use or should it be avoided?
This pattern is uncommon, but reasonably easy to understand. If it's convenient in the context of your library's usage, it should be OK.
I think it's more common to have do_stuff and do_stuff_with_timeout functions.
In mutagen, I'm injecting various
mutations in the code. One thing I'd like to mutate is the pattern
if let Ok(x) = y { .. }. However, this poses quite the challenge, as I
cannot know the type of y – the user could have built their own enum with an
unary Ok variant. I can still opportunistically mutate it for cases where we
actually have a Result whose error type implements Default using a trait
that looks like the following simplified:
#![feature(specialization)]
pub trait Errorer {
fn err(self, mutate: bool) -> Self;
}
impl<X> Errorer for X {
default fn err(self, _mutate: bool) -> Self {
self
}
}
impl<T, E> Errorer for Result<T, E>
where
E: Default,
{
fn err(self, mutate: bool) -> Self {
if mutate {
Err(Default::default())
} else {
self
}
}
}
Alas, there aren't that many errors which implement Default, so this is
not too useful. Even an implementation for Result<T, Box<Error>> would give
us more bang for the buck (and be completely possible). However, given that I
don't care much about code actually inspecting the error, I wonder if I could
do a general implementation by extending the mutation of the above code to
match Errorer::err(y, mutation) {
Ok(x) => { .. }
Err(x) => { mem::forget(x); }
}
and have err return Err(mem::uninitialized()) when mutating – so is this
behavior safe? Note: I'm returning Err(mem::uninitialized()) from a method,
only to mem::forget it later. I see no way this could panic, so we should
assume that the value will be indeed forgotten.
Is this defined behavior or should I expect nasal demons?
No, this is not defined behavior, at least not for all types. (I can't tell how your code would be called as part of mutation, so I don't know if you have control over the types here, but the generic impl sure makes it look like you do not.) That's demonstrated by the following piece of code:
#![feature(never_type)]
use std::mem;
fn main() {
unsafe { mem::forget(mem::uninitialized::<!>()) }
}
If you run this on the playground, you will see the program die with a SIGILL. The ASM output shows that LLVM just optimized the entire program to immediate SIGILL because of the way it uses a value of the uninhabited type !:
playground::main:
ud2
Generally speaking, it is near impossible to correctly use mem::uninitialized in generic code, see e.g. this issue of rc::Weak. For this reason, that function is in the process of being deprecated and replaced. But that won't help you here; what you want to do is just outright illegal for Result<T, !>.
I have a struct:
struct Foo {}
struct Boo {
foo: Option<Foo>,
}
I want to create getter for it, so user cannot modify it but can read it:
impl Boo {
pub fn get_foo(&self) -> ? { unimplemented!(); }
}
Should I return &Option<Foo> or Option<&Foo>? Are there any advantages between these two variants?
I use both variants in my program, and it became an inconvenience to mix them, so I want to choose one of them for the entire program.
Use Option<&T> instead of &Option<T>. Callers are interested in the wrapped value, not in Option.
Also, the common way to implement a getter like this is as follows:
impl Boo {
pub fn get_foo(&self) -> Option<&Foo> { self.foo.as_ref() }
}
This way you don't need to check the wrapped value in the getter. If you want to return a mutable value, use as_mut() instead.
When in doubt, pick the most flexible solution. This leaves you the most leeway in the future to change the internals of the struct without altering its API.
In this case, this means picking Option<&T>:
&Option<T> forces you to have a reference to an option,
Option<&T> only requires a reference to a T.
So, for example, in the latter case I could store a Vec<T> or a Result<T, Error> and still be able to hand out a Option<&T>. It is more flexible.
Note: this is why interfaces generally use &str instead of &String, &[T] instead of &Vec<T>, ... more flexibility!