Skip to content
6 changes: 3 additions & 3 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ dependencies = [

[[package]]
name = "annotate-snippets"
version = "0.12.7"
version = "0.12.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47224528f74de27d1d06aad6a5dda4f865b6ebe2e56c538943d746a7270cb67e"
checksum = "025c7edcdffa4ccc5c0905f472a0ae3759378cfbef88ef518a3575e19ae3aebd"
dependencies = [
"anstyle",
"unicode-width 0.2.2",
Expand Down Expand Up @@ -3767,7 +3767,7 @@ dependencies = [
name = "rustc_errors"
version = "0.0.0"
dependencies = [
"annotate-snippets 0.12.7",
"annotate-snippets 0.12.8",
"anstream",
"anstyle",
"derive_setters",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_errors/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2024"

[dependencies]
# tidy-alphabetical-start
annotate-snippets = "0.12.7"
annotate-snippets = "0.12.8"
anstream = "0.6.20"
anstyle = "1.0.13"
derive_setters = "0.1.6"
Expand Down
20 changes: 10 additions & 10 deletions compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,20 +329,22 @@ impl AnnotateSnippetEmitter {
let substitutions = suggestion
.substitutions
.into_iter()
.filter_map(|mut subst| {
.filter(|subst| {
// Suggestions coming from macros can have malformed spans. This is a heavy
// handed approach to avoid ICEs by ignoring the suggestion outright.
let invalid =
subst.parts.iter().any(|item| sm.is_valid_span(item.span).is_err());
if invalid {
debug!("suggestion contains an invalid span: {:?}", subst);
}

!invalid
})
.filter_map(|mut subst| {
// Assumption: all spans are in the same file, and all spans
// are disjoint. Sort in ascending order.
subst.parts.sort_by_key(|part| part.span.lo());
// Verify the assumption that all spans are disjoint
assert_eq!(
debug_assert_eq!(
Copy link
Contributor

Choose a reason for hiding this comment

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

CC #147849

subst.parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
None,
"all spans must be disjoint",
Expand All @@ -355,13 +357,11 @@ impl AnnotateSnippetEmitter {

let item_span = subst.parts.first()?;
let file = sm.lookup_source_file(item_span.span.lo());
if !invalid
&& should_show_source_code(
&self.ignored_directories_in_source_blocks,
sm,
&file,
)
{
if should_show_source_code(
&self.ignored_directories_in_source_blocks,
sm,
&file,
) {
Some(subst)
} else {
None
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,16 @@ const DEFAULT_COLUMN_WIDTH: usize = 140;
/// Describes the way the content of the `rendered` field of the json output is generated
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HumanReadableErrorType {
Default,
Unicode,
AnnotateSnippet,
Short,
Default { short: bool },
AnnotateSnippet { short: bool, unicode: bool },
}

impl HumanReadableErrorType {
pub fn short(&self) -> bool {
*self == HumanReadableErrorType::Short
match self {
HumanReadableErrorType::Default { short }
| HumanReadableErrorType::AnnotateSnippet { short, .. } => *short,
}
}
}

Expand Down
50 changes: 34 additions & 16 deletions compiler/rustc_errors/src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use rustc_span::hygiene::ExpnData;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use serde::Serialize;

use crate::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
use crate::diagnostic::IsLint;
use crate::emitter::{
ColorConfig, Destination, Emitter, HumanEmitter, HumanReadableErrorType, OutputTheme,
Expand Down Expand Up @@ -370,29 +371,46 @@ impl Diagnostic {
.insert(0, Diagnostic::from_sub_diagnostic(&diag.emitted_at_sub_diag(), &args, je));
}
let buf = BufWriter(Arc::new(Mutex::new(Vec::new())));
let short = je.json_rendered.short();
let dst: Destination = AutoStream::new(
Box::new(buf.clone()),
match je.color_config.to_color_choice() {
ColorChoice::Auto => ColorChoice::Always,
choice => choice,
},
);
HumanEmitter::new(dst, je.translator.clone())
.short_message(short)
.sm(je.sm.clone())
.diagnostic_width(je.diagnostic_width)
.macro_backtrace(je.macro_backtrace)
.track_diagnostics(je.track_diagnostics)
.terminal_url(je.terminal_url)
.ui_testing(je.ui_testing)
.ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone())
.theme(if let HumanReadableErrorType::Unicode = je.json_rendered {
OutputTheme::Unicode
} else {
OutputTheme::Ascii
})
.emit_diagnostic(diag, registry);
match je.json_rendered {
HumanReadableErrorType::AnnotateSnippet { short, unicode } => {
AnnotateSnippetEmitter::new(dst, je.translator.clone())
.short_message(short)
.sm(je.sm.clone())
.diagnostic_width(je.diagnostic_width)
.macro_backtrace(je.macro_backtrace)
.track_diagnostics(je.track_diagnostics)
.terminal_url(je.terminal_url)
.ui_testing(je.ui_testing)
.ignored_directories_in_source_blocks(
je.ignored_directories_in_source_blocks.clone(),
)
.theme(if unicode { OutputTheme::Unicode } else { OutputTheme::Ascii })
.emit_diagnostic(diag, registry)
}
HumanReadableErrorType::Default { short } => {
HumanEmitter::new(dst, je.translator.clone())
.short_message(short)
.sm(je.sm.clone())
.diagnostic_width(je.diagnostic_width)
.macro_backtrace(je.macro_backtrace)
.track_diagnostics(je.track_diagnostics)
.terminal_url(je.terminal_url)
.ui_testing(je.ui_testing)
.ignored_directories_in_source_blocks(
je.ignored_directories_in_source_blocks.clone(),
)
.theme(OutputTheme::Ascii)
.emit_diagnostic(diag, registry)
}
}

let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap();
let buf = String::from_utf8(buf).unwrap();

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/json/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
Some(sm),
translator,
true, // pretty
HumanReadableErrorType::Short,
HumanReadableErrorType::Default { short: true },
ColorConfig::Never,
);

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ fn test_search_paths_tracking_hash_different_order() {
let early_dcx = EarlyDiagCtxt::new(JSON);
const JSON: ErrorOutputType = ErrorOutputType::Json {
pretty: false,
json_rendered: HumanReadableErrorType::Default,
json_rendered: HumanReadableErrorType::Default { short: false },
color_config: ColorConfig::Never,
};

Expand Down
24 changes: 17 additions & 7 deletions compiler/rustc_parse/src/parser/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![allow(rustc::symbol_intern_string_literal)]

use std::assert_matches::assert_matches;
use std::io::prelude::*;
use std::iter::Peekable;
Expand All @@ -12,6 +11,7 @@ use rustc_ast::token::{self, Delimiter, Token};
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_ast::{self as ast, PatKind, visit};
use rustc_ast_pretty::pprust::item_to_string;
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
use rustc_errors::emitter::{HumanEmitter, OutputTheme};
use rustc_errors::translation::Translator;
use rustc_errors::{AutoStream, DiagCtxt, MultiSpan, PResult};
Expand Down Expand Up @@ -43,12 +43,22 @@ fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Arc<SourceMap>, Arc<Mut
let output = Arc::new(Mutex::new(Vec::new()));
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
let translator = Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
let mut emitter =
HumanEmitter::new(AutoStream::never(Box::new(Shared { data: output.clone() })), translator)
.sm(Some(source_map.clone()))
.diagnostic_width(Some(140));
emitter = emitter.theme(theme);
let dcx = DiagCtxt::new(Box::new(emitter));
let shared: Box<dyn Write + Send> = Box::new(Shared { data: output.clone() });
let auto_stream = AutoStream::never(shared);
let dcx = DiagCtxt::new(match theme {
OutputTheme::Ascii => Box::new(
HumanEmitter::new(auto_stream, translator)
.sm(Some(source_map.clone()))
.diagnostic_width(Some(140))
.theme(theme),
),
OutputTheme::Unicode => Box::new(
AnnotateSnippetEmitter::new(auto_stream, translator)
.sm(Some(source_map.clone()))
.diagnostic_width(Some(140))
.theme(theme),
),
});
(dcx, source_map, output)
}

Expand Down
Loading
Loading