about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_log/src/lib.rs13
-rw-r--r--src/librustdoc/lib.rs26
2 files changed, 32 insertions, 7 deletions
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index 49dd388f14c..1bb502ca3d0 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -37,6 +37,7 @@ use std::env::{self, VarError};
 use std::fmt::{self, Display};
 use std::io::{self, IsTerminal};
 
+use tracing::dispatcher::SetGlobalDefaultError;
 use tracing_core::{Event, Subscriber};
 use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter};
 use tracing_subscriber::fmt::FmtContext;
@@ -131,10 +132,10 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> {
                 .without_time()
                 .event_format(BacktraceFormatter { backtrace_target });
             let subscriber = subscriber.with(fmt_layer);
-            tracing::subscriber::set_global_default(subscriber).unwrap();
+            tracing::subscriber::set_global_default(subscriber)?;
         }
         Err(_) => {
-            tracing::subscriber::set_global_default(subscriber).unwrap();
+            tracing::subscriber::set_global_default(subscriber)?;
         }
     };
 
@@ -180,6 +181,7 @@ pub enum Error {
     InvalidColorValue(String),
     NonUnicodeColorValue,
     InvalidWraptree(String),
+    AlreadyInit(SetGlobalDefaultError),
 }
 
 impl std::error::Error for Error {}
@@ -199,6 +201,13 @@ impl Display for Error {
                 formatter,
                 "invalid log WRAPTREE value '{value}': expected a non-negative integer",
             ),
+            Error::AlreadyInit(tracing_error) => Display::fmt(tracing_error, formatter),
         }
     }
 }
+
+impl From<SetGlobalDefaultError> for Error {
+    fn from(tracing_error: SetGlobalDefaultError) -> Self {
+        Error::AlreadyInit(tracing_error)
+    }
+}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 44bd96a7e45..bca40b8117b 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -170,12 +170,28 @@ pub fn main() {
     // NOTE: this compiles both versions of tracing unconditionally, because
     // - The compile time hit is not that bad, especially compared to rustdoc's incremental times, and
     // - Otherwise, there's no warning that logging is being ignored when `download-rustc` is enabled
-    // NOTE: The reason this doesn't show double logging when `download-rustc = false` and
-    // `debug_logging = true` is because all rustc logging goes to its version of tracing (the one
-    // in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml).
 
-    init_logging(&early_dcx);
-    rustc_driver::init_logger(&early_dcx, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG"));
+    crate::init_logging(&early_dcx);
+    match rustc_log::init_logger(rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")) {
+        Ok(()) => {}
+        // With `download-rustc = true` there are definitely 2 distinct tracing crates in the
+        // dependency graph: one in the downloaded sysroot and one built just now as a dependency of
+        // rustdoc. So the sysroot's tracing is definitely not yet initialized here.
+        //
+        // But otherwise, depending on link style, there may or may not be 2 tracing crates in play.
+        // The one we just initialized in `crate::init_logging` above is rustdoc's direct dependency
+        // on tracing. When rustdoc is built by x.py using Cargo, rustc_driver's and rustc_log's
+        // tracing dependency is distinct from this one and also needs to be initialized (using the
+        // same RUSTDOC_LOG environment variable for both). Other build systems may use just a
+        // single tracing crate throughout the rustc and rustdoc build.
+        //
+        // The reason initializing 2 tracings does not show double logging when `download-rustc =
+        // false` and `debug_logging = true` is because all rustc logging goes only to its version
+        // of tracing (the one in the sysroot) and all of rustdoc's logging only goes to its version
+        // (the one in Cargo.toml).
+        Err(rustc_log::Error::AlreadyInit(_)) => {}
+        Err(error) => early_dcx.early_fatal(error.to_string()),
+    }
 
     let exit_code = rustc_driver::catch_with_exit_code(|| {
         let at_args = rustc_driver::args::raw_args(&early_dcx);