From de70d8173b03e92ed637713923297fb664d5f368 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 11 Jul 2018 09:30:23 -0700 Subject: [PATCH] Improve Debug display for a few types Try to cut down on the wordiness here and make these implementations a bit more usable by default. --- .../compiler/context/unit_dependencies.rs | 8 +- src/cargo/core/manifest.rs | 76 ++++++++++++++++++- src/cargo/core/package.rs | 11 ++- src/cargo/core/profiles.rs | 29 ++++++- src/cargo/lib.rs | 3 + src/cargo/macros.rs | 49 ++++++++++++ 6 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 src/cargo/macros.rs diff --git a/src/cargo/core/compiler/context/unit_dependencies.rs b/src/cargo/core/compiler/context/unit_dependencies.rs index f522f3839a9..6fe006bd786 100644 --- a/src/cargo/core/compiler/context/unit_dependencies.rs +++ b/src/cargo/core/compiler/context/unit_dependencies.rs @@ -15,12 +15,13 @@ //! (for example, with and without tests), so we actually build a dependency //! graph of `Unit`s, which capture these properties. -use super::{BuildContext, CompileMode, Kind, Unit}; +use std::collections::HashMap; + +use CargoResult; use core::dependency::Kind as DepKind; use core::profiles::ProfileFor; use core::{Package, Target}; -use std::collections::HashMap; -use CargoResult; +use super::{BuildContext, CompileMode, Kind, Unit}; pub fn build_unit_dependencies<'a, 'cfg>( roots: &[Unit<'a>], @@ -41,6 +42,7 @@ pub fn build_unit_dependencies<'a, 'cfg>( }; deps_of(unit, bcx, &mut deps, profile_for)?; } + trace!("ALL UNIT DEPENDENCIES {:#?}", deps); Ok(()) } diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 5e42103862c..2b2b86ec2cc 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -86,7 +86,7 @@ pub struct ManifestMetadata { pub links: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum LibKind { Lib, Rlib, @@ -125,7 +125,13 @@ impl LibKind { } } -#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +impl fmt::Debug for LibKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.crate_type().fmt(f) + } +} + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum TargetKind { Lib(Vec), Bin, @@ -153,9 +159,23 @@ impl ser::Serialize for TargetKind { } } +impl fmt::Debug for TargetKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::TargetKind::*; + match *self { + Lib(ref kinds) => kinds.fmt(f), + Bin => "bin".fmt(f), + ExampleBin | ExampleLib(_) => "example".fmt(f), + Test => "test".fmt(f), + CustomBuild => "custom-build".fmt(f), + Bench => "bench".fmt(f), + } + } +} + /// Information about a binary, a library, an example, etc. that is part of the /// package. -#[derive(Clone, Hash, PartialEq, Eq, Debug)] +#[derive(Clone, Hash, PartialEq, Eq)] pub struct Target { kind: TargetKind, name: String, @@ -173,7 +193,7 @@ pub struct Target { for_host: bool, } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq)] struct NonHashedPathBuf { path: PathBuf, } @@ -184,6 +204,12 @@ impl Hash for NonHashedPathBuf { } } +impl fmt::Debug for NonHashedPathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.path.fmt(f) + } +} + #[derive(Serialize)] struct SerializedTarget<'a> { /// Is this a `--bin bin`, `--lib`, `--example ex`? @@ -207,6 +233,48 @@ impl ser::Serialize for Target { } } +compact_debug! { + impl fmt::Debug for Target { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (default, default_name) = { + let src = self.src_path().to_path_buf(); + match &self.kind { + TargetKind::Lib(kinds) => { + ( + Target::lib_target(&self.name, kinds.clone(), src.clone()), + format!("lib_target({:?}, {:?}, {:?})", + self.name, kinds, src), + ) + } + TargetKind::CustomBuild => { + ( + Target::custom_build_target(&self.name, src.clone()), + format!("custom_build_target({:?}, {:?})", + self.name, src), + ) + } + _ => ( + Target::with_path(src.clone()), + format!("with_path({:?})", src), + ), + } + }; + [debug_the_fields( + kind + name + src_path + required_features + tested + benched + doc + doctest + harness + for_host + )] + } + } +} + impl Manifest { pub fn new( summary: Summary, diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 37ad259f10b..c6c2e028481 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -19,7 +19,7 @@ use util::errors::{CargoResult, CargoResultExt}; /// /// A package is a `Cargo.toml` file plus all the files that are part of it. // TODO: Is manifest_path a relic? -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct Package { /// The package's manifest manifest: Manifest, @@ -199,6 +199,15 @@ impl fmt::Display for Package { } } +impl fmt::Debug for Package { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Package") + .field("id", self.summary().package_id()) + .field("..", &"..") + .finish() + } +} + impl PartialEq for Package { fn eq(&self, other: &Package) -> bool { self.package_id() == other.package_id() diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 24fa37d3b6a..2a822022af4 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -371,7 +371,7 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) { /// Profile settings used to determine which compiler flags to use for a /// target. -#[derive(Debug, Clone, Copy, Eq)] +#[derive(Clone, Copy, Eq)] pub struct Profile { pub name: &'static str, pub opt_level: InternedString, @@ -403,6 +403,33 @@ impl Default for Profile { } } +compact_debug! { + impl fmt::Debug for Profile { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (default, default_name) = match self.name { + "dev" => (Profile::default_dev(), "default_dev()"), + "release" => (Profile::default_release(), "default_release()"), + "test" => (Profile::default_test(), "default_test()"), + "bench" => (Profile::default_bench(), "default_bench()"), + "doc" => (Profile::default_doc(), "default_doc()"), + _ => (Profile::default(), "default()"), + }; + [debug_the_fields( + name + opt_level + lto + codegen_units + debuginfo + debug_assertions + overflow_checks + rpath + incremental + panic + )] + } + } +} + impl fmt::Display for Profile { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Profile({})", self.name) diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index d99cea32f35..c81f594f857 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -60,6 +60,9 @@ pub use util::errors::Internal; pub const CARGO_ENV: &str = "CARGO"; +#[macro_use] +mod macros; + pub mod core; pub mod ops; pub mod sources; diff --git a/src/cargo/macros.rs b/src/cargo/macros.rs new file mode 100644 index 00000000000..17529ee0a91 --- /dev/null +++ b/src/cargo/macros.rs @@ -0,0 +1,49 @@ +use std::fmt; + +macro_rules! compact_debug { + ( + impl fmt::Debug for $ty:ident { + fn fmt(&$this:ident, f: &mut fmt::Formatter) -> fmt::Result { + let (default, default_name) = $e:expr; + [debug_the_fields($($field:ident)*)] + } + } + ) => ( + + impl fmt::Debug for $ty { + fn fmt(&$this, f: &mut fmt::Formatter) -> fmt::Result { + // Try printing a pretty version where we collapse as many fields as + // possible, indicating that they're equivalent to a function call + // that's hopefully enough to indicate what each value is without + // actually dumping everything so verbosely. + let mut s = f.debug_struct(stringify!($ty)); + let (default, default_name) = $e; + let mut any_default = false; + + // Exhaustively match so when fields are added we get a compile + // failure + let $ty { $($field),* } = $this; + $( + if *$field == default.$field { + any_default = true; + } else { + s.field(stringify!($field), $field); + } + )* + + if any_default { + s.field("..", &::macros::DisplayAsDebug(default_name)); + } + s.finish() + } + } + ) +} + +pub struct DisplayAsDebug(pub T); + +impl fmt::Debug for DisplayAsDebug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +}