Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit f1a467e

Browse files
authored
Merge pull request #255 from palfrey/use-error-source
Use Error::source not Error::cause in Rust versions that have it
2 parents 38f2324 + cb80278 commit f1a467e

File tree

7 files changed

+122
-19
lines changed

7 files changed

+122
-19
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ rust:
55
- nightly
66
# Oldest supported version for all features.
77
# Use of https://github.com/rust-lang/rfcs/pull/16
8-
- 1.14.0
8+
# and Backtrace needs 1.25 (see https://github.com/alexcrichton/backtrace-rs/pull/137)
9+
- 1.25.0
910
# Oldest supported version as dependency, with no features, tests, or examples.
1011
- 1.10.0
1112

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ example_generated = []
2424

2525
[dependencies]
2626
backtrace = { version = "0.3.3", optional = true }
27+
28+
[build-dependencies]
29+
version_check = "0.1.5"

build.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
extern crate version_check;
2+
3+
use version_check::is_min_version;
4+
5+
fn main() {
6+
// Switch on for versions that have Error::source
7+
// As introduced by https://github.com/rust-lang/rust/pull/53533
8+
if is_min_version("1.30").map(|(is_high_enough, _actual_version)| is_high_enough).unwrap_or(false)
9+
{
10+
println!("cargo:rustc-cfg=has_error_source");
11+
}
12+
}

src/backtrace.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod imp {
77
use std::cell::UnsafeCell;
88
use std::env;
99
use std::fmt;
10-
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
10+
use std::sync::atomic::{AtomicUsize, Ordering};
1111
use std::sync::{Arc, Mutex};
1212

1313
/// Internal representation of a backtrace
@@ -33,7 +33,7 @@ mod imp {
3333
/// in the generated error implementations.
3434
#[doc(hidden)]
3535
pub fn new() -> InternalBacktrace {
36-
static ENABLED: AtomicUsize = ATOMIC_USIZE_INIT;
36+
static ENABLED: AtomicUsize = AtomicUsize::new(0);
3737

3838
match ENABLED.load(Ordering::SeqCst) {
3939
0 => {

src/error_chain.rs

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,72 @@
1+
#[doc(hidden)]
2+
#[macro_export]
3+
#[cfg(not(has_error_source))]
4+
macro_rules! impl_error_chain_cause_or_source {
5+
(
6+
types {
7+
$error_kind_name:ident
8+
}
9+
10+
foreign_links {
11+
$( $foreign_link_variant:ident ( $foreign_link_error_path:path )
12+
$( #[$meta_foreign_links:meta] )*; )*
13+
}
14+
) => {
15+
#[allow(unknown_lints, renamed_and_removed_lints, unused_doc_comment, unused_doc_comments)]
16+
fn cause(&self) -> Option<&::std::error::Error> {
17+
match self.1.next_error {
18+
Some(ref c) => Some(&**c),
19+
None => {
20+
match self.0 {
21+
$(
22+
$(#[$meta_foreign_links])*
23+
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
24+
foreign_err.cause()
25+
}
26+
) *
27+
_ => None
28+
}
29+
}
30+
}
31+
}
32+
};
33+
}
34+
35+
#[cfg(has_error_source)]
36+
#[doc(hidden)]
37+
#[macro_export]
38+
macro_rules! impl_error_chain_cause_or_source {
39+
(
40+
types {
41+
$error_kind_name:ident
42+
}
43+
44+
foreign_links {
45+
$( $foreign_link_variant:ident ( $foreign_link_error_path:path )
46+
$( #[$meta_foreign_links:meta] )*; )*
47+
}
48+
) => {
49+
50+
#[allow(unknown_lints, renamed_and_removed_lints, unused_doc_comment, unused_doc_comments)]
51+
fn source(&self) -> Option<&(std::error::Error + 'static)> {
52+
match self.1.next_error {
53+
Some(ref c) => Some(&**c),
54+
None => {
55+
match self.0 {
56+
$(
57+
$(#[$meta_foreign_links])*
58+
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
59+
foreign_err.source()
60+
}
61+
) *
62+
_ => None
63+
}
64+
}
65+
}
66+
}
67+
};
68+
}
69+
170
/// Prefer to use `error_chain` instead of this macro.
271
#[doc(hidden)]
372
#[macro_export]
@@ -179,21 +248,13 @@ macro_rules! impl_error_chain_processed {
179248
self.description()
180249
}
181250

182-
#[allow(unknown_lints, renamed_and_removed_lints, unused_doc_comment, unused_doc_comments)]
183-
fn cause(&self) -> Option<&::std::error::Error> {
184-
match self.1.next_error {
185-
Some(ref c) => Some(&**c),
186-
None => {
187-
match self.0 {
188-
$(
189-
$(#[$meta_foreign_links])*
190-
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
191-
foreign_err.cause()
192-
}
193-
) *
194-
_ => None
195-
}
196-
}
251+
impl_error_chain_cause_or_source!{
252+
types {
253+
$error_kind_name
254+
}
255+
foreign_links {
256+
$( $foreign_link_variant ( $foreign_link_error_path )
257+
$( #[$meta_foreign_links] )*; )*
197258
}
198259
}
199260
}

src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,12 @@ impl<'a> Iterator for Iter<'a> {
570570
fn next<'b>(&'b mut self) -> Option<&'a error::Error> {
571571
match self.0.take() {
572572
Some(e) => {
573-
self.0 = e.cause();
573+
self.0 = match () {
574+
#[cfg(not(has_error_source))]
575+
() => e.cause(),
576+
#[cfg(has_error_source)]
577+
() => e.source(),
578+
};
574579
Some(e)
575580
}
576581
None => None,

tests/tests.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,15 @@ mod foreign_link_test {
292292
"Foreign error description"
293293
}
294294

295+
#[cfg(not(has_error_source))]
295296
fn cause(&self) -> Option<&::std::error::Error> {
296297
Some(&self.cause)
297298
}
299+
300+
#[cfg(has_error_source)]
301+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
302+
Some(&self.cause)
303+
}
298304
}
299305

300306
impl fmt::Display for ForeignError {
@@ -311,9 +317,15 @@ mod foreign_link_test {
311317
"Foreign error cause description"
312318
}
313319

320+
#[cfg(not(has_error_source))]
314321
fn cause(&self) -> Option<&::std::error::Error> {
315322
None
316323
}
324+
325+
#[cfg(has_error_source)]
326+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
327+
None
328+
}
317329
}
318330

319331
impl fmt::Display for ForeignErrorCause {
@@ -342,12 +354,21 @@ mod foreign_link_test {
342354
}
343355

344356
#[test]
357+
#[cfg(not(has_error_source))]
345358
fn finds_cause() {
346359
let chained_error = try_foreign_error().err().unwrap();
347360
assert_eq!(format!("{}", ForeignErrorCause {}),
348361
format!("{}", ::std::error::Error::cause(&chained_error).unwrap()));
349362
}
350363

364+
#[test]
365+
#[cfg(has_error_source)]
366+
fn finds_source() {
367+
let chained_error = try_foreign_error().err().unwrap();
368+
assert_eq!(format!("{}", ForeignErrorCause {}),
369+
format!("{}", ::std::error::Error::source(&chained_error).unwrap()));
370+
}
371+
351372
#[test]
352373
fn iterates() {
353374
let chained_error = try_foreign_error().err().unwrap();

0 commit comments

Comments
 (0)