|  | use std::env; | 
|  | use std::fs; | 
|  | use std::path::Path; | 
|  | use std::process::{Command, ExitStatus, Stdio}; | 
|  | use std::str; | 
|  |  | 
|  | // This code exercises the surface area that we expect of the Error generic | 
|  | // member access API. If the current toolchain is able to compile it, then | 
|  | // thiserror is able to provide backtrace support. | 
|  | const PROBE: &str = r#" | 
|  | #![feature(error_generic_member_access)] | 
|  |  | 
|  | use std::error::{Error, Request}; | 
|  | use std::fmt::{self, Debug, Display}; | 
|  |  | 
|  | struct MyError(Thing); | 
|  | struct Thing; | 
|  |  | 
|  | impl Debug for MyError { | 
|  | fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { | 
|  | unimplemented!() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Display for MyError { | 
|  | fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { | 
|  | unimplemented!() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Error for MyError { | 
|  | fn provide<'a>(&'a self, request: &mut Request<'a>) { | 
|  | request.provide_ref(&self.0); | 
|  | } | 
|  | } | 
|  | "#; | 
|  |  | 
|  | fn main() { | 
|  | match compile_probe() { | 
|  | Some(status) if status.success() => println!("cargo:rustc-cfg=error_generic_member_access"), | 
|  | _ => {} | 
|  | } | 
|  | } | 
|  |  | 
|  | fn compile_probe() -> Option<ExitStatus> { | 
|  | if env::var_os("RUSTC_STAGE").is_some() { | 
|  | // We are running inside rustc bootstrap. This is a highly non-standard | 
|  | // environment with issues such as: | 
|  | // | 
|  | //     https://github.com/rust-lang/cargo/issues/11138 | 
|  | //     https://github.com/rust-lang/rust/issues/114839 | 
|  | // | 
|  | // Let's just not use nightly features here. | 
|  | return None; | 
|  | } | 
|  |  | 
|  | let rustc = env::var_os("RUSTC")?; | 
|  | let out_dir = env::var_os("OUT_DIR")?; | 
|  | let probefile = Path::new(&out_dir).join("probe.rs"); | 
|  | fs::write(&probefile, PROBE).ok()?; | 
|  |  | 
|  | // Make sure to pick up Cargo rustc configuration. | 
|  | let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER") { | 
|  | let mut cmd = Command::new(wrapper); | 
|  | // The wrapper's first argument is supposed to be the path to rustc. | 
|  | cmd.arg(rustc); | 
|  | cmd | 
|  | } else { | 
|  | Command::new(rustc) | 
|  | }; | 
|  |  | 
|  | cmd.stderr(Stdio::null()) | 
|  | .arg("--edition=2018") | 
|  | .arg("--crate-name=thiserror_build") | 
|  | .arg("--crate-type=lib") | 
|  | .arg("--emit=metadata") | 
|  | .arg("--out-dir") | 
|  | .arg(out_dir) | 
|  | .arg(probefile); | 
|  |  | 
|  | if let Some(target) = env::var_os("TARGET") { | 
|  | cmd.arg("--target").arg(target); | 
|  | } | 
|  |  | 
|  | // If Cargo wants to set RUSTFLAGS, use that. | 
|  | if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") { | 
|  | if !rustflags.is_empty() { | 
|  | for arg in rustflags.split('\x1f') { | 
|  | cmd.arg(arg); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | cmd.status().ok() | 
|  | } |