Let's focus on the absolute minimum reproduction of your issue:
use std::error::Error;
fn foo() -> Result<String, Box<dyn Error>> {
Err("Error...")
}
The error returned by this code is:
error[E0308]: mismatched types
--> src/lib.rs:4:9
|
4 | Err("Error...")
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found reference
|
= note: expected type `std::boxed::Box<dyn std::error::Error>`
found type `&'static str`
It's saying that the function signature expected you to return an Err containing a Box<dyn Error>, but you actually returned an Err containing a &str. Since the types don't line up, the compiler throws an error.
The easiest way to fix this is to use the Into trait, which implements a conversion between &str and Box<dyn Error>:
use std::error::Error;
fn foo() -> Result<String, Box<dyn Error>> {
Err("Error...".into())
// `Err(Box::from("Error..."))` would also work
}
How it works
You may still be wondering what exactly that magic .into() call is doing behind the scenes.
First, let's see what happens if we just Box the &str:
use std::error::Error;
fn foo() -> Result<String, Box<dyn Error>> {
Err(Box::new("Error..."))
}
error[E0277]: the trait bound `&str: std::error::Error` is not satisfied
--> src/lib.rs:4:9
|
4 | Err(Box::new("Error..."))
| ^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `&str`
|
= note: required for the cast to the object type `dyn std::error::Error`
Again, this doesn't work because the types don't line up - it's expecting the Box to contain something that implements the Error trait, but if you look at the docs, you'll notice that &str is not one of the types that implements it. You need to wrap your string in a type that does implement Error:
use std::error::Error;
use std::fmt;
#[derive(Debug)]
struct StrError<'a>(&'a str);
// Error doesn't require you to implement any methods, but
// your type must also implement Debug and Display.
impl<'a> Error for StrError<'a> {}
impl<'a> fmt::Display for StrError<'a>{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Delegate to the Display impl for `&str`:
self.0.fmt(f)
}
}
fn foo() -> Result<String, Box<dyn Error>> {
Err(Box::new(StrError("Error...")))
}
This code compiles, and is basically exactly what impl Into<Box<dyn Error>> for &str does under the hood :)