Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3466,14 +3466,9 @@ impl Drop for Buffy {

pub fn stderr_destination(color: ColorConfig) -> Destination {
let buffer_writer = std::io::stderr();
let choice = color.to_color_choice();
// We need to resolve `ColorChoice::Auto` before `Box`ing since
// `ColorChoice::Auto` on `dyn Write` will always resolve to `Never`
let choice = if matches!(choice, ColorChoice::Auto) {
AutoStream::choice(&buffer_writer)
} else {
choice
};
let choice = get_stderr_color_choice(color, &buffer_writer);
// On Windows we'll be performing global synchronization on the entire
// system for emitting rustc errors, so there's no need to buffer
// anything.
Expand All @@ -3488,6 +3483,11 @@ pub fn stderr_destination(color: ColorConfig) -> Destination {
}
}

pub fn get_stderr_color_choice(color: ColorConfig, stderr: &std::io::Stderr) -> ColorChoice {
let choice = color.to_color_choice();
Copy link
Member

@fmease fmease Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll provide some more context for other T-rustdoc members. In my opinion to_color_choice as used in both rustc & rustdoc is suboptimal as it doesn't harness the full power of crate anstyle-query due to the fact that it yields Never if the config is Auto and stderr is not a terminal meaning NO_COLOR=1 works but e.g., CLICOLOR_FORCE=1 doesn't.

That's a separate bug I or Muscraft will deal with in the future, hopefully.

I'm saying all that because I originally wanted to use CLICOLOR_FORCE=1 in a potential regression test for #148749 which requires --color=auto (not --color=always) which obviously never leads to colored output since it's captured by compiletest, not by the terminal. I wanted to use CLICOLOR_FORCE=1 to indirectly test --color=auto (and have the golden file be an SVG or ANSI codes if that doesn't work out).

That's the reason why there's no regression test. If you have any other ideas, please let me know.

if matches!(choice, ColorChoice::Auto) { AutoStream::choice(stderr) } else { choice }
}

/// On Windows, BRIGHT_BLUE is hard to read on black. Use cyan instead.
///
/// See #36178.
Expand Down
15 changes: 9 additions & 6 deletions src/librustdoc/doctest/make.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use std::sync::Arc;
use rustc_ast::token::{Delimiter, TokenKind};
use rustc_ast::tokenstream::TokenTree;
use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind};
use rustc_errors::emitter::stderr_destination;
use rustc_errors::{AutoStream, ColorConfig, DiagCtxtHandle};
use rustc_errors::emitter::get_stderr_color_choice;
use rustc_errors::{AutoStream, ColorChoice, ColorConfig, DiagCtxtHandle};
use rustc_parse::lexer::StripTokens;
use rustc_parse::new_parser_from_source_str;
use rustc_session::parse::ParseSess;
Expand Down Expand Up @@ -446,7 +446,7 @@ fn parse_source(
span: Span,
) -> Result<ParseSourceInfo, ()> {
use rustc_errors::DiagCtxt;
use rustc_errors::emitter::{Emitter, HumanEmitter};
use rustc_errors::emitter::HumanEmitter;
use rustc_span::source_map::FilePathMapping;

let mut info =
Expand All @@ -458,9 +458,12 @@ fn parse_source(

let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
let translator = rustc_driver::default_translator();
info.supports_color =
HumanEmitter::new(stderr_destination(ColorConfig::Auto), translator.clone())
.supports_color();
let supports_color = match get_stderr_color_choice(ColorConfig::Auto, &std::io::stderr()) {
Copy link
Member

@fmease fmease Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should've realized that much earlier: Obviously, like on stable, rustdoc bad-doctest.rs --test | cat / rustdoc bad-doctest.rs --test > file.txt still leads to colored output because libtest outputs this to stdout while we're querying stderr here.

I consider this a bug but I don't want it to be fixed in this PR since there are some subtleties. E.g., if you pass --no-capture (previously known as --nocapture) to rustdoc, then both output streams don't get captured meaning querying stderr would actually make sense in that specific case. There are probably some other things that need consideration.

ColorChoice::Auto => unreachable!(),
ColorChoice::AlwaysAnsi | ColorChoice::Always => true,
ColorChoice::Never => false,
};
info.supports_color = supports_color;
// Any errors in parsing should also appear when the doctest is compiled for real, so just
// send all the errors that the parser emits directly into a `Sink` instead of stderr.
let emitter = HumanEmitter::new(AutoStream::never(Box::new(io::sink())), translator);
Expand Down
Loading