Deprecation of FromError broke program, replacement fails


#1

I tried to recompile a working program from last month, and, as usual, the language had changed and the program would no longer compile. This time, it’s error::FromError, which was listed as “stable” for Alpha 2, but now has disappeared. I’m using that because it was recommended as the proper approach in [“Improved Error Handling in Rust”] (LINK CENSORED BY FORUM SYSTEM) Searching for what changed, all I can find is ["What Happened to std:error::FromError][3]. OK, so a more general mechanism, convert::From is now being used. So I change my code for each error conversion from

impl error::FromError<hyper::HttpError> for FeedError {
    fn from_error(err: hyper::HttpError) -> FeedError {
        FeedError::FeedHTTPError(err)
        }
}

to

impl convert::From<hyper::HttpError> for FeedError {
    fn from(err: hyper::HttpError) -> FeedError {
        FeedError::FeedHTTPError(err)
        }
    }

All these are used, per “Improved Error Handling”, to convert errors to a single error enum type which expresses all the things that can go wrong with an RSS feed:

/// A set of errors that can occur handling RSS or Atom feeds.
#[derive(Debug, PartialEq, Clone)] // crank out default functions
pub enum FeedError {
 FeedIoError(io::Error),
 FeedHTTPError(hyper::HttpError),
 FeedXMLParseError(xml::BuilderError),
 FeedDateParseError(chrono::format::ParseError),
 FeedUnknownFeedTypeError,
 FeedFieldError(String),
 FeedWasHTMLError(String)
}

Now I get these compile errors:

src/rssread.rs:79:17: 79:26 error: the trait core::clone::Clone is not implemented for the type std::io::error::Error [E0277]
src/rssread.rs:79 FeedIoError(io::Error),
^~~~~~~~~
src/rssread.rs:76:28: 76:33 note: in expansion of #[derive_Clone]
src/rssread.rs:76:28: 76:33 note: expansion site
src/rssread.rs:81:19: 81:35 error: the trait core::clone::Clone is not implemented for the type hyper::error::HttpError [E0277]
src/rssread.rs:81 FeedHTTPError(hyper::HttpError),
^~~~~~~~~~~~~~~~
src/rssread.rs:76:28: 76:33 note: in expansion of #[derive_Clone]
src/rssread.rs:76:28: 76:33 note: expansion site
src/rssread.rs:79:17: 79:26 error: binary operation == cannot be applied to type std::io::error::Error [E0369]
src/rssread.rs:79 FeedIoError(io::Error),
^~~~~~~~~
src/rssread.rs:76:17: 76:26 note: in expansion of #[derive_PartialEq]
src/rssread.rs:76:17: 76:26 note: expansion site
src/rssread.rs:81:19: 81:35 error: binary operation == cannot be applied to type hyper::error::HttpError [E0369]
src/rssread.rs:81 FeedHTTPError(hyper::HttpError),
^~~~~~~~~~~~~~~~
src/rssread.rs:76:17: 76:26 note: in expansion of #[derive_PartialEq]
src/rssread.rs:76:17: 76:26 note: expansion site
src/rssread.rs:79:17: 79:26 error: binary operation != cannot be applied to type std::io::error::Error [E0369]
src/rssread.rs:79 FeedIoError(io::Error),
^~~~~~~~~
src/rssread.rs:76:17: 76:26 note: in expansion of #[derive_PartialEq]
src/rssread.rs:76:17: 76:26 note: expansion site
src/rssread.rs:81:19: 81:35 error: binary operation != cannot be applied to type hyper::error::HttpError [E0369]
src/rssread.rs:81 FeedHTTPError(hyper::HttpError),
^~~~~~~~~~~~~~~~
src/rssread.rs:76:17: 76:26 note: in expansion of #[derive_PartialEq]
src/rssread.rs:76:17: 76:26 note: expansion site

The problem seems to be that basic error types are not cloneable, and with this newly mandated “std::convert::From” approach, they now have to be. All this worked fine with std::error::FromError.

Now what?


#2

The clone error looks completely separate from the FromError change. From has no bounds at all on the clonability of types.

Are you using something like #[derive(Clone)] that would require the inner types to be Clone? If one of the other types of error that you are wrapping used to implement Clone, but now doesn’t, that would cause your error.


#3

Ah. Thanks. I was asking for #[derive(Clone)], as shown in the enum declaration. With that removed, the code compiles. I’m puzzled that it does, though. Each enum case has a value, not a reference, so creating an enum would imply a copy of the error type. How does that work for a non-cloneable object?


#4

The issue is that io::Error used to be cloneable, but isn’t any longer. I think it was changed so that an io::Erro could embed an Error trait object, which is itself not cloneable. I don’t know the rationale for this change.

Your existing code is probably just moving errors around, which doesn’t require cloning. Clone gives you the clone method. If you never used it, then removing derive(Clone) would have no effect.