Failure not working for no_std


#1

I’m having trouble compiling a no_std crate that depends on the Failure crate. Running cargo build spits out the following error:

error[E0433]: failed to resolve. Maybe a missing `extern crate std;`?
 --> src\lib.rs:6:17
  |
6 | #[derive(Debug, failure::Fail)]
  |                 ^^^^^^^^^^^^^ Maybe a missing `extern crate std;`?

In my Cargo.toml I’ve disabled failure's “std” feature and it is still looking for std. Also I don’t understand why it is looking for Fail in std when its use is fully qualified with the failure crate name.

The contents of my lib.rs are as below:

#![no_std]
#![feature(use_extern_macros)]

extern crate failure;

#[derive(Debug, failure::Fail)]
struct M {
    d: i32
}

impl core::fmt::Display for M {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        write!(f, "Dummy string - will do for now")
    }
}

and my Cargo.toml is:

[package]
name = "test_no_std"
version = "0.1.0"

[dependencies.failure]
version = "0.1.1"
default-features = false
features = ["derive"]

Any idea how I can solve this?


#2

Running cargo expand gives

#![feature(prelude_import)]
#![no_std]
#![no_std]
#![feature(use_extern_macros)]
#[prelude_import]
use core::prelude::v1::*;
#[macro_use]
extern crate core as core;

extern crate failure;

struct M {
    d: i32,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for M {
    fn fmt(&self, __arg_0: &mut ::core::fmt::Formatter)
     -> ::core::fmt::Result {
        match *self {
            M { d: ref __self_0_0 } => {
                let mut builder = __arg_0.debug_struct("M");
                let _ = builder.field("d", &&(*__self_0_0));
                builder.finish()
            }
        }
    }
}
impl ::failure::Fail for M {
    #[allow(unreachable_code)]
    fn cause(&self) -> ::std::option::Option<&::failure::Fail> {
        match *self { M { d: ref __binding_0 } => { return None } }
        None
    }
    #[allow(unreachable_code)]
    fn backtrace(&self) -> ::std::option::Option<&::failure::Backtrace> {
        match *self { M { d: ref __binding_0 } => { return None } }
        None
    }
}

impl core::fmt::Display for M {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        f.write_fmt(::core::fmt::Arguments::new_v1(&["Dummy string - will do for now"],
                                                   &match () { () => [], }))
    }
}

see those ::stds in there? Looks like failure-derive needs to be updated to support this use-case.


#3

I’ve got a new version that’s fixed the derive to support no_std, but its not on crates.io yet, sorry. failure itself is no_std already if you don’t use the derive.


#4

You could always create a fake std module. Something like this:

mod std {
    pub use core::option;
}

#5

Thanks @steveklabnik, especially for teaching me a new and useful cargo command :slight_smile:.

Thanks @withoutboats. When can we expect to see the new version of failure_derive on crates.io (no pressure :smiley:)?

And thanks @toothbrush for the workaround.


#6

@gurry I’m glad I could help. I’m used to this kind of workaround with writing Rust libraries that support both ![no_std] and std code.