Rollup merge of #121783 - nnethercote:emitter-cleanups, r=oli-obk
Emitter cleanups Some cleanups I made when reading emitter code. In particular, `HumanEmitter` and `JsonEmitter` have gone from three constructors to one. r? `@oli-obk`
This commit is contained in:
commit
0e9f02d6fa
15 changed files with 138 additions and 219 deletions
|
@ -21,12 +21,11 @@ use crate::{
|
|||
FluentBundle, LazyFallbackBundle, Level, MultiSpan, Subdiag, SubstitutionHighlight,
|
||||
SuggestionStyle, TerminalUrl,
|
||||
};
|
||||
use rustc_lint_defs::pluralize;
|
||||
|
||||
use derive_setters::Setters;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc};
|
||||
use rustc_error_messages::{FluentArgs, SpanLabel};
|
||||
use rustc_lint_defs::pluralize;
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::{max, min, Reverse};
|
||||
|
@ -35,7 +34,7 @@ use std::io::prelude::*;
|
|||
use std::io::{self, IsTerminal};
|
||||
use std::iter;
|
||||
use std::path::Path;
|
||||
use termcolor::{Ansi, Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream};
|
||||
use termcolor::{Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream};
|
||||
use termcolor::{Color, WriteColor};
|
||||
|
||||
/// Default column width, used in tests and when terminal dimensions cannot be determined.
|
||||
|
@ -58,18 +57,6 @@ impl HumanReadableErrorType {
|
|||
HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc),
|
||||
}
|
||||
}
|
||||
pub fn new_emitter(
|
||||
self,
|
||||
mut dst: Box<dyn WriteColor + Send>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
) -> HumanEmitter {
|
||||
let (short, color_config) = self.unzip();
|
||||
let color = color_config.suggests_using_colors();
|
||||
if !dst.supports_color() && color {
|
||||
dst = Box::new(Ansi::new(dst));
|
||||
}
|
||||
HumanEmitter::new(dst, fallback_bundle).short_message(short)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -130,8 +117,8 @@ impl Margin {
|
|||
fn was_cut_right(&self, line_len: usize) -> bool {
|
||||
let right =
|
||||
if self.computed_right == self.span_right || self.computed_right == self.label_right {
|
||||
// Account for the "..." padding given above. Otherwise we end up with code lines that
|
||||
// do fit but end in "..." as if they were trimmed.
|
||||
// Account for the "..." padding given above. Otherwise we end up with code lines
|
||||
// that do fit but end in "..." as if they were trimmed.
|
||||
self.computed_right - 6
|
||||
} else {
|
||||
self.computed_right
|
||||
|
@ -628,12 +615,6 @@ impl ColorConfig {
|
|||
ColorConfig::Auto => ColorChoice::Never,
|
||||
}
|
||||
}
|
||||
fn suggests_using_colors(self) -> bool {
|
||||
match self {
|
||||
ColorConfig::Always | ColorConfig::Auto => true,
|
||||
ColorConfig::Never => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short`
|
||||
|
@ -657,19 +638,14 @@ pub struct HumanEmitter {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileWithAnnotatedLines {
|
||||
pub file: Lrc<SourceFile>,
|
||||
pub lines: Vec<Line>,
|
||||
pub(crate) struct FileWithAnnotatedLines {
|
||||
pub(crate) file: Lrc<SourceFile>,
|
||||
pub(crate) lines: Vec<Line>,
|
||||
multiline_depth: usize,
|
||||
}
|
||||
|
||||
impl HumanEmitter {
|
||||
pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
|
||||
let dst = from_stderr(color_config);
|
||||
Self::create(dst, fallback_bundle)
|
||||
}
|
||||
|
||||
fn create(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
|
||||
pub fn new(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
|
||||
HumanEmitter {
|
||||
dst: IntoDynSyncSend(dst),
|
||||
sm: None,
|
||||
|
@ -686,13 +662,6 @@ impl HumanEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
dst: Box<dyn WriteColor + Send>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
) -> HumanEmitter {
|
||||
Self::create(dst, fallback_bundle)
|
||||
}
|
||||
|
||||
fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> {
|
||||
if self.ui_testing {
|
||||
Cow::Borrowed(ANONYMIZED_LINE_NUM)
|
||||
|
@ -724,8 +693,9 @@ impl HumanEmitter {
|
|||
.skip(left)
|
||||
.take_while(|ch| {
|
||||
// Make sure that the trimming on the right will fall within the terminal width.
|
||||
// FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is.
|
||||
// For now, just accept that sometimes the code line will be longer than desired.
|
||||
// FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char`
|
||||
// is. For now, just accept that sometimes the code line will be longer than
|
||||
// desired.
|
||||
let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1);
|
||||
if taken + next > right - left {
|
||||
return false;
|
||||
|
@ -2228,8 +2198,8 @@ impl HumanEmitter {
|
|||
buffer.puts(*row_num - 1, max_line_num_len + 3, &line, Style::NoStyle);
|
||||
*row_num += 1;
|
||||
}
|
||||
// If the last line is exactly equal to the line we need to add, we can skip both of them.
|
||||
// This allows us to avoid output like the following:
|
||||
// If the last line is exactly equal to the line we need to add, we can skip both of
|
||||
// them. This allows us to avoid output like the following:
|
||||
// 2 - &
|
||||
// 2 + if true { true } else { false }
|
||||
// 3 - if true { true } else { false }
|
||||
|
@ -2586,6 +2556,7 @@ fn num_overlap(
|
|||
let extra = if inclusive { 1 } else { 0 };
|
||||
(b_start..b_end + extra).contains(&a_start) || (a_start..a_end + extra).contains(&b_start)
|
||||
}
|
||||
|
||||
fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
|
||||
num_overlap(
|
||||
a1.start_col.display,
|
||||
|
@ -2632,7 +2603,7 @@ fn emit_to_destination(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub type Destination = Box<(dyn WriteColor + Send)>;
|
||||
pub type Destination = Box<dyn WriteColor + Send>;
|
||||
|
||||
struct Buffy {
|
||||
buffer_writer: BufferWriter,
|
||||
|
@ -2674,7 +2645,7 @@ impl WriteColor for Buffy {
|
|||
}
|
||||
}
|
||||
|
||||
fn from_stderr(color: ColorConfig) -> Destination {
|
||||
pub fn stderr_destination(color: ColorConfig) -> Destination {
|
||||
let choice = color.to_color_choice();
|
||||
// On Windows we'll be performing global synchronization on the entire
|
||||
// system for emitting rustc errors, so there's no need to buffer
|
||||
|
|
|
@ -23,9 +23,11 @@ impl<'args> TranslateError<'args> {
|
|||
pub fn message(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
|
||||
Self::One { id, args, kind: TranslateErrorKind::MessageMissing }
|
||||
}
|
||||
|
||||
pub fn primary(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
|
||||
Self::One { id, args, kind: TranslateErrorKind::PrimaryBundleMissing }
|
||||
}
|
||||
|
||||
pub fn attribute(
|
||||
id: &'args Cow<'args, str>,
|
||||
args: &'args FluentArgs<'args>,
|
||||
|
@ -33,6 +35,7 @@ impl<'args> TranslateError<'args> {
|
|||
) -> Self {
|
||||
Self::One { id, args, kind: TranslateErrorKind::AttributeMissing { attr } }
|
||||
}
|
||||
|
||||
pub fn value(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
|
||||
Self::One { id, args, kind: TranslateErrorKind::ValueMissing }
|
||||
}
|
||||
|
|
|
@ -9,42 +9,49 @@
|
|||
|
||||
// FIXME: spec the JSON output properly.
|
||||
|
||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
use termcolor::{ColorSpec, WriteColor};
|
||||
|
||||
use crate::emitter::{should_show_source_code, Emitter, HumanReadableErrorType};
|
||||
use crate::emitter::{
|
||||
should_show_source_code, ColorConfig, Destination, Emitter, HumanEmitter,
|
||||
HumanReadableErrorType,
|
||||
};
|
||||
use crate::registry::Registry;
|
||||
use crate::translation::{to_fluent_args, Translate};
|
||||
use crate::{
|
||||
diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel,
|
||||
Subdiag, TerminalUrl,
|
||||
};
|
||||
use rustc_lint_defs::Applicability;
|
||||
|
||||
use derive_setters::Setters;
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
|
||||
use rustc_error_messages::FluentArgs;
|
||||
use rustc_lint_defs::Applicability;
|
||||
use rustc_span::hygiene::ExpnData;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::Span;
|
||||
use serde::Serialize;
|
||||
use std::error::Report;
|
||||
use std::io::{self, Write};
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::vec;
|
||||
|
||||
use serde::Serialize;
|
||||
use termcolor::{ColorSpec, WriteColor};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[derive(Setters)]
|
||||
pub struct JsonEmitter {
|
||||
#[setters(skip)]
|
||||
dst: IntoDynSyncSend<Box<dyn Write + Send>>,
|
||||
registry: Option<Registry>,
|
||||
#[setters(skip)]
|
||||
sm: Lrc<SourceMap>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
#[setters(skip)]
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
#[setters(skip)]
|
||||
pretty: bool,
|
||||
ui_testing: bool,
|
||||
ignored_directories_in_source_blocks: Vec<String>,
|
||||
#[setters(skip)]
|
||||
json_rendered: HumanReadableErrorType,
|
||||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
|
@ -53,98 +60,30 @@ pub struct JsonEmitter {
|
|||
}
|
||||
|
||||
impl JsonEmitter {
|
||||
pub fn stderr(
|
||||
registry: Option<Registry>,
|
||||
source_map: Lrc<SourceMap>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
pretty: bool,
|
||||
json_rendered: HumanReadableErrorType,
|
||||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> JsonEmitter {
|
||||
JsonEmitter {
|
||||
dst: IntoDynSyncSend(Box::new(io::BufWriter::new(io::stderr()))),
|
||||
registry,
|
||||
sm: source_map,
|
||||
fluent_bundle,
|
||||
fallback_bundle,
|
||||
pretty,
|
||||
ui_testing: false,
|
||||
ignored_directories_in_source_blocks: Vec::new(),
|
||||
json_rendered,
|
||||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn basic(
|
||||
pretty: bool,
|
||||
json_rendered: HumanReadableErrorType,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> JsonEmitter {
|
||||
let file_path_mapping = FilePathMapping::empty();
|
||||
JsonEmitter::stderr(
|
||||
None,
|
||||
Lrc::new(SourceMap::new(file_path_mapping)),
|
||||
fluent_bundle,
|
||||
fallback_bundle,
|
||||
pretty,
|
||||
json_rendered,
|
||||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
dst: Box<dyn Write + Send>,
|
||||
registry: Option<Registry>,
|
||||
source_map: Lrc<SourceMap>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
sm: Lrc<SourceMap>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
pretty: bool,
|
||||
json_rendered: HumanReadableErrorType,
|
||||
diagnostic_width: Option<usize>,
|
||||
macro_backtrace: bool,
|
||||
track_diagnostics: bool,
|
||||
terminal_url: TerminalUrl,
|
||||
) -> JsonEmitter {
|
||||
JsonEmitter {
|
||||
dst: IntoDynSyncSend(dst),
|
||||
registry,
|
||||
sm: source_map,
|
||||
fluent_bundle,
|
||||
registry: None,
|
||||
sm,
|
||||
fluent_bundle: None,
|
||||
fallback_bundle,
|
||||
pretty,
|
||||
ui_testing: false,
|
||||
ignored_directories_in_source_blocks: Vec::new(),
|
||||
json_rendered,
|
||||
diagnostic_width,
|
||||
macro_backtrace,
|
||||
track_diagnostics,
|
||||
terminal_url,
|
||||
diagnostic_width: None,
|
||||
macro_backtrace: false,
|
||||
track_diagnostics: false,
|
||||
terminal_url: TerminalUrl::No,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui_testing(self, ui_testing: bool) -> Self {
|
||||
Self { ui_testing, ..self }
|
||||
}
|
||||
|
||||
pub fn ignored_directories_in_source_blocks(self, value: Vec<String>) -> Self {
|
||||
Self { ignored_directories_in_source_blocks: value, ..self }
|
||||
}
|
||||
|
||||
fn emit(&mut self, val: EmitTyped<'_>) -> io::Result<()> {
|
||||
if self.pretty {
|
||||
serde_json::to_writer_pretty(&mut *self.dst, &val)?
|
||||
|
@ -162,7 +101,7 @@ enum EmitTyped<'a> {
|
|||
Diagnostic(Diagnostic),
|
||||
Artifact(ArtifactNotification<'a>),
|
||||
FutureIncompat(FutureIncompatReport<'a>),
|
||||
UnusedExtern(UnusedExterns<'a, 'a, 'a>),
|
||||
UnusedExtern(UnusedExterns<'a>),
|
||||
}
|
||||
|
||||
impl Translate for JsonEmitter {
|
||||
|
@ -332,14 +271,15 @@ struct FutureIncompatReport<'a> {
|
|||
// We could unify this struct the one in rustdoc but they have different
|
||||
// ownership semantics, so doing so would create wasteful allocations.
|
||||
#[derive(Serialize)]
|
||||
struct UnusedExterns<'a, 'b, 'c> {
|
||||
struct UnusedExterns<'a> {
|
||||
/// The severity level of the unused dependencies lint
|
||||
lint_level: &'a str,
|
||||
/// List of unused externs by their names.
|
||||
unused_extern_names: &'b [&'c str],
|
||||
unused_extern_names: &'a [&'a str],
|
||||
}
|
||||
|
||||
impl Diagnostic {
|
||||
/// Converts from `rustc_errors::DiagInner` to `Diagnostic`.
|
||||
fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic {
|
||||
let args = to_fluent_args(diag.args.iter());
|
||||
let sugg = diag.suggestions.iter().flatten().map(|sugg| {
|
||||
|
@ -405,9 +345,14 @@ impl Diagnostic {
|
|||
.collect();
|
||||
|
||||
let buf = BufWriter::default();
|
||||
let output = buf.clone();
|
||||
je.json_rendered
|
||||
.new_emitter(Box::new(buf), je.fallback_bundle.clone())
|
||||
let mut dst: Destination = Box::new(buf.clone());
|
||||
let (short, color_config) = je.json_rendered.unzip();
|
||||
match color_config {
|
||||
ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
|
||||
ColorConfig::Never => {}
|
||||
}
|
||||
HumanEmitter::new(dst, je.fallback_bundle.clone())
|
||||
.short_message(short)
|
||||
.sm(Some(je.sm.clone()))
|
||||
.fluent_bundle(je.fluent_bundle.clone())
|
||||
.diagnostic_width(je.diagnostic_width)
|
||||
|
@ -417,8 +362,8 @@ impl Diagnostic {
|
|||
.ui_testing(je.ui_testing)
|
||||
.ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone())
|
||||
.emit_diagnostic(diag);
|
||||
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
|
||||
let output = String::from_utf8(output).unwrap();
|
||||
let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap();
|
||||
let buf = String::from_utf8(buf).unwrap();
|
||||
|
||||
Diagnostic {
|
||||
message: translated_message.to_string(),
|
||||
|
@ -426,7 +371,7 @@ impl Diagnostic {
|
|||
level,
|
||||
spans,
|
||||
children,
|
||||
rendered: Some(output),
|
||||
rendered: Some(buf),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::*;
|
||||
|
||||
use crate::emitter::ColorConfig;
|
||||
use crate::DiagCtxt;
|
||||
use rustc_span::source_map::FilePathMapping;
|
||||
use rustc_span::BytePos;
|
||||
|
||||
use std::str;
|
||||
|
@ -48,20 +48,14 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
|||
let output = Arc::new(Mutex::new(Vec::new()));
|
||||
let je = JsonEmitter::new(
|
||||
Box::new(Shared { data: output.clone() }),
|
||||
None,
|
||||
sm,
|
||||
None,
|
||||
fallback_bundle,
|
||||
true,
|
||||
true, // pretty
|
||||
HumanReadableErrorType::Short(ColorConfig::Never),
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
TerminalUrl::No,
|
||||
);
|
||||
|
||||
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
|
||||
let dcx = DiagCtxt::with_emitter(Box::new(je));
|
||||
let dcx = DiagCtxt::new(Box::new(je));
|
||||
dcx.span_err(span, "foo");
|
||||
|
||||
let bytes = output.lock().unwrap();
|
||||
|
|
|
@ -59,11 +59,11 @@ pub use snippet::Style;
|
|||
// See https://github.com/rust-lang/rust/pull/115393.
|
||||
pub use termcolor::{Color, ColorSpec, WriteColor};
|
||||
|
||||
use emitter::{is_case_difference, DynEmitter, Emitter, HumanEmitter};
|
||||
use emitter::{is_case_difference, DynEmitter, Emitter};
|
||||
use registry::Registry;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
|
||||
use rustc_data_structures::sync::{Lock, Lrc};
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_data_structures::AtomicRef;
|
||||
use rustc_lint_defs::LintExpectationId;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
|
@ -217,10 +217,10 @@ impl CodeSuggestion {
|
|||
|
||||
use rustc_span::{CharPos, Pos};
|
||||
|
||||
/// Extracts a substring from the provided `line_opt` based on the specified low and high indices,
|
||||
/// appends it to the given buffer `buf`, and returns the count of newline characters in the substring
|
||||
/// for accurate highlighting.
|
||||
/// If `line_opt` is `None`, a newline character is appended to the buffer, and 0 is returned.
|
||||
/// Extracts a substring from the provided `line_opt` based on the specified low and high
|
||||
/// indices, appends it to the given buffer `buf`, and returns the count of newline
|
||||
/// characters in the substring for accurate highlighting. If `line_opt` is `None`, a
|
||||
/// newline character is appended to the buffer, and 0 is returned.
|
||||
///
|
||||
/// ## Returns
|
||||
///
|
||||
|
@ -482,8 +482,8 @@ struct DiagCtxtInner {
|
|||
/// have been converted.
|
||||
check_unstable_expect_diagnostics: bool,
|
||||
|
||||
/// Expected [`DiagInner`][struct@diagnostic::DiagInner]s store a [`LintExpectationId`] as part of
|
||||
/// the lint level. [`LintExpectationId`]s created early during the compilation
|
||||
/// Expected [`DiagInner`][struct@diagnostic::DiagInner]s store a [`LintExpectationId`] as part
|
||||
/// of the lint level. [`LintExpectationId`]s created early during the compilation
|
||||
/// (before `HirId`s have been defined) are not stable and can therefore not be
|
||||
/// stored on disk. This buffer stores these diagnostics until the ID has been
|
||||
/// replaced by a stable [`LintExpectationId`]. The [`DiagInner`][struct@diagnostic::DiagInner]s
|
||||
|
@ -590,13 +590,6 @@ impl Drop for DiagCtxtInner {
|
|||
}
|
||||
|
||||
impl DiagCtxt {
|
||||
pub fn with_tty_emitter(
|
||||
sm: Option<Lrc<SourceMap>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
) -> Self {
|
||||
let emitter = Box::new(HumanEmitter::stderr(ColorConfig::Auto, fallback_bundle).sm(sm));
|
||||
Self::with_emitter(emitter)
|
||||
}
|
||||
pub fn disable_warnings(mut self) -> Self {
|
||||
self.inner.get_mut().flags.can_emit_warnings = false;
|
||||
self
|
||||
|
@ -612,7 +605,7 @@ impl DiagCtxt {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_emitter(emitter: Box<DynEmitter>) -> Self {
|
||||
pub fn new(emitter: Box<DynEmitter>) -> Self {
|
||||
Self {
|
||||
inner: Lock::new(DiagCtxtInner {
|
||||
flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue