How to make the inner value of a Result must_use - rust

I can use the #[must_use] attribute to mark a function as having a return value that must either be used or explicitly ignored:
#[must_use]
fn plain() -> i32 {
1
}
fn main() {
plain(); // warning
}
However, if I want to change my function so it now returns a Result, I cannot do this:
#[must_use]
fn result() -> Result<i32, ()> {
Ok(1)
}
fn main() {
result().unwrap();
}
because the call to .unwrap() counts as a "use", and the #[must_use] attribute is applying to the entire Result.
Is there a way to make #[must_use] apply to the inner type as well? Essentially I would like to make sure that the i32 is not accidentally "eaten" by the semicolon.
I have the additional constraint that I cannot change the public API of this function, so I can't make it return a Result<MustUse<i32>, ()> or something along those lines.

You can't do this by directly adding your own annotation to the Result, but you can do this trivially with a newtype:
#[must_use]
#[repr(transparent)]
pub struct MustUse<T>(T);
impl<T> From<T> for MustUse<T> {
fn from(v: T) -> Self {
Self(v)
}
}
impl<T> MustUse<T> {
#[must_use]
fn into_inner(self) -> T {
self.0
}
}
Now, given this declaration:
fn result() -> Result<MustUse<i32>, ()> {
Ok(1.into())
}
All of the following cause a warning:
result(); warns because Result<_, _> is must-use.
result().unwrap(); warns because MustUse<_> is must-use.
result().unwrap().into_inner(); warns because MustUse<_>::into_inner() is must-use.
(Note that you can bypass the warning by invoking a different, non-must-use method of Result, such as result().ok(), but that will be true no matter what you do.)

Related

How to 'implement' functions from inner object onto the outer struct?

given this example
struct Outer<T>(*mut T);
impl<T> Outer<T> {
pub fn new(value: &mut T) -> Outer<T> {
Outer(value as *mut T)
}
}
struct Inner(pub i32);
impl Inner {
pub fn do_thing(&self) {
println!("did the thing {}", self.0);
}
}
fn main() {
let outer = Outer::new(Inner(2));
outer.do_thing() // error: do_thing doesnt exist
}
how would i expose the methods of Inner as methods of Outer
im trying to achieve what Box is doing
You have to reborrow the pointer in order to implement Deref (playground):
impl<T: ?Sized> Deref for Outer<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.0 }
}
}
Answer from before the edit below:
The clean way is to have methods that return the inner type:
impl<T> Outer<T> {
pub fn get(&self) -> &T {
&self.0
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.0
}
pub fn into_inner(self) -> T {
self.0
}
}
This is more useful when the inner type isn't pub (you can just do self.0 for the same effect as all three methods), but is a common pattern that users of rust libraries expect.
The other way is to implement Deref and DerefMut. This is messier because it's a very strong API commitment: you now have all the methods of the inner type added to the outer type unconditionally, and gain any future methods. It also means that any namespace collisions between the wrapper and the target are hard to notice, which is why things like Arc::get_mut are associated functions instead of methods. If you use this, consider changing methods on the wrapper to associated functions (don't take a self parameter).
impl<T> Deref for Outer<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}

How to use traits for function overloading in Rust? [duplicate]

I am modeling an API where method overloading would be a good fit. My naïve attempt failed:
// fn attempt_1(_x: i32) {}
// fn attempt_1(_x: f32) {}
// Error: duplicate definition of value `attempt_1`
I then added an enum and worked through to:
enum IntOrFloat {
Int(i32),
Float(f32),
}
fn attempt_2(_x: IntOrFloat) {}
fn main() {
let i: i32 = 1;
let f: f32 = 3.0;
// Can't pass the value directly
// attempt_2(i);
// attempt_2(f);
// Error: mismatched types: expected enum `IntOrFloat`
attempt_2(IntOrFloat::Int(i));
attempt_2(IntOrFloat::Float(f));
// Ugly that the caller has to explicitly wrap the parameter
}
Doing some quick searches, I've found some references that talk about overloading, and all of them seem to end in "we aren't going to allow this, but give traits a try". So I tried:
enum IntOrFloat {
Int(i32),
Float(f32),
}
trait IntOrFloatTrait {
fn to_int_or_float(&self) -> IntOrFloat;
}
impl IntOrFloatTrait for i32 {
fn to_int_or_float(&self) -> IntOrFloat {
IntOrFloat::Int(*self)
}
}
impl IntOrFloatTrait for f32 {
fn to_int_or_float(&self) -> IntOrFloat {
IntOrFloat::Float(*self)
}
}
fn attempt_3(_x: &dyn IntOrFloatTrait) {}
fn main() {
let i: i32 = 1;
let f: f32 = 3.0;
attempt_3(&i);
attempt_3(&f);
// Better, but the caller still has to explicitly take the reference
}
Is this the closest I can get to method overloading? Is there a cleaner way?
Yes, there is, and you almost got it already. Traits are the way to go, but you don't need trait objects, use generics:
#[derive(Debug)]
enum IntOrFloat {
Int(i32),
Float(f32),
}
trait IntOrFloatTrait {
fn to_int_or_float(&self) -> IntOrFloat;
}
impl IntOrFloatTrait for i32 {
fn to_int_or_float(&self) -> IntOrFloat {
IntOrFloat::Int(*self)
}
}
impl IntOrFloatTrait for f32 {
fn to_int_or_float(&self) -> IntOrFloat {
IntOrFloat::Float(*self)
}
}
fn attempt_4<T: IntOrFloatTrait>(x: T) {
let v = x.to_int_or_float();
println!("{:?}", v);
}
fn main() {
let i: i32 = 1;
let f: f32 = 3.0;
attempt_4(i);
attempt_4(f);
}
See it working here.
Here's another way that drops the enum. It's an iteration on Vladimir's answer.
trait Tr {
fn go(&self) -> ();
}
impl Tr for i32 {
fn go(&self) {
println!("i32")
}
}
impl Tr for f32 {
fn go(&self) {
println!("f32")
}
}
fn attempt_1<T: Tr>(t: T) {
t.go()
}
fn main() {
attempt_1(1 as i32);
attempt_1(1 as f32);
}
Function Overloading is Possible!!! (well, sorta...)
This Rust Playground example has more a more detailed example, and shows usage of a struct variant, which may be better for documentation on the parameters.
For more serious flexible overloading where you want to have sets of any number of parameters of any sort of type, you can take advantage of the From<T> trait for conversion of a tuple to enum variants, and have a generic function that converts tuples passed into it to the enum type.
So code like this is possible:
fn main() {
let f = Foo { };
f.do_something(3.14); // One f32.
f.do_something((1, 2)); // Two i32's...
f.do_something(("Yay!", 42, 3.14)); // A str, i32, and f64 !!
}
First, define the different sets of parameter combinations as an enum:
// The variants should consist of unambiguous sets of types.
enum FooParam {
Bar(i32, i32),
Baz(f32),
Qux(&'static str, i32, f64),
}
Now, the conversion code; a macro can be written to do the tedious From<T> implementations, but here's what it could produce:
impl From<(i32, i32)> for FooParam {
fn from(p: (i32, i32)) -> Self {
FooParam::Bar(p.0, p.1)
}
}
impl From<f32> for FooParam {
fn from(p: f32) -> Self {
FooParam::Baz(p)
}
}
impl From<(&'static str, i32, f64)> for FooParam {
fn from(p: (&'static str, i32, f64)) -> Self {
FooParam::Qux(p.0, p.1, p.2)
}
}
And then finally, implement the struct with generic method:
struct Foo {}
impl Foo {
fn do_something<T: Into<FooParam>>(&self, t: T) {
use FooParam::*;
let fp = t.into();
match fp {
Bar(a, b) => print!("Bar: {:?}, {:?}\n", a, b),
Baz(a) => print!("Baz: {:?}\n", a),
Qux(a, b, c) => {
print!("Qux: {:?}, {:?}, {:?}\n", a, b, c)
}
}
}
}
Note: The trait bound on T needs to be specified.
Also, the variants need to be composed of combinations of types that the compiler wouldn't find ambiguous - which is an expectation for overloaded methods in other languages as well (Java/C++).
This approach has possibilities... it would be awesome if there's a decorator available - or one were written that did the From<T> implementations automatically when applied to an enum. Something like this:
// THIS DOESN'T EXIST - so don't expect the following to work.
// This is just an example of a macro that could be written to
// help in using the above approach to function overloading.
#[derive(ParameterOverloads)]
enum FooParam {
Bar(i32, i32),
Baz(f32),
Qux(&'static str, i32, f64),
}
// If this were written, it could eliminate the tedious
// implementations of From<...>.
The Builder
Another approach that addresses the case where you have multiple optional parameters to an action or configuration is the builder pattern. The examples below deviate somewhat from the recommendations in the link. Typically, there's a separate builder class/struct which finalizes the configuration and returns the configured object when a final method is invoked.
One of the most relevant situations this can apply to is where you want a constructor that takes a variable number of optional arguments - since Rust doesn't have built-in overloading, we can't have multiple versions of ___::new(). But we can get a similar effect using a chain of methods that return self. Playground link.
fn main() {
// Create.
let mut bb = BattleBot::new("Berzerker".into());
// Configure.
bb.flame_thrower(true)
.locomotion(TractorTreads)
.power_source(Uranium);
println!("{:#?}", bb);
}
Each of the configuration methods has a signature similar to:
fn power_source(&mut self, ps: PowerSource) -> &mut Self {
self.power_source = ps;
self
}
These methods could also be written to consume self and return non-reference copies or clones of self.
This approach can also be applied to actions. For instance, we could have a Command object that can be tuned with chained methods, which then performs the command when .exec() is invoked.
Applying this same idea to an "overloaded" method that we want to take a variable number of parameters, we modify our expectations a bit and have the method take an object that can be configured with the builder pattern.
let mut params = DrawParams::new();
graphics.draw_obj(params.model_path("./planes/X15.m3d")
.skin("./skins/x15.sk")
.location(23.64, 77.43, 88.89)
.rotate_x(25.03)
.effect(MotionBlur));
Alternatively, we could decide on having a GraphicsObject struct that has several config tuning methods, then performs the drawing when .draw() is invoked.

Implementing a generic conversion from an object implementing the `Error` trait

I cannot get the following code to compile.
I get an error that From is already implemented.
If I remove the manual impl of From I get the error that From is not implemented.
If I do not implement Error it works fine.
I suppose that this is due to the blank impl impl<T> From<T> for T in core. How should I work around this? Not implementing Error is not really an option.
Code (playground)
use std::fmt;
use std::io;
use std::error::Error;
#[derive(Debug)]
enum ErrorType {
Other(Box<Error>)
}
impl fmt::Display for ErrorType {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("not implemented")
}
}
impl Error for ErrorType {
fn description(&self) -> &str {
use self::ErrorType::*;
match *self {
Other(ref err) => err.description(),
}
}
}
impl<E: Error + 'static> From<E> for ErrorType {
fn from(other: E) -> Self {
ErrorType::Other(Box::new(other))
}
}
fn ret_io_err() -> Result<(), io::Error> {
Ok(())
}
fn ret_error_type() -> Result<(), ErrorType> {
try!(ret_io_err());
Ok(())
}
fn main() {}
You don't.
That implementation would be a bit useless, anyway. It would mean that all other error types would just be immediately boxed. At that point, you might as well just make use of the existing conversions involving Box<Error> and use that instead.
If you want an error type that actually preserves the type of the unified errors, you'll need to implement From once for each of them. The error-type crate can help with defining unifying error types.
According comments above I've found this one approach works only:
impl<T: error::Error + 'static> From<Box<T>> for Error {
fn from(e: Box<T>) -> Self {
Error::Other(e)
}
}
To use it you should Box errors:
try!(any_result().map_err(Box::new))
But if you need generic error (for user-defined tasks, as example) you don't need to wrap it with enum, try to use it directly:
trait AnyTask {
fn do_it(&self) -> Result<Success, Box<Error>>;
}
It makes possible to use try! or .into() everywhere. This way:
fn do_it(&self) -> Result<Succeed, Box<Error>> {
let row = try!(self.database.find_last());
if row.some_condition {
return Err("I don't like it!".into());
}
try!(self.database.insert(row));
Ok(Success)
}

How can I wrap any impl of std::error::Error to ease error propagation?

I'm trying to simplify the error flow in a webapp I'm working on, and my plan was to make a struct that implements std::error::Error and just forwards the result of description() for whatever kind of error it's wrapped around. I've implemented From for the types of errors I want to wrap, so this struct makes it easy to use try! to get a uniform error result. Here's what I have so far for the struct:
#![feature(convert)]
use std::error::{Error};
use std::fmt::{self,Display,Formatter};
use std::io::{self,Read};
use std::ops::Deref;
use std::fs::{File};
#[derive(Debug)]
pub struct StrErr{
desc:String,
c: Option<Box<Error>>
}
impl StrErr{
pub fn new(msg:String) ->Self{
StrErr{desc:msg, c:None}
}
}
impl Error for StrErr{
fn description(&self) -> &str{
self.desc.as_str()
}
fn cause(& self) -> Option<& Error> {
self.c.map(|e| e.deref())
}
}
impl Display for StrErr {
fn fmt(&self, f:&mut Formatter) -> Result<(),fmt::Error> {
f.write_str(self.desc.as_str())
}
}
impl From<io::Error> for StrErr {
fn from(o:io::Error) -> Self {
StrErr{desc: String::from(o.description()),c:Some(Box::new(o))}
}
}
fn main(){
let contrived = Some("foo.txt")
.ok_or_else(|| StrErr::new(String::from("error message")))
.and_then(|filename| Ok(try!(File::open(filename))))
.and_then(|mut file| {
let mut content = String::new();
try!(file.read_to_string(&mut content));
Ok(content)
});
if let Ok(content) = contrived {
println!("Got content: {}", content);
} else {
println!("got an error");
}
}
playground
The problem is with the cause() method - I can't return a reference to the inner Error instance because e doesn't live long enough. Is there a different way I can structure this so that I can keep the generic reference to anything that implements Error (which I currently do by putting it in a Box) but I can still fully implement the Error trait (which is expecting a ref to the parent Error)?
I've worked around it by just punting on cause() and having it return None, but I'd much rather conform to the intent of the trait.
rustc 1.2.0-nightly (613e57b44 2015-06-01) (built 2015-06-02)
This is one way you can convert an Option<Box<Trait>> to an Option<&Trait>. I'm avoiding all of the trait implementation to clearly show the interesting code:
use std::error::Error;
pub struct StrErr {
c: Option<Box<Error>>
}
impl StrErr {
fn cause(&self) -> Option<&Error> {
self.c.as_ref().map(|e| &**e)
}
}
fn main() {}
We use Option::as_ref to avoid consuming the self.c item. The map closure is provided with a &Box<Trait>, so we dereference it twice to get to a Trait, and then reference it once to get to a &Trait.

How can I use std::convert::Into to convert something that might fail?

I would like a function that accepts a variety of types that can be converted to my specific type. In similar cases, I'd use std::convert::Into (or std::convert::From):
pub struct MyThing;
impl<'a> Into<MyThing> for &'a str {
fn into(self) -> MyThing {
MyThing
}
}
fn main() {}
As an extra wrinkle, in my specific case, the conversion can potentially fail. Normally, I'd use Result to represent an operation that may fail. Combining the two concepts together:
pub struct MyThing;
pub struct Error;
impl<'a> Into<Result<MyThing, Error>> for &'a str {
fn into(self) -> Result<MyThing, Error> {
if self.len() % 2 == 0 {
Ok(MyThing)
} else {
Err(Error)
}
}
}
fn main() {}
Unfortunately, this seems to run afoul of coherence rules:
error: the impl does not reference any types defined in this crate;
only traits defined in the current crate can be implemented for
arbitrary types [E0117]
I see that I could create my own specific trait:
struct MyThing;
struct Error;
trait IntoMyThing {
fn into(self) -> Result<MyThing, Error>;
}
impl<'a> IntoMyThing for &'a str {
fn into(self) -> Result<MyThing, Error> {
if self.len() % 2 == 0 {
Ok(MyThing)
} else {
Err(Error)
}
}
}
fn main() {}
Or even a more-generic trait:
struct MyThing;
struct Error;
trait MaybeInto<T, E> {
fn into(self) -> Result<T, E>;
}
impl<'a> MaybeInto<MyThing, Error> for &'a str {
fn into(self) -> Result<MyThing, Error> {
if self.len() % 2 == 0 {
Ok(MyThing)
} else {
Err(Error)
}
}
}
fn main() {}
But is there any way to reuse components from the standard library to accomplish my goal?
This isn't possible as-is due to coherence rules, which makes things like this pretty inconvenient, because you can't do it unless you create a newtype for one of the types, either the Result or the &str. See RFC #1023 for more information.
In short, based on the new rules stipulated by that RFC, you cannot implement a trait that's not local to the crate for a type that's not local to the crate.
Modify the orphan rules so that impls of remote traits require a local type that is either a struct/enum/trait defined in the current crate LT = LocalTypeConstructor<...> or a reference to a local type LT = ... | &LT | &mut LT.
So since you didn't create the Into trait in your crate nor the Result type, you get this error. Creating a new type fixes this because it basically wraps a non-local type in a local type.

Resources