mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #119606 - nnethercote:consuming-emit, r=oli-obk
Consuming `emit` This PR makes `DiagnosticBuilder::emit` consuming, i.e. take `self` instead of `&mut self`. This is good because it doesn't make sense to emit a diagnostic twice. This requires some changes to `DiagnosticBuilder` method changing -- every existing non-consuming chaining method gets a new consuming partner with a `_mv` suffix -- but permits a host of beneficial follow-up changes: more concise code through more chaining, removal of redundant diagnostic construction API methods, and removal of machinery to track the possibility of a diagnostic being emitted multiple times. r? `@compiler-errors`
This commit is contained in:
commit
ca663b06c5
@ -23,7 +23,7 @@ macro_rules! gate {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
|
||||
.help($help)
|
||||
.help_mv($help)
|
||||
.emit();
|
||||
}
|
||||
}};
|
||||
|
@ -54,13 +54,12 @@ pub(crate) struct UnknownMetaItem<'a> {
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0541));
|
||||
diag.arg("item", self.item);
|
||||
diag.arg("expected", expected.join(", "));
|
||||
diag.span_label(self.span, fluent::attr_label);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item)
|
||||
.span_mv(self.span)
|
||||
.code_mv(error_code!(E0541))
|
||||
.arg_mv("item", self.item)
|
||||
.arg_mv("expected", expected.join(", "))
|
||||
.span_label_mv(self.span, fluent::attr_label)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,17 +31,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrow_span: Span,
|
||||
borrow_desc: &str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0503,
|
||||
"cannot use {} because it was mutably borrowed",
|
||||
desc,
|
||||
);
|
||||
|
||||
err.span_label(borrow_span, format!("{borrow_desc} is borrowed here"));
|
||||
err.span_label(span, format!("use of borrowed {borrow_desc}"));
|
||||
err
|
||||
)
|
||||
.span_label_mv(borrow_span, format!("{borrow_desc} is borrowed here"))
|
||||
.span_label_mv(span, format!("use of borrowed {borrow_desc}"))
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_mutably_borrow_multiply(
|
||||
@ -238,17 +236,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrow_span: Span,
|
||||
desc: &str,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0506,
|
||||
"cannot assign to {} because it is borrowed",
|
||||
desc,
|
||||
);
|
||||
|
||||
err.span_label(borrow_span, format!("{desc} is borrowed here"));
|
||||
err.span_label(span, format!("{desc} is assigned to here but it was already borrowed"));
|
||||
err
|
||||
)
|
||||
.span_label_mv(borrow_span, format!("{desc} is borrowed here"))
|
||||
.span_label_mv(span, format!("{desc} is assigned to here but it was already borrowed"))
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_reassign_immutable(
|
||||
@ -287,16 +283,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
(&ty::Slice(_), _) => "slice",
|
||||
_ => span_bug!(move_from_span, "this path should not cause illegal move"),
|
||||
};
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
move_from_span,
|
||||
E0508,
|
||||
"cannot move out of type `{}`, a non-copy {}",
|
||||
ty,
|
||||
type_name,
|
||||
);
|
||||
err.span_label(move_from_span, "cannot move out of here");
|
||||
err
|
||||
)
|
||||
.span_label_mv(move_from_span, "cannot move out of here")
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_move_out_of_interior_of_drop(
|
||||
@ -304,15 +299,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
move_from_span: Span,
|
||||
container_ty: Ty<'_>,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
move_from_span,
|
||||
E0509,
|
||||
"cannot move out of type `{}`, which implements the `Drop` trait",
|
||||
container_ty,
|
||||
);
|
||||
err.span_label(move_from_span, "cannot move out of here");
|
||||
err
|
||||
)
|
||||
.span_label_mv(move_from_span, "cannot move out of here")
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_act_on_moved_value(
|
||||
@ -352,7 +346,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
immutable_section: &str,
|
||||
action: &str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
mutate_span,
|
||||
E0510,
|
||||
@ -360,10 +354,9 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
action,
|
||||
immutable_place,
|
||||
immutable_section,
|
||||
);
|
||||
err.span_label(mutate_span, format!("cannot {action}"));
|
||||
err.span_label(immutable_span, format!("value is immutable in {immutable_section}"));
|
||||
err
|
||||
)
|
||||
.span_label_mv(mutate_span, format!("cannot {action}"))
|
||||
.span_label_mv(immutable_span, format!("value is immutable in {immutable_section}"))
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_borrow_across_coroutine_yield(
|
||||
@ -372,14 +365,13 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
yield_span: Span,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0626,
|
||||
"borrow may still be in use when {coroutine_kind:#} yields",
|
||||
);
|
||||
err.span_label(yield_span, "possible yield occurs here");
|
||||
err
|
||||
)
|
||||
.span_label_mv(yield_span, "possible yield occurs here")
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_borrow_across_destructor(
|
||||
@ -409,7 +401,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
reference_desc: &str,
|
||||
path_desc: &str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0515,
|
||||
@ -417,14 +409,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
RETURN = return_kind,
|
||||
REFERENCE = reference_desc,
|
||||
LOCAL = path_desc,
|
||||
);
|
||||
|
||||
err.span_label(
|
||||
)
|
||||
.span_label_mv(
|
||||
span,
|
||||
format!("{return_kind}s a {reference_desc} data owned by the current function"),
|
||||
);
|
||||
|
||||
err
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_capture_in_long_lived_closure(
|
||||
@ -435,16 +424,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
capture_span: Span,
|
||||
scope: &str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
closure_span,
|
||||
E0373,
|
||||
"{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
|
||||
which is owned by the current {scope}",
|
||||
);
|
||||
err.span_label(capture_span, format!("{borrowed_path} is borrowed here"))
|
||||
.span_label(closure_span, format!("may outlive borrowed value {borrowed_path}"));
|
||||
err
|
||||
)
|
||||
.span_label_mv(capture_span, format!("{borrowed_path} is borrowed here"))
|
||||
.span_label_mv(closure_span, format!("may outlive borrowed value {borrowed_path}"))
|
||||
}
|
||||
|
||||
pub(crate) fn thread_local_value_does_not_live_long_enough(
|
||||
|
@ -2218,15 +2218,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
drop_span, borrow_span
|
||||
);
|
||||
|
||||
let mut err = self.thread_local_value_does_not_live_long_enough(borrow_span);
|
||||
|
||||
err.span_label(
|
||||
borrow_span,
|
||||
"thread-local variables cannot be borrowed beyond the end of the function",
|
||||
);
|
||||
err.span_label(drop_span, "end of enclosing function is here");
|
||||
|
||||
err
|
||||
self.thread_local_value_does_not_live_long_enough(borrow_span)
|
||||
.span_label_mv(
|
||||
borrow_span,
|
||||
"thread-local variables cannot be borrowed beyond the end of the function",
|
||||
)
|
||||
.span_label_mv(drop_span, "end of enclosing function is here")
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
|
@ -329,15 +329,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
if let PlaceRef { local, projection: [] } = deref_base {
|
||||
let decl = &self.body.local_decls[local];
|
||||
if decl.is_ref_for_guard() {
|
||||
let mut err = self.cannot_move_out_of(
|
||||
span,
|
||||
&format!("`{}` in pattern guard", self.local_names[local].unwrap()),
|
||||
);
|
||||
err.note(
|
||||
"variables bound in patterns cannot be moved from \
|
||||
return self
|
||||
.cannot_move_out_of(
|
||||
span,
|
||||
&format!("`{}` in pattern guard", self.local_names[local].unwrap()),
|
||||
)
|
||||
.note_mv(
|
||||
"variables bound in patterns cannot be moved from \
|
||||
until after the end of the pattern guard",
|
||||
);
|
||||
return err;
|
||||
);
|
||||
} else if decl.is_ref_to_static() {
|
||||
return self.report_cannot_move_from_static(move_place, span);
|
||||
}
|
||||
@ -381,15 +381,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
closure_kind_ty, closure_kind, place_description,
|
||||
);
|
||||
|
||||
let mut diag = self.cannot_move_out_of(span, &place_description);
|
||||
|
||||
diag.span_label(upvar_span, "captured outer variable");
|
||||
diag.span_label(
|
||||
self.infcx.tcx.def_span(def_id),
|
||||
format!("captured by this `{closure_kind}` closure"),
|
||||
);
|
||||
|
||||
diag
|
||||
self.cannot_move_out_of(span, &place_description)
|
||||
.span_label_mv(upvar_span, "captured outer variable")
|
||||
.span_label_mv(
|
||||
self.infcx.tcx.def_span(def_id),
|
||||
format!("captured by this `{closure_kind}` closure"),
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let source = self.borrowed_content_source(deref_base);
|
||||
|
@ -348,7 +348,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
|
||||
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
|
||||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||
let mut diag = unexpected_hidden_region_diagnostic(
|
||||
let diag = unexpected_hidden_region_diagnostic(
|
||||
self.infcx.tcx,
|
||||
span,
|
||||
named_ty,
|
||||
|
@ -421,7 +421,7 @@ fn check_opaque_type_parameter_valid(
|
||||
return Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(spans, format!("{descr} used multiple times"))
|
||||
.span_note_mv(spans, format!("{descr} used multiple times"))
|
||||
.emit());
|
||||
}
|
||||
}
|
||||
|
@ -458,7 +458,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
||||
match expr_to_spanned_string(ecx, template_expr, msg) {
|
||||
Ok(template_part) => template_part,
|
||||
Err(err) => {
|
||||
if let Some((mut err, _)) = err {
|
||||
if let Some((err, _)) = err {
|
||||
err.emit();
|
||||
}
|
||||
return None;
|
||||
@ -693,13 +693,14 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
||||
0 => {}
|
||||
1 => {
|
||||
let (sp, msg) = unused_operands.into_iter().next().unwrap();
|
||||
let mut err = ecx.dcx().struct_span_err(sp, msg);
|
||||
err.span_label(sp, msg);
|
||||
err.help(format!(
|
||||
"if this argument is intentionally unused, \
|
||||
consider using it in an asm comment: `\"/*{help_str} */\"`"
|
||||
));
|
||||
err.emit();
|
||||
ecx.dcx()
|
||||
.struct_span_err(sp, msg)
|
||||
.span_label_mv(sp, msg)
|
||||
.help_mv(format!(
|
||||
"if this argument is intentionally unused, \
|
||||
consider using it in an asm comment: `\"/*{help_str} */\"`"
|
||||
))
|
||||
.emit();
|
||||
}
|
||||
_ => {
|
||||
let mut err = ecx.dcx().struct_span_err(
|
||||
@ -747,7 +748,7 @@ pub(super) fn expand_asm<'cx>(
|
||||
};
|
||||
MacEager::expr(expr)
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
@ -779,7 +780,7 @@ pub(super) fn expand_global_asm<'cx>(
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ pub fn expand_assert<'cx>(
|
||||
) -> Box<dyn MacResult + 'cx> {
|
||||
let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) {
|
||||
Ok(assert) => assert,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(span);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ pub fn expand_cfg(
|
||||
);
|
||||
MacEager::expr(cx.expr_bool(sp, matches_cfg))
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ impl CfgEval<'_, '_> {
|
||||
parser.capture_cfg = true;
|
||||
match parse_annotatable_with(&mut parser) {
|
||||
Ok(a) => annotatable = a,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return Some(annotatable);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String])
|
||||
let start_span = parser.token.span;
|
||||
let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
||||
Ok(ai) => ai,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
continue;
|
||||
}
|
||||
|
@ -803,24 +803,23 @@ pub(crate) struct AsmClobberNoReg {
|
||||
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_no_reg,
|
||||
);
|
||||
diag.span(self.spans.clone());
|
||||
// eager translation as `span_labels` takes `AsRef<str>`
|
||||
let lbl1 = dcx.eagerly_translate_to_string(
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_abi,
|
||||
[].into_iter(),
|
||||
);
|
||||
diag.span_labels(self.clobbers, &lbl1);
|
||||
let lbl2 = dcx.eagerly_translate_to_string(
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_outputs,
|
||||
[].into_iter(),
|
||||
);
|
||||
diag.span_labels(self.spans, &lbl2);
|
||||
diag
|
||||
DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_no_reg,
|
||||
)
|
||||
.span_mv(self.spans.clone())
|
||||
.span_labels_mv(self.clobbers, &lbl1)
|
||||
.span_labels_mv(self.spans, &lbl2)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
|
||||
}
|
||||
|
||||
match p.expect(&token::Comma) {
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
match token::TokenKind::Comma.similar_tokens() {
|
||||
Some(tks) if tks.contains(&p.token.kind) => {
|
||||
// If a similar token is found, then it may be a typo. We
|
||||
@ -630,8 +630,7 @@ fn report_missing_placeholders(
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !placeholders.is_empty() {
|
||||
if let Some(mut new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders)
|
||||
{
|
||||
if let Some(new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders) {
|
||||
diag.cancel();
|
||||
new_diag.emit();
|
||||
return;
|
||||
@ -976,7 +975,7 @@ fn expand_format_args_impl<'cx>(
|
||||
MacEager::expr(DummyResult::raw_expr(sp, true))
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
||||
|
||||
self.dcx
|
||||
.struct_span_err(attr.span, msg)
|
||||
.span_label(prev_attr.span, "previous attribute here")
|
||||
.span_label_mv(prev_attr.span, "previous attribute here")
|
||||
.emit();
|
||||
|
||||
return;
|
||||
|
@ -109,7 +109,7 @@ pub fn expand_include<'cx>(
|
||||
// The file will be added to the code map by the parser
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
@ -146,7 +146,7 @@ pub fn expand_include<'cx>(
|
||||
let mut ret = SmallVec::new();
|
||||
loop {
|
||||
match self.p.parse_item(ForceCollect::No) {
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
@ -181,7 +181,7 @@ pub fn expand_include_str(
|
||||
};
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
@ -215,7 +215,7 @@ pub fn expand_include_bytes(
|
||||
};
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
|
@ -409,8 +409,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>)
|
||||
),
|
||||
);
|
||||
}
|
||||
err.span_label(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions")
|
||||
.span_suggestion(attr_sp,
|
||||
err.span_label_mv(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions")
|
||||
.span_suggestion_mv(attr_sp,
|
||||
"replace with conditional compilation to make the item only exist when tests are being run",
|
||||
"#[cfg(test)]",
|
||||
Applicability::MaybeIncorrect)
|
||||
@ -480,7 +480,7 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
|
||||
"argument must be of the form: \
|
||||
`expected = \"error message\"`",
|
||||
)
|
||||
.note(
|
||||
.note_mv(
|
||||
"errors in this attribute were erroneously \
|
||||
allowed and will become a hard error in a \
|
||||
future release",
|
||||
|
@ -12,7 +12,7 @@ pub fn expand_type_ascribe(
|
||||
) -> Box<dyn base::MacResult + 'static> {
|
||||
let (expr, ty) = match parse_ascribe(cx, tts) {
|
||||
Ok(parsed) => parsed,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(span);
|
||||
}
|
||||
|
@ -321,9 +321,10 @@ fn dep_symbol_lookup_fn(
|
||||
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
||||
Linkage::Static => {
|
||||
let name = crate_info.crate_name[&cnum];
|
||||
let mut err = sess.dcx().struct_err(format!("Can't load static lib {}", name));
|
||||
err.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
|
||||
err.emit();
|
||||
sess.dcx()
|
||||
.struct_err(format!("Can't load static lib {}", name))
|
||||
.note("rustc_codegen_cranelift can only load dylibs in JIT mode.")
|
||||
.emit();
|
||||
}
|
||||
Linkage::Dynamic => {
|
||||
dylib_paths.push(src.dylib.as_ref().unwrap().0.clone());
|
||||
|
@ -105,10 +105,8 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_
|
||||
let (message, _) = diag.messages().first().expect("`LlvmError` with no message");
|
||||
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args());
|
||||
|
||||
let mut diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config);
|
||||
diag.arg("error", message);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
|
||||
.arg_mv("error", message)
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,10 +202,10 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for WithLlvmError<'_> {
|
||||
PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err,
|
||||
ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
|
||||
};
|
||||
let mut diag = self.0.into_diagnostic(dcx, level);
|
||||
diag.primary_message(msg_with_llvm_err);
|
||||
diag.arg("llvm_err", self.1);
|
||||
diag
|
||||
self.0
|
||||
.into_diagnostic(dcx, level)
|
||||
.primary_message_mv(msg_with_llvm_err)
|
||||
.arg_mv("llvm_err", self.1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,14 +303,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||
// This exception needs to be kept in sync with allowing
|
||||
// `#[target_feature]` on `main` and `start`.
|
||||
} else if !tcx.features().target_feature_11 {
|
||||
let mut err = feature_err(
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::target_feature_11,
|
||||
attr.span,
|
||||
"`#[target_feature(..)]` can only be applied to `unsafe` functions",
|
||||
);
|
||||
err.span_label(tcx.def_span(did), "not an `unsafe` function");
|
||||
err.emit();
|
||||
)
|
||||
.span_label_mv(tcx.def_span(did), "not an `unsafe` function")
|
||||
.emit();
|
||||
} else {
|
||||
check_target_feature_trait_unsafe(tcx, did, attr.span);
|
||||
}
|
||||
@ -477,7 +477,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||
InlineAttr::Never
|
||||
} else {
|
||||
struct_span_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument")
|
||||
.help("valid inline arguments are `always` and `never`")
|
||||
.help_mv("valid inline arguments are `always` and `never`")
|
||||
.emit();
|
||||
|
||||
InlineAttr::None
|
||||
@ -662,7 +662,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
|
||||
let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
|
||||
tcx.dcx()
|
||||
.struct_span_err(attr.span, msg)
|
||||
.note("the value may not exceed `u16::MAX`")
|
||||
.note_mv("the value may not exceed `u16::MAX`")
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
|
@ -212,192 +212,124 @@ pub struct ThorinErrorWrapper(pub thorin::Error);
|
||||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let build = |msg| DiagnosticBuilder::new(dcx, level, msg);
|
||||
let mut diag;
|
||||
match self.0 {
|
||||
thorin::Error::ReadInput(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_read_input_failure);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ReadInput(_) => build(fluent::codegen_ssa_thorin_read_input_failure),
|
||||
thorin::Error::ParseFileKind(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_file_kind);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_input_file_kind)
|
||||
}
|
||||
thorin::Error::ParseObjectFile(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_object_file);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_input_object_file)
|
||||
}
|
||||
thorin::Error::ParseArchiveFile(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_archive_file);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_input_archive_file)
|
||||
}
|
||||
thorin::Error::ParseArchiveMember(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_archive_member);
|
||||
diag
|
||||
}
|
||||
thorin::Error::InvalidInputKind => {
|
||||
diag = build(fluent::codegen_ssa_thorin_invalid_input_kind);
|
||||
diag
|
||||
}
|
||||
thorin::Error::DecompressData(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_decompress_data);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_archive_member)
|
||||
}
|
||||
thorin::Error::InvalidInputKind => build(fluent::codegen_ssa_thorin_invalid_input_kind),
|
||||
thorin::Error::DecompressData(_) => build(fluent::codegen_ssa_thorin_decompress_data),
|
||||
thorin::Error::NamelessSection(_, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_section_without_name);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_section_without_name)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::RelocationWithInvalidSymbol(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol);
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol)
|
||||
.arg_mv("section", section)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::MultipleRelocations(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_relocations);
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_multiple_relocations)
|
||||
.arg_mv("section", section)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::UnsupportedRelocation(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_unsupported_relocation);
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingDwoName(id) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_dwo_name);
|
||||
diag.arg("id", format!("0x{id:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_unsupported_relocation)
|
||||
.arg_mv("section", section)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::MissingDwoName(id) => build(fluent::codegen_ssa_thorin_missing_dwo_name)
|
||||
.arg_mv("id", format!("0x{id:08x}")),
|
||||
thorin::Error::NoCompilationUnits => {
|
||||
diag = build(fluent::codegen_ssa_thorin_no_compilation_units);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoDie => {
|
||||
diag = build(fluent::codegen_ssa_thorin_no_die);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_no_compilation_units)
|
||||
}
|
||||
thorin::Error::NoDie => build(fluent::codegen_ssa_thorin_no_die),
|
||||
thorin::Error::TopLevelDieNotUnit => {
|
||||
diag = build(fluent::codegen_ssa_thorin_top_level_die_not_unit);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_top_level_die_not_unit)
|
||||
}
|
||||
thorin::Error::MissingRequiredSection(section) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_required_section);
|
||||
diag.arg("section", section);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_missing_required_section)
|
||||
.arg_mv("section", section)
|
||||
}
|
||||
thorin::Error::ParseUnitAbbreviations(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_abbreviations);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_unit_abbreviations)
|
||||
}
|
||||
thorin::Error::ParseUnitAttribute(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_attribute);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_unit_attribute)
|
||||
}
|
||||
thorin::Error::ParseUnitHeader(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_header);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnit(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_unit_header)
|
||||
}
|
||||
thorin::Error::ParseUnit(_) => build(fluent::codegen_ssa_thorin_parse_unit),
|
||||
thorin::Error::IncompatibleIndexVersion(section, format, actual) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_incompatible_index_version);
|
||||
diag.arg("section", section);
|
||||
diag.arg("actual", actual);
|
||||
diag.arg("format", format);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_incompatible_index_version)
|
||||
.arg_mv("section", section)
|
||||
.arg_mv("actual", actual)
|
||||
.arg_mv("format", format)
|
||||
}
|
||||
thorin::Error::OffsetAtIndex(_, index) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_offset_at_index);
|
||||
diag.arg("index", index);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_offset_at_index).arg_mv("index", index)
|
||||
}
|
||||
thorin::Error::StrAtOffset(_, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_str_at_offset);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_str_at_offset)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::ParseIndex(_, section) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_index);
|
||||
diag.arg("section", section);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_index).arg_mv("section", section)
|
||||
}
|
||||
thorin::Error::UnitNotInIndex(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_unit_not_in_index);
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_unit_not_in_index)
|
||||
.arg_mv("unit", format!("0x{unit:08x}"))
|
||||
}
|
||||
thorin::Error::RowNotInIndex(_, row) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_row_not_in_index);
|
||||
diag.arg("row", row);
|
||||
diag
|
||||
}
|
||||
thorin::Error::SectionNotInRow => {
|
||||
diag = build(fluent::codegen_ssa_thorin_section_not_in_row);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_row_not_in_index).arg_mv("row", row)
|
||||
}
|
||||
thorin::Error::SectionNotInRow => build(fluent::codegen_ssa_thorin_section_not_in_row),
|
||||
thorin::Error::EmptyUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_empty_unit);
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_empty_unit).arg_mv("unit", format!("0x{unit:08x}"))
|
||||
}
|
||||
thorin::Error::MultipleDebugInfoSection => {
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_debug_info_section);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_multiple_debug_info_section)
|
||||
}
|
||||
thorin::Error::MultipleDebugTypesSection => {
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_debug_types_section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NotSplitUnit => {
|
||||
diag = build(fluent::codegen_ssa_thorin_not_split_unit);
|
||||
diag
|
||||
}
|
||||
thorin::Error::DuplicateUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_duplicate_unit);
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_multiple_debug_types_section)
|
||||
}
|
||||
thorin::Error::NotSplitUnit => build(fluent::codegen_ssa_thorin_not_split_unit),
|
||||
thorin::Error::DuplicateUnit(unit) => build(fluent::codegen_ssa_thorin_duplicate_unit)
|
||||
.arg_mv("unit", format!("0x{unit:08x}")),
|
||||
thorin::Error::MissingReferencedUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit);
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_missing_referenced_unit)
|
||||
.arg_mv("unit", format!("0x{unit:08x}"))
|
||||
}
|
||||
thorin::Error::NoOutputObjectCreated => {
|
||||
diag = build(fluent::codegen_ssa_thorin_not_output_object_created);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_not_output_object_created)
|
||||
}
|
||||
thorin::Error::MixedInputEncodings => {
|
||||
diag = build(fluent::codegen_ssa_thorin_mixed_input_encodings);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_mixed_input_encodings)
|
||||
}
|
||||
thorin::Error::Io(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_io);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_io).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
thorin::Error::ObjectRead(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_object_read);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_object_read).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
thorin::Error::ObjectWrite(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_object_write);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_object_write).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
thorin::Error::GimliRead(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_gimli_read);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_gimli_read).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
thorin::Error::GimliWrite(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_gimli_write);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_gimli_write).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
_ => unimplemented!("Untranslated thorin error"),
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ pub fn from_target_feature(
|
||||
let code = "enable = \"..\"";
|
||||
tcx.dcx()
|
||||
.struct_span_err(span, msg)
|
||||
.span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
|
||||
.span_suggestion_mv(span, "must be of the form", code, Applicability::HasPlaceholders)
|
||||
.emit();
|
||||
};
|
||||
let rust_features = tcx.features();
|
||||
|
@ -338,7 +338,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut err = op.build_error(self.ccx, span);
|
||||
let err = op.build_error(self.ccx, span);
|
||||
assert!(err.is_error());
|
||||
|
||||
match op.importance() {
|
||||
|
@ -716,7 +716,7 @@ fn print_crate_info(
|
||||
let result = parse_crate_attrs(sess);
|
||||
match result {
|
||||
Ok(attrs) => Some(attrs),
|
||||
Err(mut parse_error) => {
|
||||
Err(parse_error) => {
|
||||
parse_error.emit();
|
||||
return Compilation::Stop;
|
||||
}
|
||||
|
@ -30,57 +30,44 @@ where
|
||||
G: EmissionGuarantee,
|
||||
{
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = self.node.into_diagnostic(dcx, level);
|
||||
diag.span(self.span);
|
||||
diag
|
||||
self.node.into_diagnostic(dcx, level).span_mv(self.span)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for emitting structured error messages and other diagnostic information.
|
||||
/// Each constructed `DiagnosticBuilder` must be consumed by a function such as
|
||||
/// `emit`, `cancel`, `delay_as_bug`, or `into_diagnostic`. A panic occurrs if a
|
||||
/// `DiagnosticBuilder` is dropped without being consumed by one of these
|
||||
/// functions.
|
||||
///
|
||||
/// If there is some state in a downstream crate you would like to
|
||||
/// access in the methods of `DiagnosticBuilder` here, consider
|
||||
/// extending `DiagCtxtFlags`.
|
||||
#[must_use]
|
||||
#[derive(Clone)]
|
||||
pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> {
|
||||
state: DiagnosticBuilderState<'a>,
|
||||
pub dcx: &'a DiagCtxt,
|
||||
|
||||
/// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a
|
||||
/// return value, especially within the frequently-used `PResult` type.
|
||||
/// In theory, return value optimization (RVO) should avoid unnecessary
|
||||
/// copying. In practice, it does not (at the time of writing).
|
||||
diagnostic: Box<Diagnostic>,
|
||||
/// Why the `Option`? It is always `Some` until the `DiagnosticBuilder` is
|
||||
/// consumed via `emit`, `cancel`, etc. At that point it is consumed and
|
||||
/// replaced with `None`. Then `drop` checks that it is `None`; if not, it
|
||||
/// panics because a diagnostic was built but not used.
|
||||
///
|
||||
/// Why the Box? `Diagnostic` is a large type, and `DiagnosticBuilder` is
|
||||
/// often used as a return value, especially within the frequently-used
|
||||
/// `PResult` type. In theory, return value optimization (RVO) should avoid
|
||||
/// unnecessary copying. In practice, it does not (at the time of writing).
|
||||
diag: Option<Box<Diagnostic>>,
|
||||
|
||||
_marker: PhantomData<G>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum DiagnosticBuilderState<'a> {
|
||||
/// Initial state of a `DiagnosticBuilder`, before `.emit()` or `.cancel()`.
|
||||
///
|
||||
/// The `Diagnostic` will be emitted through this `DiagCtxt`.
|
||||
Emittable(&'a DiagCtxt),
|
||||
// Cloning a `DiagnosticBuilder` is a recipe for a diagnostic being emitted
|
||||
// twice, which would be bad.
|
||||
impl<G> !Clone for DiagnosticBuilder<'_, G> {}
|
||||
|
||||
/// State of a `DiagnosticBuilder`, after `.emit()` or *during* `.cancel()`.
|
||||
///
|
||||
/// The `Diagnostic` will be ignored when calling `.emit()`, and it can be
|
||||
/// assumed that `.emit()` was previously called, to end up in this state.
|
||||
///
|
||||
/// While this is also used by `.cancel()`, this state is only observed by
|
||||
/// the `Drop` `impl` of `DiagnosticBuilder`, because `.cancel()` takes
|
||||
/// `self` by-value specifically to prevent any attempts to `.emit()`.
|
||||
///
|
||||
// FIXME(eddyb) currently this doesn't prevent extending the `Diagnostic`,
|
||||
// despite that being potentially lossy, if important information is added
|
||||
// *after* the original `.emit()` call.
|
||||
AlreadyEmittedOrDuringCancellation,
|
||||
}
|
||||
|
||||
// `DiagnosticBuilderState` should be pointer-sized.
|
||||
rustc_data_structures::static_assert_size!(
|
||||
DiagnosticBuilderState<'_>,
|
||||
std::mem::size_of::<&DiagCtxt>()
|
||||
DiagnosticBuilder<'_, ()>,
|
||||
2 * std::mem::size_of::<usize>()
|
||||
);
|
||||
|
||||
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
|
||||
@ -94,68 +81,50 @@ pub trait EmissionGuarantee: Sized {
|
||||
/// `impl` of `EmissionGuarantee`, to make it impossible to create a value
|
||||
/// of `Self::EmitResult` without actually performing the emission.
|
||||
#[track_caller]
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult;
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult;
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// Takes the diagnostic. For use by methods that consume the
|
||||
/// DiagnosticBuilder: `emit`, `cancel`, etc. Afterwards, `drop` is the
|
||||
/// only code that will be run on `self`.
|
||||
fn take_diag(&mut self) -> Diagnostic {
|
||||
Box::into_inner(self.diag.take().unwrap())
|
||||
}
|
||||
|
||||
/// Most `emit_producing_guarantee` functions use this as a starting point.
|
||||
fn emit_producing_nothing(&mut self) {
|
||||
match self.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
dcx.emit_diagnostic_without_consuming(&mut self.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
fn emit_producing_nothing(mut self) {
|
||||
let diag = self.take_diag();
|
||||
self.dcx.emit_diagnostic(diag);
|
||||
}
|
||||
|
||||
/// `ErrorGuaranteed::emit_producing_guarantee` uses this.
|
||||
// FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`.
|
||||
fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
|
||||
let diag = self.take_diag();
|
||||
|
||||
// Only allow a guarantee if the `level` wasn't switched to a
|
||||
// non-error. The field isn't `pub`, but the whole `Diagnostic` can be
|
||||
// overwritten with a new one, thanks to `DerefMut`.
|
||||
assert!(
|
||||
diag.is_error(),
|
||||
"emitted non-error ({:?}) diagnostic from `DiagnosticBuilder<ErrorGuaranteed>`",
|
||||
diag.level,
|
||||
);
|
||||
|
||||
let guar = self.dcx.emit_diagnostic(diag);
|
||||
guar.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`.
|
||||
impl EmissionGuarantee for ErrorGuaranteed {
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
// Contrast this with `emit_producing_nothing`.
|
||||
match db.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
db.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
let guar = dcx.emit_diagnostic_without_consuming(&mut db.diagnostic);
|
||||
|
||||
// Only allow a guarantee if the `level` wasn't switched to a
|
||||
// non-error - the field isn't `pub`, but the whole `Diagnostic`
|
||||
// can be overwritten with a new one, thanks to `DerefMut`.
|
||||
assert!(
|
||||
db.diagnostic.is_error(),
|
||||
"emitted non-error ({:?}) diagnostic \
|
||||
from `DiagnosticBuilder<ErrorGuaranteed>`",
|
||||
db.diagnostic.level,
|
||||
);
|
||||
guar.unwrap()
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it,
|
||||
// but can take advantage of the previous `.emit()`'s guarantee
|
||||
// still being applicable (i.e. as a form of idempotency).
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {
|
||||
// Only allow a guarantee if the `level` wasn't switched to a
|
||||
// non-error - the field isn't `pub`, but the whole `Diagnostic`
|
||||
// can be overwritten with a new one, thanks to `DerefMut`.
|
||||
assert!(
|
||||
db.diagnostic.is_error(),
|
||||
"`DiagnosticBuilder<ErrorGuaranteed>`'s diagnostic \
|
||||
became non-error ({:?}), after original `.emit()`",
|
||||
db.diagnostic.level,
|
||||
);
|
||||
#[allow(deprecated)]
|
||||
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||
}
|
||||
}
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_error_guaranteed()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) should there be a `Option<ErrorGuaranteed>` impl as well?
|
||||
impl EmissionGuarantee for () {
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
}
|
||||
}
|
||||
@ -168,7 +137,7 @@ pub struct BugAbort;
|
||||
impl EmissionGuarantee for BugAbort {
|
||||
type EmitResult = !;
|
||||
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
panic::panic_any(ExplicitBug);
|
||||
}
|
||||
@ -182,37 +151,48 @@ pub struct FatalAbort;
|
||||
impl EmissionGuarantee for FatalAbort {
|
||||
type EmitResult = !;
|
||||
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
crate::FatalError.raise()
|
||||
}
|
||||
}
|
||||
|
||||
impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
rustc_span::fatal_error::FatalError
|
||||
}
|
||||
}
|
||||
|
||||
/// In general, the `DiagnosticBuilder` uses deref to allow access to
|
||||
/// the fields and methods of the embedded `diagnostic` in a
|
||||
/// transparent way. *However,* many of the methods are intended to
|
||||
/// be used in a chained way, and hence ought to return `self`. In
|
||||
/// that case, we can't just naively forward to the method on the
|
||||
/// `diagnostic`, because the return type would be a `&Diagnostic`
|
||||
/// instead of a `&DiagnosticBuilder<'a>`. This `forward!` macro makes
|
||||
/// it easy to declare such methods on the builder.
|
||||
/// `DiagnosticBuilder` impls `DerefMut`, which allows access to the fields and
|
||||
/// methods of the embedded `Diagnostic`. However, that doesn't allow method
|
||||
/// chaining at the `DiagnosticBuilder` level. Each use of this macro defines
|
||||
/// two builder methods at that level, both of which wrap the equivalent method
|
||||
/// in `Diagnostic`.
|
||||
/// - A `&mut self -> &mut Self` method, with the same name as the underlying
|
||||
/// `Diagnostic` method. It is mostly to modify existing diagnostics, either
|
||||
/// in a standalone fashion, e.g. `err.code(code)`, or in a chained fashion
|
||||
/// to make multiple modifications, e.g. `err.code(code).span(span)`.
|
||||
/// - A `self -> Self` method, with `_mv` suffix added (short for "move").
|
||||
/// It is mostly used in a chained fashion when producing a new diagnostic,
|
||||
/// e.g. `let err = struct_err(msg).code_mv(code)`, or when emitting a new
|
||||
/// diagnostic , e.g. `struct_err(msg).code_mv(code).emit()`.
|
||||
///
|
||||
/// Although the latter method can be used to modify an existing diagnostic,
|
||||
/// e.g. `err = err.code_mv(code)`, this should be avoided because the former
|
||||
/// method give shorter code, e.g. `err.code(code)`.
|
||||
macro_rules! forward {
|
||||
// Forward pattern for &mut self -> &mut Self
|
||||
(
|
||||
$(#[$attrs:meta])*
|
||||
pub fn $n:ident(&mut self $(, $name:ident: $ty:ty)* $(,)?) -> &mut Self
|
||||
($n:ident, $n_mv:ident)($($name:ident: $ty:ty),* $(,)?)
|
||||
) => {
|
||||
$(#[$attrs])*
|
||||
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
|
||||
pub fn $n(&mut self $(, $name: $ty)*) -> &mut Self {
|
||||
self.diagnostic.$n($($name),*);
|
||||
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
|
||||
self.diag.as_mut().unwrap().$n($($name),*);
|
||||
self
|
||||
}
|
||||
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
|
||||
pub fn $n_mv(mut self, $($name: $ty),*) -> Self {
|
||||
self.diag.as_mut().unwrap().$n($($name),*);
|
||||
self
|
||||
}
|
||||
};
|
||||
@ -222,13 +202,13 @@ impl<G: EmissionGuarantee> Deref for DiagnosticBuilder<'_, G> {
|
||||
type Target = Diagnostic;
|
||||
|
||||
fn deref(&self) -> &Diagnostic {
|
||||
&self.diagnostic
|
||||
self.diag.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: EmissionGuarantee> DerefMut for DiagnosticBuilder<'_, G> {
|
||||
fn deref_mut(&mut self) -> &mut Diagnostic {
|
||||
&mut self.diagnostic
|
||||
self.diag.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,20 +222,14 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// Creates a new `DiagnosticBuilder` with an already constructed
|
||||
/// diagnostic.
|
||||
#[track_caller]
|
||||
pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diagnostic: Diagnostic) -> Self {
|
||||
pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diag: Diagnostic) -> Self {
|
||||
debug!("Created new diagnostic");
|
||||
Self {
|
||||
state: DiagnosticBuilderState::Emittable(dcx),
|
||||
diagnostic: Box::new(diagnostic),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Emit the diagnostic. Does not consume `self`, which may be surprising,
|
||||
/// but there are various places that rely on continuing to use `self`
|
||||
/// after calling `emit`.
|
||||
/// Emit and consume the diagnostic.
|
||||
#[track_caller]
|
||||
pub fn emit(&mut self) -> G::EmitResult {
|
||||
pub fn emit(self) -> G::EmitResult {
|
||||
G::emit_producing_guarantee(self)
|
||||
}
|
||||
|
||||
@ -264,21 +238,17 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
///
|
||||
/// See `emit` and `delay_as_bug` for details.
|
||||
#[track_caller]
|
||||
pub fn emit_unless(&mut self, delay: bool) -> G::EmitResult {
|
||||
pub fn emit_unless(mut self, delay: bool) -> G::EmitResult {
|
||||
if delay {
|
||||
self.downgrade_to_delayed_bug();
|
||||
}
|
||||
self.emit()
|
||||
}
|
||||
|
||||
/// Cancel the diagnostic (a structured diagnostic must either be emitted or
|
||||
/// Cancel and consume the diagnostic. (A diagnostic must either be emitted or
|
||||
/// cancelled or it will panic when dropped).
|
||||
///
|
||||
/// This method takes `self` by-value to disallow calling `.emit()` on it,
|
||||
/// which may be expected to *guarantee* the emission of an error, either
|
||||
/// at the time of the call, or through a prior `.emit()` call.
|
||||
pub fn cancel(mut self) {
|
||||
self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
self.diag = None;
|
||||
drop(self);
|
||||
}
|
||||
|
||||
@ -294,44 +264,21 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
}
|
||||
|
||||
/// Converts the builder to a `Diagnostic` for later emission,
|
||||
/// unless dcx has disabled such buffering, or `.emit()` was called.
|
||||
/// unless dcx has disabled such buffering.
|
||||
pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> {
|
||||
let dcx = match self.state {
|
||||
// No `.emit()` calls, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => dcx,
|
||||
// `.emit()` was previously called, nothing we can do.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
if dcx.inner.lock().flags.dont_buffer_diagnostics
|
||||
|| dcx.inner.lock().flags.treat_err_as_bug.is_some()
|
||||
{
|
||||
let flags = self.dcx.inner.lock().flags;
|
||||
if flags.dont_buffer_diagnostics || flags.treat_err_as_bug.is_some() {
|
||||
self.emit();
|
||||
return None;
|
||||
}
|
||||
|
||||
// Take the `Diagnostic` by replacing it with a dummy.
|
||||
let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from(""));
|
||||
let diagnostic = std::mem::replace(&mut *self.diagnostic, dummy);
|
||||
|
||||
// Disable the ICE on `Drop`.
|
||||
self.cancel();
|
||||
let diag = self.take_diag();
|
||||
|
||||
// Logging here is useful to help track down where in logs an error was
|
||||
// actually emitted.
|
||||
debug!("buffer: diagnostic={:?}", diagnostic);
|
||||
debug!("buffer: diag={:?}", diag);
|
||||
|
||||
Some((diagnostic, dcx))
|
||||
}
|
||||
|
||||
/// Retrieves the [`DiagCtxt`] if available
|
||||
pub fn dcx(&self) -> Option<&DiagCtxt> {
|
||||
match self.state {
|
||||
DiagnosticBuilderState::Emittable(dcx) => Some(dcx),
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => None,
|
||||
}
|
||||
Some((diag, self.dcx))
|
||||
}
|
||||
|
||||
/// Buffers the diagnostic for later emission,
|
||||
@ -351,170 +298,157 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// In the meantime, though, callsites are required to deal with the "bug"
|
||||
/// locally in whichever way makes the most sense.
|
||||
#[track_caller]
|
||||
pub fn delay_as_bug(&mut self) -> G::EmitResult {
|
||||
pub fn delay_as_bug(mut self) -> G::EmitResult {
|
||||
self.downgrade_to_delayed_bug();
|
||||
self.emit()
|
||||
}
|
||||
|
||||
forward!(pub fn span_label(
|
||||
&mut self,
|
||||
forward!((span_label, span_label_mv)(
|
||||
span: Span,
|
||||
label: impl Into<SubdiagnosticMessage>
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_labels(
|
||||
&mut self,
|
||||
label: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((span_labels, span_labels_mv)(
|
||||
spans: impl IntoIterator<Item = Span>,
|
||||
label: &str,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn note_expected_found(
|
||||
&mut self,
|
||||
));
|
||||
forward!((note_expected_found, note_expected_found_mv)(
|
||||
expected_label: &dyn fmt::Display,
|
||||
expected: DiagnosticStyledString,
|
||||
found_label: &dyn fmt::Display,
|
||||
found: DiagnosticStyledString,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn note_expected_found_extra(
|
||||
&mut self,
|
||||
));
|
||||
forward!((note_expected_found_extra, note_expected_found_extra_mv)(
|
||||
expected_label: &dyn fmt::Display,
|
||||
expected: DiagnosticStyledString,
|
||||
found_label: &dyn fmt::Display,
|
||||
found: DiagnosticStyledString,
|
||||
expected_extra: &dyn fmt::Display,
|
||||
found_extra: &dyn fmt::Display,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span_note(
|
||||
&mut self,
|
||||
));
|
||||
forward!((note, note_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((note_once, note_once_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((span_note, span_note_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_note_once(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_note_once, span_note_once_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span_warn(
|
||||
&mut self,
|
||||
));
|
||||
forward!((warn, warn_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((span_warn, span_warn_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn help_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span_help(
|
||||
&mut self,
|
||||
));
|
||||
forward!((help, help_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((help_once, help_once_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((span_help, span_help_once_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn is_lint(&mut self) -> &mut Self);
|
||||
forward!(pub fn disable_suggestions(&mut self) -> &mut Self);
|
||||
forward!(pub fn multipart_suggestion(
|
||||
&mut self,
|
||||
));
|
||||
forward!((multipart_suggestion, multipart_suggestion_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: Vec<(Span, String)>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn multipart_suggestion_verbose(
|
||||
&mut self,
|
||||
));
|
||||
forward!((multipart_suggestion_verbose, multipart_suggestion_verbose_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: Vec<(Span, String)>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn tool_only_multipart_suggestion(
|
||||
&mut self,
|
||||
));
|
||||
forward!((tool_only_multipart_suggestion, tool_only_multipart_suggestion_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: Vec<(Span, String)>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestion(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestion, span_suggestion_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestions(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestions, span_suggestions_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestions: impl IntoIterator<Item = String>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn multipart_suggestions(
|
||||
&mut self,
|
||||
));
|
||||
forward!((multipart_suggestions, multipart_suggestions_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestion_short(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestion_short, span_suggestion_short_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestion_verbose(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestion_verbose, span_suggestion_verbose_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestion_hidden(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestion_hidden, span_suggestion_hidden_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn tool_only_span_suggestion(
|
||||
&mut self,
|
||||
));
|
||||
forward!((tool_only_span_suggestion, tool_only_span_suggestion_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self);
|
||||
forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
|
||||
forward!(pub fn arg(
|
||||
&mut self,
|
||||
name: impl Into<Cow<'static, str>>,
|
||||
arg: impl IntoDiagnosticArg,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn subdiagnostic(
|
||||
&mut self,
|
||||
subdiagnostic: impl crate::AddToDiagnostic
|
||||
) -> &mut Self);
|
||||
));
|
||||
forward!((primary_message, primary_message_mv)(
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
));
|
||||
forward!((span, span_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
));
|
||||
forward!((code, code_mv)(
|
||||
s: DiagnosticId,
|
||||
));
|
||||
forward!((arg, arg_mv)(
|
||||
name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
|
||||
));
|
||||
forward!((subdiagnostic, subdiagnostic_mv)(
|
||||
subdiagnostic: impl crate::AddToDiagnostic,
|
||||
));
|
||||
}
|
||||
|
||||
impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.diagnostic.fmt(f)
|
||||
self.diag.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled
|
||||
/// or we emit a bug.
|
||||
/// Destructor bomb: every `DiagnosticBuilder` must be consumed (emitted,
|
||||
/// cancelled, etc.) or we emit a bug.
|
||||
impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
|
||||
fn drop(&mut self) {
|
||||
match self.state {
|
||||
// No `.emit()` or `.cancel()` calls.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
if !panicking() {
|
||||
dcx.emit_diagnostic(Diagnostic::new(
|
||||
Level::Bug,
|
||||
DiagnosticMessage::from(
|
||||
"the following error was constructed but not emitted",
|
||||
),
|
||||
));
|
||||
dcx.emit_diagnostic_without_consuming(&mut self.diagnostic);
|
||||
panic!("error was constructed but not emitted");
|
||||
}
|
||||
match self.diag.take() {
|
||||
Some(diag) if !panicking() => {
|
||||
self.dcx.emit_diagnostic(Diagnostic::new(
|
||||
Level::Bug,
|
||||
DiagnosticMessage::from("the following error was constructed but not emitted"),
|
||||
));
|
||||
self.dcx.emit_diagnostic(*diag);
|
||||
panic!("error was constructed but not emitted");
|
||||
}
|
||||
// `.emit()` was previously called, or maybe we're during `.cancel()`.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -522,11 +456,11 @@ impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
|
||||
#[macro_export]
|
||||
macro_rules! struct_span_err {
|
||||
($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({
|
||||
$dcx.struct_span_err_with_code(
|
||||
$dcx.struct_span_err(
|
||||
$span,
|
||||
format!($($message)*),
|
||||
$crate::error_code!($code),
|
||||
)
|
||||
.code_mv($crate::error_code!($code))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -249,60 +249,43 @@ impl<Id> IntoDiagnosticArg for hir::def::Res<Id> {
|
||||
|
||||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag;
|
||||
match self {
|
||||
TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
|
||||
diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space);
|
||||
diag.arg("addr_space", addr_space);
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space)
|
||||
.arg_mv("addr_space", addr_space)
|
||||
.arg_mv("cause", cause)
|
||||
.arg_mv("err", err)
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits);
|
||||
diag.arg("kind", kind);
|
||||
diag.arg("bit", bit);
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits)
|
||||
.arg_mv("kind", kind)
|
||||
.arg_mv("bit", bit)
|
||||
.arg_mv("cause", cause)
|
||||
.arg_mv("err", err)
|
||||
}
|
||||
TargetDataLayoutErrors::MissingAlignment { cause } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment);
|
||||
diag.arg("cause", cause);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment)
|
||||
.arg_mv("cause", cause)
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment);
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err_kind", err.diag_ident());
|
||||
diag.arg("align", err.align());
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment)
|
||||
.arg_mv("cause", cause)
|
||||
.arg_mv("err_kind", err.diag_ident())
|
||||
.arg_mv("align", err.align())
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
|
||||
diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
fluent::errors_target_inconsistent_architecture,
|
||||
);
|
||||
diag.arg("dl", dl);
|
||||
diag.arg("target", target);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_inconsistent_architecture)
|
||||
.arg_mv("dl", dl)
|
||||
.arg_mv("target", target)
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
|
||||
diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
fluent::errors_target_inconsistent_pointer_width,
|
||||
);
|
||||
diag.arg("pointer_size", pointer_size);
|
||||
diag.arg("target", target);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_inconsistent_pointer_width)
|
||||
.arg_mv("pointer_size", pointer_size)
|
||||
.arg_mv("target", target)
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBitsSize { err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size)
|
||||
.arg_mv("err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,11 @@
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_into_inner)]
|
||||
#![feature(extract_if)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(yeet_expr)]
|
||||
@ -507,11 +509,11 @@ pub enum StashKey {
|
||||
Cycle,
|
||||
}
|
||||
|
||||
fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
|
||||
(*f)(d)
|
||||
fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
|
||||
(*f)(diag)
|
||||
}
|
||||
|
||||
pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&mut Diagnostic, &mut dyn FnMut(&mut Diagnostic))> =
|
||||
pub static TRACK_DIAGNOSTICS: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
|
||||
AtomicRef::new(&(default_track_diagnostic as _));
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
@ -728,24 +730,7 @@ impl DiagCtxt {
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_warn(msg);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
|
||||
/// Also include a code.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_warn_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_span_warn(span, msg);
|
||||
result.code(code);
|
||||
result
|
||||
self.struct_warn(msg).span_mv(span)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warning` level with the `msg`.
|
||||
@ -785,23 +770,7 @@ impl DiagCtxt {
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_err(msg);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_err_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_span_err(span, msg);
|
||||
result.code(code);
|
||||
result
|
||||
self.struct_err(msg).span_mv(span)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level with the `msg`.
|
||||
@ -812,32 +781,6 @@ impl DiagCtxt {
|
||||
DiagnosticBuilder::new(self, Error, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level with the `msg` and the `code`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_err_with_code(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_err(msg);
|
||||
result.code(code);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warn` level with the `msg` and the `code`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_warn_with_code(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_warn(msg);
|
||||
result.code(code);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Fatal` level at the given `span` and with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
@ -846,23 +789,7 @@ impl DiagCtxt {
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, FatalAbort> {
|
||||
let mut result = self.struct_fatal(msg);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_fatal_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, FatalAbort> {
|
||||
let mut result = self.struct_span_fatal(span, msg);
|
||||
result.code(code);
|
||||
result
|
||||
self.struct_fatal(msg).span_mv(span)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Fatal` level with the `msg`.
|
||||
@ -903,9 +830,7 @@ impl DiagCtxt {
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, BugAbort> {
|
||||
let mut result = self.struct_bug(msg);
|
||||
result.span(span);
|
||||
result
|
||||
self.struct_bug(msg).span_mv(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
@ -914,17 +839,6 @@ impl DiagCtxt {
|
||||
self.struct_span_fatal(span, msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_fatal_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> ! {
|
||||
self.struct_span_fatal_with_code(span, msg, code).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_err(
|
||||
@ -935,34 +849,12 @@ impl DiagCtxt {
|
||||
self.struct_span_err(span, msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_err_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> ErrorGuaranteed {
|
||||
self.struct_span_err_with_code(span, msg, code).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
|
||||
self.struct_span_warn(span, msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_warn_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) {
|
||||
self.struct_span_warn_with_code(span, msg, code).emit()
|
||||
}
|
||||
|
||||
pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
self.struct_span_bug(span, msg).emit()
|
||||
}
|
||||
@ -1020,9 +912,7 @@ impl DiagCtxt {
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut db = DiagnosticBuilder::new(self, Note, msg);
|
||||
db.span(span);
|
||||
db
|
||||
DiagnosticBuilder::new(self, Note, msg).span_mv(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
@ -1184,17 +1074,8 @@ impl DiagCtxt {
|
||||
self.inner.borrow_mut().emitter.emit_diagnostic(&db);
|
||||
}
|
||||
|
||||
pub fn emit_diagnostic(&self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
||||
self.emit_diagnostic_without_consuming(&mut diagnostic)
|
||||
}
|
||||
|
||||
// It's unfortunate this exists. `emit_diagnostic` is preferred, because it
|
||||
// consumes the diagnostic, thus ensuring it is emitted just once.
|
||||
pub(crate) fn emit_diagnostic_without_consuming(
|
||||
&self,
|
||||
diagnostic: &mut Diagnostic,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
self.inner.borrow_mut().emit_diagnostic_without_consuming(diagnostic)
|
||||
pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
||||
self.inner.borrow_mut().emit_diagnostic(diagnostic)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
@ -1383,13 +1264,6 @@ impl DiagCtxtInner {
|
||||
}
|
||||
|
||||
fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
||||
self.emit_diagnostic_without_consuming(&mut diagnostic)
|
||||
}
|
||||
|
||||
fn emit_diagnostic_without_consuming(
|
||||
&mut self,
|
||||
diagnostic: &mut Diagnostic,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() {
|
||||
diagnostic.level = Bug;
|
||||
}
|
||||
@ -1445,7 +1319,7 @@ impl DiagCtxtInner {
|
||||
}
|
||||
|
||||
let mut guaranteed = None;
|
||||
(*TRACK_DIAGNOSTICS)(diagnostic, &mut |diagnostic| {
|
||||
(*TRACK_DIAGNOSTICS)(diagnostic, &mut |mut diagnostic| {
|
||||
if let Some(ref code) = diagnostic.code {
|
||||
self.emitted_diagnostic_codes.insert(code.clone());
|
||||
}
|
||||
@ -1481,7 +1355,7 @@ impl DiagCtxtInner {
|
||||
);
|
||||
}
|
||||
|
||||
self.emitter.emit_diagnostic(diagnostic);
|
||||
self.emitter.emit_diagnostic(&diagnostic);
|
||||
if diagnostic.is_error() {
|
||||
self.deduplicated_err_count += 1;
|
||||
} else if let Warning(_) = diagnostic.level {
|
||||
|
@ -1232,7 +1232,7 @@ pub fn expr_to_string(
|
||||
) -> Option<(Symbol, ast::StrStyle)> {
|
||||
expr_to_spanned_string(cx, expr, err_msg)
|
||||
.map_err(|err| {
|
||||
err.map(|(mut err, _)| {
|
||||
err.map(|(err, _)| {
|
||||
err.emit();
|
||||
})
|
||||
})
|
||||
@ -1254,7 +1254,7 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str
|
||||
pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> {
|
||||
match p.parse_expr() {
|
||||
Ok(e) => return Some(e),
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
@ -362,7 +362,7 @@ impl<'a> StripUnconfigured<'a> {
|
||||
pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option<MetaItem>) {
|
||||
let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) {
|
||||
Ok(meta_item) => meta_item,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return (true, None);
|
||||
}
|
||||
|
@ -735,7 +735,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
fragment_kind.expect_from_annotatables(items)
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
fragment_kind.dummy(span)
|
||||
}
|
||||
|
@ -679,8 +679,8 @@ impl TtParser {
|
||||
// We use the span of the metavariable declaration to determine any
|
||||
// edition-specific matching behavior for non-terminals.
|
||||
let nt = match parser.to_mut().parse_nonterminal(kind) {
|
||||
Err(mut err) => {
|
||||
let guarantee = err.span_label(
|
||||
Err(err) => {
|
||||
let guarantee = err.span_label_mv(
|
||||
span,
|
||||
format!(
|
||||
"while parsing argument for this `{kind}` macro fragment"
|
||||
|
@ -215,7 +215,7 @@ fn expand_macro<'cx>(
|
||||
// rhs has holes ( `$id` and `$(...)` that need filled)
|
||||
let tts = match transcribe(cx, &named_matches, rhs, rhs_span, transparency) {
|
||||
Ok(tts) => tts,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(arm_span);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ pub(super) fn parse(
|
||||
);
|
||||
sess.dcx
|
||||
.struct_span_err(span, msg)
|
||||
.help(VALID_FRAGMENT_NAMES_MSG)
|
||||
.help_mv(VALID_FRAGMENT_NAMES_MSG)
|
||||
.emit();
|
||||
token::NonterminalKind::Ident
|
||||
},
|
||||
@ -175,7 +175,7 @@ fn parse_tree<'a>(
|
||||
// of a meta-variable expression (e.g. `${count(ident)}`).
|
||||
// Try to parse the meta-variable expression.
|
||||
match MetaVarExpr::parse(tts, delim_span.entire(), sess) {
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
// Returns early the same read `$` to avoid spanning
|
||||
// unrelated diagnostics that could be performed afterwards
|
||||
|
@ -282,7 +282,7 @@ impl ModError<'_> {
|
||||
secondary_path: secondary_path.display().to_string(),
|
||||
})
|
||||
}
|
||||
ModError::ParserError(mut err) => err.emit(),
|
||||
ModError::ParserError(err) => err.emit(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ impl MultiItemModifier for DeriveProcMacro {
|
||||
items.push(Annotatable::Item(item));
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
|
@ -537,7 +537,7 @@ impl server::TokenStream for Rustc<'_, '_> {
|
||||
}
|
||||
expr
|
||||
};
|
||||
let expr = expr.map_err(|mut err| {
|
||||
let expr = expr.map_err(|err| {
|
||||
err.emit();
|
||||
})?;
|
||||
|
||||
|
@ -305,7 +305,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
binding.span,
|
||||
format!("{} `{}` is private", assoc_item.kind, binding.item_name),
|
||||
)
|
||||
.span_label(binding.span, format!("private {}", assoc_item.kind))
|
||||
.span_label_mv(binding.span, format!("private {}", assoc_item.kind))
|
||||
.emit();
|
||||
}
|
||||
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);
|
||||
|
@ -58,13 +58,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
if !trait_def.paren_sugar {
|
||||
if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
|
||||
// For now, require that parenthetical notation be used only with `Fn()` etc.
|
||||
let mut err = feature_err(
|
||||
feature_err(
|
||||
&self.tcx().sess.parse_sess,
|
||||
sym::unboxed_closures,
|
||||
span,
|
||||
"parenthetical notation is only stable when used with `Fn`-family traits",
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -70,7 +70,7 @@ fn generic_arg_mismatch_err(
|
||||
Res::Err => {
|
||||
add_braces_suggestion(arg, &mut err);
|
||||
return err
|
||||
.primary_message("unresolved item provided when a constant was expected")
|
||||
.primary_message_mv("unresolved item provided when a constant was expected")
|
||||
.emit();
|
||||
}
|
||||
Res::Def(DefKind::TyParam, src_def_id) => {
|
||||
@ -650,9 +650,9 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
|
||||
if position == GenericArgPosition::Value
|
||||
&& args.num_lifetime_params() != param_counts.lifetimes
|
||||
{
|
||||
let mut err = struct_span_err!(tcx.dcx(), span, E0794, "{}", msg);
|
||||
err.span_note(span_late, note);
|
||||
err.emit();
|
||||
struct_span_err!(tcx.dcx(), span, E0794, "{}", msg)
|
||||
.span_note_mv(span_late, note)
|
||||
.emit();
|
||||
} else {
|
||||
let mut multispan = MultiSpan::from_span(span);
|
||||
multispan.push_span_label(span_late, note);
|
||||
|
@ -1647,9 +1647,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
let msg = format!("{kind} `{name}` is private");
|
||||
let def_span = tcx.def_span(item);
|
||||
tcx.dcx()
|
||||
.struct_span_err_with_code(span, msg, rustc_errors::error_code!(E0624))
|
||||
.span_label(span, format!("private {kind}"))
|
||||
.span_label(def_span, format!("{kind} defined here"))
|
||||
.struct_span_err(span, msg)
|
||||
.code_mv(rustc_errors::error_code!(E0624))
|
||||
.span_label_mv(span, format!("private {kind}"))
|
||||
.span_label_mv(def_span, format!("{kind} defined here"))
|
||||
.emit();
|
||||
}
|
||||
tcx.check_stability(item, Some(block), span, None);
|
||||
|
@ -290,19 +290,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
|
||||
if references_self {
|
||||
let def_id = i.bottom().0.def_id();
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
tcx.dcx(),
|
||||
i.bottom().1,
|
||||
E0038,
|
||||
"the {} `{}` cannot be made into an object",
|
||||
tcx.def_descr(def_id),
|
||||
tcx.item_name(def_id),
|
||||
);
|
||||
err.note(
|
||||
)
|
||||
.note_mv(
|
||||
rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![])
|
||||
.error_msg(),
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
ty::ExistentialTraitRef { def_id: trait_ref.def_id, args }
|
||||
@ -375,7 +375,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
self.ast_region_to_region(lifetime, None)
|
||||
} else {
|
||||
self.re_infer(None, span).unwrap_or_else(|| {
|
||||
let mut err = struct_span_err!(
|
||||
let err = struct_span_err!(
|
||||
tcx.dcx(),
|
||||
span,
|
||||
E0228,
|
||||
|
@ -550,8 +550,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
E0044,
|
||||
"foreign items may not have {kinds} parameters",
|
||||
)
|
||||
.span_label(item.span, format!("can't have {kinds} parameters"))
|
||||
.help(
|
||||
.span_label_mv(item.span, format!("can't have {kinds} parameters"))
|
||||
.help_mv(
|
||||
// FIXME: once we start storing spans for type arguments, turn this
|
||||
// into a suggestion.
|
||||
format!(
|
||||
@ -788,7 +788,7 @@ fn check_impl_items_against_trait<'tcx>(
|
||||
};
|
||||
tcx.dcx()
|
||||
.struct_span_err(tcx.def_span(def_id), msg)
|
||||
.note(format!(
|
||||
.note_mv(format!(
|
||||
"specialization behaves in inconsistent and \
|
||||
surprising ways with {feature}, \
|
||||
and for now is disallowed"
|
||||
@ -830,7 +830,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
|
||||
let e = fields[FieldIdx::from_u32(0)].ty(tcx, args);
|
||||
if !fields.iter().all(|f| f.ty(tcx, args) == e) {
|
||||
struct_span_err!(tcx.dcx(), sp, E0076, "SIMD vector should be homogeneous")
|
||||
.span_label(sp, "SIMD elements must have the same type")
|
||||
.span_label_mv(sp, "SIMD elements must have the same type")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
@ -1107,7 +1107,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
E0084,
|
||||
"unsupported representation for zero-variant enum"
|
||||
)
|
||||
.span_label(tcx.def_span(def_id), "zero-variant enum")
|
||||
.span_label_mv(tcx.def_span(def_id), "zero-variant enum")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
@ -1140,13 +1140,13 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var));
|
||||
|
||||
if disr_non_unit || (disr_units && has_non_units) {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
tcx.dcx(),
|
||||
tcx.def_span(def_id),
|
||||
E0732,
|
||||
"`#[repr(inttype)]` must be specified"
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1249,7 +1249,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut e) = error {
|
||||
if let Some(e) = error {
|
||||
e.emit();
|
||||
}
|
||||
|
||||
@ -1294,7 +1294,7 @@ pub(super) fn check_type_params_are_used<'tcx>(
|
||||
{
|
||||
let span = tcx.def_span(param.def_id);
|
||||
struct_span_err!(tcx.dcx(), span, E0091, "type parameter `{}` is unused", param.name,)
|
||||
.span_label(span, "unused type parameter")
|
||||
.span_label_mv(span, "unused type parameter")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
@ -1302,9 +1302,9 @@ pub(super) fn check_type_params_are_used<'tcx>(
|
||||
|
||||
fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
|
||||
struct_span_err!(tcx.dcx(), span, E0733, "recursion in an `async fn` requires boxing")
|
||||
.span_label(span, "recursive `async fn`")
|
||||
.note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
|
||||
.note(
|
||||
.span_label_mv(span, "recursive `async fn`")
|
||||
.note_mv("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
|
||||
.note_mv(
|
||||
"consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
|
||||
)
|
||||
.emit()
|
||||
|
@ -934,12 +934,12 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
||||
return_span,
|
||||
"return type captures more lifetimes than trait definition",
|
||||
)
|
||||
.span_label(self.tcx.def_span(def_id), "this lifetime was captured")
|
||||
.span_note(
|
||||
.span_label_mv(self.tcx.def_span(def_id), "this lifetime was captured")
|
||||
.span_note_mv(
|
||||
self.tcx.def_span(self.def_id),
|
||||
"hidden type must only reference lifetimes captured by this impl trait",
|
||||
)
|
||||
.note(format!("hidden type inferred to be `{}`", self.ty))
|
||||
.note_mv(format!("hidden type inferred to be `{}`", self.ty))
|
||||
.emit()
|
||||
}
|
||||
_ => {
|
||||
@ -1371,7 +1371,7 @@ fn compare_number_of_generics<'tcx>(
|
||||
let spans = arg_spans(impl_.kind, impl_item.generics);
|
||||
let span = spans.first().copied();
|
||||
|
||||
let mut err = tcx.dcx().struct_span_err_with_code(
|
||||
let mut err = tcx.dcx().struct_span_err(
|
||||
spans,
|
||||
format!(
|
||||
"{} `{}` has {} {kind} parameter{} but its trait \
|
||||
@ -1384,8 +1384,8 @@ fn compare_number_of_generics<'tcx>(
|
||||
pluralize!(trait_count),
|
||||
kind = kind,
|
||||
),
|
||||
DiagnosticId::Error("E0049".into()),
|
||||
);
|
||||
err.code(DiagnosticId::Error("E0049".into()));
|
||||
|
||||
let msg =
|
||||
format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);
|
||||
|
@ -161,7 +161,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||
"`Drop` impl requires `{root_predicate}` \
|
||||
but the {self_descr} it is implemented for does not",
|
||||
)
|
||||
.span_note(item_span, "the implementor must specify the same requirement")
|
||||
.span_note_mv(item_span, "the implementor must specify the same requirement")
|
||||
.emit(),
|
||||
);
|
||||
}
|
||||
@ -193,7 +193,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||
"`Drop` impl requires `{outlives}` \
|
||||
but the {self_descr} it is implemented for does not",
|
||||
)
|
||||
.span_note(item_span, "the implementor must specify the same requirement")
|
||||
.span_note_mv(item_span, "the implementor must specify the same requirement")
|
||||
.emit(),
|
||||
);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ fn equate_intrinsic_type<'tcx>(
|
||||
}
|
||||
_ => {
|
||||
struct_span_err!(tcx.dcx(), it.span, E0622, "intrinsic must be a function")
|
||||
.span_label(it.span, "expected a function")
|
||||
.span_label_mv(it.span, "expected a function")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
@ -153,12 +153,14 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
};
|
||||
let Some(asm_ty) = asm_ty else {
|
||||
let msg = format!("cannot use value of type `{ty}` for inline assembly");
|
||||
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
|
||||
err.note(
|
||||
"only integers, floats, SIMD vectors, pointers and function pointers \
|
||||
can be used as arguments for inline assembly",
|
||||
);
|
||||
err.emit();
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(expr.span, msg)
|
||||
.note_mv(
|
||||
"only integers, floats, SIMD vectors, pointers and function pointers \
|
||||
can be used as arguments for inline assembly",
|
||||
)
|
||||
.emit();
|
||||
return None;
|
||||
};
|
||||
|
||||
@ -166,9 +168,11 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
// possibly fail is for SIMD types which don't #[derive(Copy)].
|
||||
if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
|
||||
let msg = "arguments for inline assembly must be copyable";
|
||||
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
|
||||
err.note(format!("`{ty}` does not implement the Copy trait"));
|
||||
err.emit();
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(expr.span, msg)
|
||||
.note_mv(format!("`{ty}` does not implement the Copy trait"))
|
||||
.emit();
|
||||
}
|
||||
|
||||
// Ideally we wouldn't need to do this, but LLVM's register allocator
|
||||
@ -183,16 +187,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
if let Some((in_expr, Some(in_asm_ty))) = tied_input {
|
||||
if in_asm_ty != asm_ty {
|
||||
let msg = "incompatible types for asm inout argument";
|
||||
let mut err = self.tcx.dcx().struct_span_err(vec![in_expr.span, expr.span], msg);
|
||||
|
||||
let in_expr_ty = (self.get_operand_ty)(in_expr);
|
||||
err.span_label(in_expr.span, format!("type `{in_expr_ty}`"));
|
||||
err.span_label(expr.span, format!("type `{ty}`"));
|
||||
err.note(
|
||||
"asm inout arguments must have the same type, \
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(vec![in_expr.span, expr.span], msg)
|
||||
.span_label_mv(in_expr.span, format!("type `{in_expr_ty}`"))
|
||||
.span_label_mv(expr.span, format!("type `{ty}`"))
|
||||
.note_mv(
|
||||
"asm inout arguments must have the same type, \
|
||||
unless they are both pointers or integers of the same size",
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
// All of the later checks have already been done on the input, so
|
||||
@ -234,13 +239,15 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
if let Some(feature) = feature {
|
||||
if !target_features.contains(feature) {
|
||||
let msg = format!("`{feature}` target feature is not enabled");
|
||||
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
|
||||
err.note(format!(
|
||||
"this is required to use type `{}` with register class `{}`",
|
||||
ty,
|
||||
reg_class.name(),
|
||||
));
|
||||
err.emit();
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(expr.span, msg)
|
||||
.note_mv(format!(
|
||||
"this is required to use type `{}` with register class `{}`",
|
||||
ty,
|
||||
reg_class.name(),
|
||||
))
|
||||
.emit();
|
||||
return Some(asm_ty);
|
||||
}
|
||||
}
|
||||
@ -449,14 +456,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
ty::Never | ty::Error(_) => {}
|
||||
ty::FnDef(..) => {}
|
||||
_ => {
|
||||
let mut err =
|
||||
self.tcx.dcx().struct_span_err(*op_sp, "invalid `sym` operand");
|
||||
err.span_label(
|
||||
self.tcx.def_span(anon_const.def_id),
|
||||
format!("is {} `{}`", ty.kind().article(), ty),
|
||||
);
|
||||
err.help("`sym` operands must refer to either a function or a static");
|
||||
err.emit();
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(*op_sp, "invalid `sym` operand")
|
||||
.span_label_mv(
|
||||
self.tcx.def_span(anon_const.def_id),
|
||||
format!("is {} `{}`", ty.kind().article(), ty),
|
||||
)
|
||||
.help_mv(
|
||||
"`sym` operands must refer to either a function or a static",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -197,11 +197,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
|
||||
let mut res = Ok(());
|
||||
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
|
||||
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
|
||||
let mut err =
|
||||
tcx.dcx().struct_span_err(sp, "impls of auto traits cannot be default");
|
||||
err.span_labels(impl_.defaultness_span, "default because of this");
|
||||
err.span_label(sp, "auto trait");
|
||||
res = Err(err.emit());
|
||||
res = Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(sp, "impls of auto traits cannot be default")
|
||||
.span_labels_mv(impl_.defaultness_span, "default because of this")
|
||||
.span_label_mv(sp, "auto trait")
|
||||
.emit());
|
||||
}
|
||||
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
|
||||
match tcx.impl_polarity(def_id) {
|
||||
@ -489,35 +490,33 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
||||
|
||||
if !unsatisfied_bounds.is_empty() {
|
||||
let plural = pluralize!(unsatisfied_bounds.len());
|
||||
let mut err = tcx.dcx().struct_span_err(
|
||||
gat_item_hir.span,
|
||||
format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
|
||||
);
|
||||
|
||||
let suggestion = format!(
|
||||
"{} {}",
|
||||
gat_item_hir.generics.add_where_or_trailing_comma(),
|
||||
unsatisfied_bounds.join(", "),
|
||||
);
|
||||
err.span_suggestion(
|
||||
gat_item_hir.generics.tail_span_for_predicate_suggestion(),
|
||||
format!("add the required where clause{plural}"),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
let bound =
|
||||
if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };
|
||||
err.note(format!(
|
||||
"{bound} currently required to ensure that impls have maximum flexibility"
|
||||
));
|
||||
err.note(
|
||||
"we are soliciting feedback, see issue #87479 \
|
||||
tcx.dcx()
|
||||
.struct_span_err(
|
||||
gat_item_hir.span,
|
||||
format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
|
||||
)
|
||||
.span_suggestion_mv(
|
||||
gat_item_hir.generics.tail_span_for_predicate_suggestion(),
|
||||
format!("add the required where clause{plural}"),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note_mv(format!(
|
||||
"{bound} currently required to ensure that impls have maximum flexibility"
|
||||
))
|
||||
.note_mv(
|
||||
"we are soliciting feedback, see issue #87479 \
|
||||
<https://github.com/rust-lang/rust/issues/87479> \
|
||||
for more information",
|
||||
);
|
||||
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -838,8 +837,8 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
|
||||
trait_should_be_self,
|
||||
"associated item referring to unboxed trait object for its own trait",
|
||||
)
|
||||
.span_label(trait_name.span, "in this trait")
|
||||
.multipart_suggestion(
|
||||
.span_label_mv(trait_name.span, "in this trait")
|
||||
.multipart_suggestion_mv(
|
||||
"you might have meant to use `Self` to refer to the implementing type",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
@ -938,8 +937,8 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
||||
};
|
||||
if may_suggest_feature && tcx.sess.is_nightly_build() {
|
||||
diag.help(
|
||||
"add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
|
||||
);
|
||||
"add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
|
||||
);
|
||||
}
|
||||
|
||||
Err(diag.emit())
|
||||
@ -1599,7 +1598,7 @@ fn check_method_receiver<'tcx>(
|
||||
the `arbitrary_self_types` feature",
|
||||
),
|
||||
)
|
||||
.help(HELP_FOR_SELF_TYPE)
|
||||
.help_mv(HELP_FOR_SELF_TYPE)
|
||||
.emit()
|
||||
} else {
|
||||
// Report error; would not have worked with `arbitrary_self_types`.
|
||||
@ -1612,8 +1611,8 @@ fn check_method_receiver<'tcx>(
|
||||
|
||||
fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed {
|
||||
struct_span_err!(tcx.dcx(), span, E0307, "invalid `self` parameter type: {receiver_ty}")
|
||||
.note("type of `self` must be `Self` or a type that dereferences to it")
|
||||
.help(HELP_FOR_SELF_TYPE)
|
||||
.note_mv("type of `self` must be `Self` or a type that dereferences to it")
|
||||
.help_mv(HELP_FOR_SELF_TYPE)
|
||||
.emit()
|
||||
}
|
||||
|
||||
@ -1921,10 +1920,8 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error
|
||||
}
|
||||
|
||||
fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> {
|
||||
let mut err =
|
||||
struct_span_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used");
|
||||
err.span_label(span, "unused parameter");
|
||||
err
|
||||
struct_span_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used")
|
||||
.span_label_mv(span, "unused parameter")
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
@ -70,17 +70,16 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
||||
match seen_items.entry(norm_ident) {
|
||||
Entry::Occupied(entry) => {
|
||||
let former = entry.get();
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.tcx.dcx(),
|
||||
span,
|
||||
E0592,
|
||||
"duplicate definitions with name `{}`",
|
||||
ident,
|
||||
);
|
||||
err.span_label(span, format!("duplicate definitions for `{ident}`"));
|
||||
err.span_label(*former, format!("other definition for `{ident}`"));
|
||||
|
||||
err.emit();
|
||||
)
|
||||
.span_label_mv(span, format!("duplicate definitions for `{ident}`"))
|
||||
.span_label_mv(*former, format!("other definition for `{ident}`"))
|
||||
.emit();
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(span);
|
||||
|
@ -181,7 +181,7 @@ fn check_object_overlap<'tcx>(
|
||||
trait_ref.self_ty(),
|
||||
tcx.def_path_str(trait_def_id)
|
||||
)
|
||||
.span_label(
|
||||
.span_label_mv(
|
||||
span,
|
||||
format!(
|
||||
"`{}` automatically implements trait `{}`",
|
||||
|
@ -25,7 +25,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
"implementing the trait `{}` is not unsafe",
|
||||
trait_ref.print_trait_sugared()
|
||||
)
|
||||
.span_suggestion_verbose(
|
||||
.span_suggestion_verbose_mv(
|
||||
item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)),
|
||||
"remove `unsafe` from this trait implementation",
|
||||
"",
|
||||
@ -42,13 +42,13 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
"the trait `{}` requires an `unsafe impl` declaration",
|
||||
trait_ref.print_trait_sugared()
|
||||
)
|
||||
.note(format!(
|
||||
.note_mv(format!(
|
||||
"the trait `{}` enforces invariants that the compiler can't check. \
|
||||
Review the trait documentation and make sure this implementation \
|
||||
upholds those invariants before adding the `unsafe` keyword",
|
||||
trait_ref.print_trait_sugared()
|
||||
))
|
||||
.span_suggestion_verbose(
|
||||
.span_suggestion_verbose_mv(
|
||||
item.span.shrink_to_lo(),
|
||||
"add `unsafe` to this trait implementation",
|
||||
"unsafe ",
|
||||
@ -65,13 +65,13 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
|
||||
attr_name
|
||||
)
|
||||
.note(format!(
|
||||
.note_mv(format!(
|
||||
"the trait `{}` enforces invariants that the compiler can't check. \
|
||||
Review the trait documentation and make sure this implementation \
|
||||
upholds those invariants before adding the `unsafe` keyword",
|
||||
trait_ref.print_trait_sugared()
|
||||
))
|
||||
.span_suggestion_verbose(
|
||||
.span_suggestion_verbose_mv(
|
||||
item.span.shrink_to_lo(),
|
||||
"add `unsafe` to this trait implementation",
|
||||
"unsafe ",
|
||||
|
@ -750,12 +750,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||
kind: hir::ItemKind::OpaqueTy { .. }, ..
|
||||
}) = self.tcx.hir_node(parent_id)
|
||||
{
|
||||
let mut err = self.tcx.dcx().struct_span_err(
|
||||
self.tcx.dcx().struct_span_err(
|
||||
lifetime.ident.span,
|
||||
"higher kinded lifetime bounds on nested opaque types are not supported yet",
|
||||
);
|
||||
err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
|
||||
err.emit();
|
||||
)
|
||||
.span_note_mv(self.tcx.def_span(def_id), "lifetime declared here")
|
||||
.emit();
|
||||
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
|
||||
}
|
||||
}
|
||||
@ -2114,7 +2114,7 @@ pub fn deny_non_region_late_bound(
|
||||
hir::GenericParamKind::Lifetime { .. } => continue,
|
||||
};
|
||||
|
||||
let mut diag = tcx.dcx().struct_span_err(
|
||||
let diag = tcx.dcx().struct_span_err(
|
||||
param.span,
|
||||
format!("late-bound {what} parameter not allowed on {where_}"),
|
||||
);
|
||||
|
@ -523,8 +523,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||
fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx> {
|
||||
let span = self.path_segment.ident.span;
|
||||
let msg = self.create_error_message();
|
||||
|
||||
self.tcx.dcx().struct_span_err_with_code(span, msg, self.code())
|
||||
self.tcx.dcx().struct_span_err(span, msg).code_mv(self.code())
|
||||
}
|
||||
|
||||
/// Builds the `expected 1 type argument / supplied 2 type arguments` message.
|
||||
|
@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
callee_expr.span,
|
||||
format!("evaluate({predicate:?}) = {result:?}"),
|
||||
)
|
||||
.span_label(predicate_span, "predicate")
|
||||
.span_label_mv(predicate_span, "predicate")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
}
|
||||
CastError::NeedViaInt => {
|
||||
make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx)
|
||||
.help("cast through an integer first")
|
||||
.help_mv("cast through an integer first")
|
||||
.emit();
|
||||
}
|
||||
CastError::IllegalCast => {
|
||||
@ -277,7 +277,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
}
|
||||
CastError::DifferingKinds => {
|
||||
make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx)
|
||||
.note("vtable kinds may not match")
|
||||
.note_mv("vtable kinds may not match")
|
||||
.emit();
|
||||
}
|
||||
CastError::CastToBool => {
|
||||
@ -512,7 +512,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
self.cast_ty,
|
||||
fcx,
|
||||
)
|
||||
.note("cannot cast an enum with a non-exhaustive variant when it's defined in another crate")
|
||||
.note_mv("cannot cast an enum with a non-exhaustive variant when it's defined in another crate")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Requires that the two types unify, and prints an error message if
|
||||
/// they don't.
|
||||
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
if let Some(mut e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
if let Some(e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
e.emit();
|
||||
}
|
||||
}
|
||||
@ -189,7 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) {
|
||||
if let Some(err) = self.demand_eqtype_diag(sp, expected, actual) {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
@ -228,7 +228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
) -> Ty<'tcx> {
|
||||
let (ty, err) =
|
||||
self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
|
||||
if let Some(mut err) = err {
|
||||
if let Some(err) = err {
|
||||
err.emit();
|
||||
}
|
||||
ty
|
||||
|
@ -940,12 +940,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Make this use Diagnostic once error codes can be dynamically set.
|
||||
let mut err = self.dcx().struct_span_err_with_code(
|
||||
op_span,
|
||||
"invalid left-hand side of assignment",
|
||||
DiagnosticId::Error(err_code.into()),
|
||||
);
|
||||
let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment");
|
||||
err.code(DiagnosticId::Error(err_code.into()));
|
||||
err.span_label(lhs.span, "cannot assign to this expression");
|
||||
|
||||
self.comes_from_while_condition(lhs.hir_id, |expr| {
|
||||
@ -1338,7 +1334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
Err(error) => {
|
||||
if segment.ident.name != kw::Empty {
|
||||
if let Some(mut err) = self.report_method_error(
|
||||
if let Some(err) = self.report_method_error(
|
||||
span,
|
||||
rcvr_t,
|
||||
segment.ident,
|
||||
@ -2011,7 +2007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
!= range_def_id
|
||||
{
|
||||
// Suppress any range expr type mismatches
|
||||
if let Some(mut diag) =
|
||||
if let Some(diag) =
|
||||
self.dcx().steal_diagnostic(last_expr_field.span, StashKey::MaybeFruTypo)
|
||||
{
|
||||
diag.delay_as_bug();
|
||||
@ -2836,15 +2832,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
fn private_field_err(&self, field: Ident, base_did: DefId) -> DiagnosticBuilder<'_> {
|
||||
let struct_path = self.tcx().def_path_str(base_did);
|
||||
let kind_name = self.tcx().def_descr(base_did);
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
field.span,
|
||||
E0616,
|
||||
"field `{field}` of {kind_name} `{struct_path}` is private",
|
||||
);
|
||||
err.span_label(field.span, "private field");
|
||||
|
||||
err
|
||||
)
|
||||
.span_label_mv(field.span, "private field")
|
||||
}
|
||||
|
||||
pub(crate) fn get_field_candidates_considering_privacy(
|
||||
@ -3185,9 +3179,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.require_type_is_sized(ty, expr.span, traits::InlineAsmSized);
|
||||
|
||||
if !is_input && !expr.is_syntactic_place_expr() {
|
||||
let mut err = self.dcx().struct_span_err(expr.span, "invalid asm output");
|
||||
err.span_label(expr.span, "cannot assign to this expression");
|
||||
err.emit();
|
||||
self.dcx()
|
||||
.struct_span_err(expr.span, "invalid asm output")
|
||||
.span_label_mv(expr.span, "cannot assign to this expression")
|
||||
.emit();
|
||||
}
|
||||
|
||||
// If this is an input value, we require its type to be fully resolved
|
||||
@ -3280,27 +3275,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.iter_enumerated()
|
||||
.find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident)
|
||||
else {
|
||||
let mut err = type_error_struct!(
|
||||
type_error_struct!(
|
||||
self.dcx(),
|
||||
ident.span,
|
||||
container,
|
||||
E0599,
|
||||
"no variant named `{ident}` found for enum `{container}`",
|
||||
);
|
||||
err.span_label(field.span, "variant not found");
|
||||
err.emit();
|
||||
)
|
||||
.span_label_mv(field.span, "variant not found")
|
||||
.emit();
|
||||
break;
|
||||
};
|
||||
let Some(&subfield) = fields.next() else {
|
||||
let mut err = type_error_struct!(
|
||||
type_error_struct!(
|
||||
self.dcx(),
|
||||
ident.span,
|
||||
container,
|
||||
E0795,
|
||||
"`{ident}` is an enum variant; expected field at end of `offset_of`",
|
||||
);
|
||||
err.span_label(field.span, "enum variant");
|
||||
err.emit();
|
||||
)
|
||||
.span_label_mv(field.span, "enum variant")
|
||||
.emit();
|
||||
break;
|
||||
};
|
||||
let (subident, sub_def_scope) =
|
||||
@ -3311,16 +3306,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.iter_enumerated()
|
||||
.find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident)
|
||||
else {
|
||||
let mut err = type_error_struct!(
|
||||
type_error_struct!(
|
||||
self.dcx(),
|
||||
ident.span,
|
||||
container,
|
||||
E0609,
|
||||
"no field named `{subfield}` on enum variant `{container}::{ident}`",
|
||||
);
|
||||
err.span_label(field.span, "this enum variant...");
|
||||
err.span_label(subident.span, "...does not have this field");
|
||||
err.emit();
|
||||
)
|
||||
.span_label_mv(field.span, "this enum variant...")
|
||||
.span_label_mv(subident.span, "...does not have this field")
|
||||
.emit();
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -845,7 +845,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.and_then(|r| {
|
||||
// lint bare trait if the method is found in the trait
|
||||
if span.edition().at_least_rust_2021()
|
||||
&& let Some(mut diag) =
|
||||
&& let Some(diag) =
|
||||
self.dcx().steal_diagnostic(qself.span, StashKey::TraitMissingMethod)
|
||||
{
|
||||
diag.emit();
|
||||
@ -877,7 +877,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// emit or cancel the diagnostic for bare traits
|
||||
if span.edition().at_least_rust_2021()
|
||||
&& let Some(mut diag) =
|
||||
&& let Some(diag) =
|
||||
self.dcx().steal_diagnostic(qself.span, StashKey::TraitMissingMethod)
|
||||
{
|
||||
if trait_missing_method {
|
||||
@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if item_name.name != kw::Empty {
|
||||
if let Some(mut e) = self.report_method_error(
|
||||
if let Some(e) = self.report_method_error(
|
||||
span,
|
||||
ty.normalized,
|
||||
item_name,
|
||||
|
@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
format!("arguments to this {call_name} are incorrect"),
|
||||
);
|
||||
} else {
|
||||
err = tcx.dcx().struct_span_err_with_code(
|
||||
err = tcx.dcx().struct_span_err(
|
||||
full_call_span,
|
||||
format!(
|
||||
"{call_name} takes {}{} but {} {} supplied",
|
||||
@ -676,8 +676,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
potentially_plural_count(provided_args.len(), "argument"),
|
||||
pluralize!("was", provided_args.len())
|
||||
),
|
||||
DiagnosticId::Error(err_code.to_owned()),
|
||||
);
|
||||
err.code(DiagnosticId::Error(err_code.to_owned()));
|
||||
err.multipart_suggestion_verbose(
|
||||
"wrap these arguments in parentheses to construct a tuple",
|
||||
vec![
|
||||
@ -815,18 +815,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
call_name,
|
||||
)
|
||||
} else {
|
||||
tcx.dcx().struct_span_err_with_code(
|
||||
full_call_span,
|
||||
format!(
|
||||
"this {} takes {}{} but {} {} supplied",
|
||||
call_name,
|
||||
if c_variadic { "at least " } else { "" },
|
||||
potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
|
||||
potentially_plural_count(provided_args.len(), "argument"),
|
||||
pluralize!("was", provided_args.len())
|
||||
),
|
||||
DiagnosticId::Error(err_code.to_owned()),
|
||||
)
|
||||
tcx.dcx()
|
||||
.struct_span_err(
|
||||
full_call_span,
|
||||
format!(
|
||||
"this {} takes {}{} but {} {} supplied",
|
||||
call_name,
|
||||
if c_variadic { "at least " } else { "" },
|
||||
potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
|
||||
potentially_plural_count(provided_args.len(), "argument"),
|
||||
pluralize!("was", provided_args.len())
|
||||
),
|
||||
)
|
||||
.code_mv(DiagnosticId::Error(err_code.to_owned()))
|
||||
};
|
||||
|
||||
// As we encounter issues, keep track of what we want to provide for the suggestion
|
||||
@ -1384,7 +1385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
"expected struct, variant or union type, found {}",
|
||||
ty.normalized.sort_string(self.tcx)
|
||||
)
|
||||
.span_label(path_span, "not a struct")
|
||||
.span_label_mv(path_span, "not a struct")
|
||||
.emit(),
|
||||
})
|
||||
}
|
||||
@ -1459,8 +1460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let previous_diverges = self.diverges.get();
|
||||
let else_ty = self.check_block_with_expected(blk, NoExpectation);
|
||||
let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
|
||||
if let Some(mut err) =
|
||||
self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
|
||||
if let Some(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
|
||||
{
|
||||
err.emit();
|
||||
}
|
||||
|
@ -74,9 +74,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& size_to == Pointer(dl.instruction_address_space).size(&tcx)
|
||||
{
|
||||
struct_span_err!(tcx.dcx(), span, E0591, "can't transmute zero-sized type")
|
||||
.note(format!("source type: {from}"))
|
||||
.note(format!("target type: {to}"))
|
||||
.help("cast with `as` to a pointer instead")
|
||||
.note_mv(format!("source type: {from}"))
|
||||
.note_mv(format!("target type: {to}"))
|
||||
.help_mv("cast with `as` to a pointer instead")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
@ -121,6 +121,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
if from == to {
|
||||
err.note(format!("`{from}` does not have a fixed size"));
|
||||
err.emit();
|
||||
} else {
|
||||
err.note(format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
|
||||
.note(format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
|
||||
@ -128,8 +129,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
err.delay_as_bug();
|
||||
} else if let Err(LayoutError::ReferencesError(_)) = sk_to {
|
||||
err.delay_as_bug();
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
@ -366,18 +366,17 @@ fn report_unexpected_variant_res(
|
||||
_ => res.descr(),
|
||||
};
|
||||
let path_str = rustc_hir_pretty::qpath_to_string(qpath);
|
||||
let mut err = tcx.dcx().struct_span_err_with_code(
|
||||
span,
|
||||
format!("expected {expected}, found {res_descr} `{path_str}`"),
|
||||
DiagnosticId::Error(err_code.into()),
|
||||
);
|
||||
let err = tcx
|
||||
.dcx()
|
||||
.struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
|
||||
.code_mv(DiagnosticId::Error(err_code.into()));
|
||||
match res {
|
||||
Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => {
|
||||
let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
|
||||
err.span_label(span, "`fn` calls are not allowed in patterns");
|
||||
err.help(format!("for more information, visit {patterns_url}"))
|
||||
err.span_label_mv(span, "`fn` calls are not allowed in patterns")
|
||||
.help_mv(format!("for more information, visit {patterns_url}"))
|
||||
}
|
||||
_ => err.span_label(span, format!("not a {expected}")),
|
||||
_ => err.span_label_mv(span, format!("not a {expected}")),
|
||||
}
|
||||
.emit()
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& let hir::ExprKind::Assign(..) = expr.kind
|
||||
{
|
||||
// We defer to the later error produced by `check_lhs_assignable`.
|
||||
err.delay_as_bug();
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
|
||||
let suggest_deref_binop =
|
||||
|
@ -117,7 +117,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
actual: Ty<'tcx>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) {
|
||||
if let Some(mut err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
|
||||
if let Some(err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
@ -441,7 +441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
//
|
||||
// then that's equivalent to there existing a LUB.
|
||||
let cause = self.pattern_cause(ti, span);
|
||||
if let Some(mut err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
|
||||
if let Some(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
|
||||
err.emit_unless(
|
||||
ti.span
|
||||
.filter(|&s| {
|
||||
@ -1103,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// Type-check the tuple struct pattern against the expected type.
|
||||
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti);
|
||||
let had_err = if let Some(mut err) = diag {
|
||||
let had_err = if let Some(err) = diag {
|
||||
err.emit();
|
||||
true
|
||||
} else {
|
||||
@ -1329,9 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
});
|
||||
let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
|
||||
let pat_ty = Ty::new_tup(tcx, element_tys);
|
||||
if let Some(mut err) =
|
||||
self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info)
|
||||
{
|
||||
if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
|
||||
let reported = err.emit();
|
||||
// Walk subpatterns with an expected type of `err` in this case to silence
|
||||
// further errors being emitted when using the bindings. #50333
|
||||
@ -1469,8 +1467,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
match (inexistent_fields_err, unmentioned_err) {
|
||||
(Some(mut i), Some(mut u)) => {
|
||||
if let Some(mut e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
(Some(i), Some(u)) => {
|
||||
if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
// We don't want to show the nonexistent fields error when this was
|
||||
// `Foo { a, b }` when it should have been `Foo(a, b)`.
|
||||
i.delay_as_bug();
|
||||
@ -1481,19 +1479,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
u.emit();
|
||||
}
|
||||
}
|
||||
(None, Some(mut u)) => {
|
||||
if let Some(mut e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
(None, Some(u)) => {
|
||||
if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
u.delay_as_bug();
|
||||
e.emit();
|
||||
} else {
|
||||
u.emit();
|
||||
}
|
||||
}
|
||||
(Some(mut err), None) => {
|
||||
(Some(err), None) => {
|
||||
err.emit();
|
||||
}
|
||||
(None, None)
|
||||
if let Some(mut err) =
|
||||
if let Some(err) =
|
||||
self.error_tuple_variant_index_shorthand(variant, pat, fields) =>
|
||||
{
|
||||
err.emit();
|
||||
@ -1543,19 +1541,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi()));
|
||||
let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" };
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
pat.span,
|
||||
E0638,
|
||||
"`..` required with {descr} marked as non-exhaustive",
|
||||
);
|
||||
err.span_suggestion_verbose(
|
||||
)
|
||||
.span_suggestion_verbose_mv(
|
||||
sp_comma,
|
||||
"add `..` at the end of the field list to ignore all other fields",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
fn error_field_already_bound(
|
||||
@ -1571,8 +1569,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
"field `{}` bound multiple times in the pattern",
|
||||
ident
|
||||
)
|
||||
.span_label(span, format!("multiple uses of `{ident}` in pattern"))
|
||||
.span_label(other_field, format!("first use of `{ident}`"))
|
||||
.span_label_mv(span, format!("multiple uses of `{ident}` in pattern"))
|
||||
.span_label_mv(other_field, format!("first use of `{ident}`"))
|
||||
.emit()
|
||||
}
|
||||
|
||||
@ -2237,7 +2235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pluralize!(min_len),
|
||||
size,
|
||||
)
|
||||
.span_label(span, format!("expected {} element{}", size, pluralize!(size)))
|
||||
.span_label_mv(span, format!("expected {} element{}", size, pluralize!(size)))
|
||||
.emit()
|
||||
}
|
||||
|
||||
@ -2256,7 +2254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pluralize!(min_len),
|
||||
size,
|
||||
)
|
||||
.span_label(
|
||||
.span_label_mv(
|
||||
span,
|
||||
format!("pattern cannot match array of {} element{}", size, pluralize!(size),),
|
||||
)
|
||||
|
@ -332,15 +332,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if inside_union
|
||||
&& source.ty_adt_def().is_some_and(|adt| adt.is_manually_drop())
|
||||
{
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
self.dcx().struct_span_err(
|
||||
expr.span,
|
||||
"not automatically applying `DerefMut` on `ManuallyDrop` union field",
|
||||
);
|
||||
err.help(
|
||||
)
|
||||
.help_mv(
|
||||
"writing to this reference calls the destructor for the old value",
|
||||
);
|
||||
err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor");
|
||||
err.emit();
|
||||
)
|
||||
.help_mv("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
source = adjustment.target;
|
||||
|
@ -361,7 +361,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
||||
);
|
||||
}
|
||||
ty::ReError(_) => {
|
||||
err.delay_as_bug();
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
_ => {
|
||||
// Ugh. This is a painful case: the hidden region is not one
|
||||
@ -2356,15 +2356,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
},
|
||||
};
|
||||
|
||||
let mut err = self.tcx.dcx().struct_span_err_with_code(
|
||||
span,
|
||||
format!("{labeled_user_string} may not live long enough"),
|
||||
match sub.kind() {
|
||||
ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309),
|
||||
ty::ReStatic => error_code!(E0310),
|
||||
_ => error_code!(E0311),
|
||||
},
|
||||
);
|
||||
let mut err = self
|
||||
.tcx
|
||||
.dcx()
|
||||
.struct_span_err(span, format!("{labeled_user_string} may not live long enough"));
|
||||
err.code(match sub.kind() {
|
||||
ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309),
|
||||
ty::ReStatic => error_code!(E0310),
|
||||
_ => error_code!(E0311),
|
||||
});
|
||||
|
||||
'_explain: {
|
||||
let (description, span) = match sub.kind() {
|
||||
|
@ -60,7 +60,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
||||
|
||||
pub fn try_report(&self) -> Option<ErrorGuaranteed> {
|
||||
self.try_report_from_nll()
|
||||
.map(|mut diag| diag.emit())
|
||||
.map(|diag| diag.emit())
|
||||
.or_else(|| self.try_report_impl_not_conforming_to_trait())
|
||||
.or_else(|| self.try_report_anon_anon_conflict())
|
||||
.or_else(|| self.try_report_static_impl_trait())
|
||||
|
@ -281,7 +281,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
};
|
||||
if sub.is_error() || sup.is_error() {
|
||||
err.delay_as_bug();
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
err
|
||||
}
|
||||
@ -367,9 +367,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
&trace.cause.code().peel_derives()
|
||||
{
|
||||
let span = *span;
|
||||
let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
|
||||
err.span_note(span, "the lifetime requirement is introduced here");
|
||||
err
|
||||
self.report_concrete_failure(placeholder_origin, sub, sup)
|
||||
.span_note_mv(span, "the lifetime requirement is introduced here")
|
||||
} else {
|
||||
unreachable!(
|
||||
"control flow ensures we have a `BindingObligation` or `ExprBindingObligation` here..."
|
||||
|
@ -29,7 +29,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
|
||||
/// This is a callback from `rustc_errors` as it cannot access the implicit state
|
||||
/// in `rustc_middle` otherwise. It is used when diagnostic messages are
|
||||
/// emitted and stores them in the current query, if there is one.
|
||||
fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
|
||||
fn track_diagnostic(diagnostic: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
|
||||
tls::with_context_opt(|icx| {
|
||||
if let Some(icx) = icx {
|
||||
if let Some(diagnostics) = icx.diagnostics {
|
||||
|
@ -108,7 +108,7 @@ impl<'tcx> Queries<'tcx> {
|
||||
|
||||
pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
|
||||
self.parse.compute(|| {
|
||||
passes::parse(&self.compiler.sess).map_err(|mut parse_error| parse_error.emit())
|
||||
passes::parse(&self.compiler.sess).map_err(|parse_error| parse_error.emit())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -357,7 +357,6 @@ pub fn struct_lint_level(
|
||||
if let Level::Expect(_) = level {
|
||||
let name = lint.name_lower();
|
||||
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn: false });
|
||||
|
||||
decorate(&mut err);
|
||||
err.emit();
|
||||
return;
|
||||
|
@ -132,7 +132,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
||||
.tcx
|
||||
.dcx()
|
||||
.struct_span_err(self.span, "non-defining opaque type use in defining scope")
|
||||
.span_label(
|
||||
.span_label_mv(
|
||||
self.span,
|
||||
format!(
|
||||
"lifetime `{r}` is part of concrete type but not used in \
|
||||
|
@ -369,7 +369,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
if let Some((old_item_id, _)) = dtor_candidate {
|
||||
self.dcx()
|
||||
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
|
||||
.span_note(self.def_span(old_item_id), "other impl here")
|
||||
.span_note_mv(self.def_span(old_item_id), "other impl here")
|
||||
.delay_as_bug();
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ pub fn recursive_type_error(
|
||||
}
|
||||
s
|
||||
};
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
tcx.dcx(),
|
||||
err_span,
|
||||
E0072,
|
||||
@ -198,13 +198,13 @@ pub fn recursive_type_error(
|
||||
pluralize!(cycle_len),
|
||||
items_list,
|
||||
pluralize!("has", cycle_len),
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
)
|
||||
.multipart_suggestion_mv(
|
||||
"insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle",
|
||||
suggestion,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
fn find_item_ty_spans(
|
||||
|
@ -181,8 +181,7 @@ pub(crate) struct UnsafeOpInUnsafeFn {
|
||||
impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn {
|
||||
#[track_caller]
|
||||
fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) {
|
||||
let dcx = diag.dcx().expect("lint should not yet be emitted");
|
||||
let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());
|
||||
let desc = diag.dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());
|
||||
diag.arg("details", desc);
|
||||
diag.span_label(self.details.span, self.details.label());
|
||||
self.details.add_subdiagnostics(diag);
|
||||
|
@ -67,7 +67,7 @@ pub(crate) fn parse_token_trees<'a>(
|
||||
let (stream, res, unmatched_delims) =
|
||||
tokentrees::TokenTreesReader::parse_all_token_trees(string_reader);
|
||||
match res {
|
||||
Ok(_open_spacing) if unmatched_delims.is_empty() => Ok(stream),
|
||||
Ok(()) if unmatched_delims.is_empty() => Ok(stream),
|
||||
_ => {
|
||||
// Return error if there are unmatched delimiters or unclosed delimiters.
|
||||
// We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
|
||||
@ -249,9 +249,9 @@ impl<'a> StringReader<'a> {
|
||||
let lifetime_name = self.str_from(start);
|
||||
if starts_with_number {
|
||||
let span = self.mk_sp(start, self.pos);
|
||||
let mut diag = self.dcx().struct_err("lifetimes cannot start with a number");
|
||||
diag.span(span);
|
||||
diag.stash(span, StashKey::LifetimeIsChar);
|
||||
self.dcx().struct_err("lifetimes cannot start with a number")
|
||||
.span_mv(span)
|
||||
.stash(span, StashKey::LifetimeIsChar);
|
||||
}
|
||||
let ident = Symbol::intern(lifetime_name);
|
||||
token::Lifetime(ident)
|
||||
@ -395,51 +395,58 @@ impl<'a> StringReader<'a> {
|
||||
match kind {
|
||||
rustc_lexer::LiteralKind::Char { terminated } => {
|
||||
if !terminated {
|
||||
self.dcx().span_fatal_with_code(
|
||||
self.mk_sp(start, end),
|
||||
"unterminated character literal",
|
||||
error_code!(E0762),
|
||||
)
|
||||
self.dcx()
|
||||
.struct_span_fatal(self.mk_sp(start, end), "unterminated character literal")
|
||||
.code_mv(error_code!(E0762))
|
||||
.emit()
|
||||
}
|
||||
self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' '
|
||||
}
|
||||
rustc_lexer::LiteralKind::Byte { terminated } => {
|
||||
if !terminated {
|
||||
self.dcx().span_fatal_with_code(
|
||||
self.mk_sp(start + BytePos(1), end),
|
||||
"unterminated byte constant",
|
||||
error_code!(E0763),
|
||||
)
|
||||
self.dcx()
|
||||
.struct_span_fatal(
|
||||
self.mk_sp(start + BytePos(1), end),
|
||||
"unterminated byte constant",
|
||||
)
|
||||
.code_mv(error_code!(E0763))
|
||||
.emit()
|
||||
}
|
||||
self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
|
||||
}
|
||||
rustc_lexer::LiteralKind::Str { terminated } => {
|
||||
if !terminated {
|
||||
self.dcx().span_fatal_with_code(
|
||||
self.mk_sp(start, end),
|
||||
"unterminated double quote string",
|
||||
error_code!(E0765),
|
||||
)
|
||||
self.dcx()
|
||||
.struct_span_fatal(
|
||||
self.mk_sp(start, end),
|
||||
"unterminated double quote string",
|
||||
)
|
||||
.code_mv(error_code!(E0765))
|
||||
.emit()
|
||||
}
|
||||
self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " "
|
||||
}
|
||||
rustc_lexer::LiteralKind::ByteStr { terminated } => {
|
||||
if !terminated {
|
||||
self.dcx().span_fatal_with_code(
|
||||
self.mk_sp(start + BytePos(1), end),
|
||||
"unterminated double quote byte string",
|
||||
error_code!(E0766),
|
||||
)
|
||||
self.dcx()
|
||||
.struct_span_fatal(
|
||||
self.mk_sp(start + BytePos(1), end),
|
||||
"unterminated double quote byte string",
|
||||
)
|
||||
.code_mv(error_code!(E0766))
|
||||
.emit()
|
||||
}
|
||||
self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" "
|
||||
}
|
||||
rustc_lexer::LiteralKind::CStr { terminated } => {
|
||||
if !terminated {
|
||||
self.dcx().span_fatal_with_code(
|
||||
self.mk_sp(start + BytePos(1), end),
|
||||
"unterminated C string",
|
||||
error_code!(E0767),
|
||||
)
|
||||
self.dcx()
|
||||
.struct_span_fatal(
|
||||
self.mk_sp(start + BytePos(1), end),
|
||||
"unterminated C string",
|
||||
)
|
||||
.code_mv(error_code!(E0767))
|
||||
.emit()
|
||||
}
|
||||
self.cook_c_string(token::CStr, Mode::CStr, start, end, 2, 1) // c" "
|
||||
}
|
||||
@ -573,12 +580,9 @@ impl<'a> StringReader<'a> {
|
||||
possible_offset: Option<u32>,
|
||||
found_terminators: u32,
|
||||
) -> ! {
|
||||
let mut err = self.dcx().struct_span_fatal_with_code(
|
||||
self.mk_sp(start, start),
|
||||
"unterminated raw string",
|
||||
error_code!(E0748),
|
||||
);
|
||||
|
||||
let mut err =
|
||||
self.dcx().struct_span_fatal(self.mk_sp(start, start), "unterminated raw string");
|
||||
err.code(error_code!(E0748));
|
||||
err.span_label(self.mk_sp(start, start), "unterminated raw string");
|
||||
|
||||
if n_hashes > 0 {
|
||||
@ -609,11 +613,8 @@ impl<'a> StringReader<'a> {
|
||||
None => "unterminated block comment",
|
||||
};
|
||||
let last_bpos = self.pos;
|
||||
let mut err = self.dcx().struct_span_fatal_with_code(
|
||||
self.mk_sp(start, last_bpos),
|
||||
msg,
|
||||
error_code!(E0758),
|
||||
);
|
||||
let mut err = self.dcx().struct_span_fatal(self.mk_sp(start, last_bpos), msg);
|
||||
err.code(error_code!(E0758));
|
||||
let mut nested_block_comment_open_idxs = vec![];
|
||||
let mut last_nested_block_comment_idxs = None;
|
||||
let mut content_chars = self.str_from(start).char_indices().peekable();
|
||||
|
@ -277,9 +277,9 @@ impl<'a> TokenTreesReader<'a> {
|
||||
parser.bump();
|
||||
}
|
||||
if !diff_errs.is_empty() {
|
||||
errs.iter_mut().for_each(|err| {
|
||||
err.delay_as_bug();
|
||||
});
|
||||
for err in errs {
|
||||
err.cancel();
|
||||
}
|
||||
return diff_errs;
|
||||
}
|
||||
return errs;
|
||||
|
@ -245,9 +245,9 @@ pub fn parse_cfg_attr(
|
||||
crate::validate_attr::check_cfg_attr_bad_delim(parse_sess, dspan, delim);
|
||||
match parse_in(parse_sess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
|
||||
Ok(r) => return Some(r),
|
||||
Err(mut e) => {
|
||||
e.help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`"))
|
||||
.note(CFG_ATTR_NOTE_REF)
|
||||
Err(e) => {
|
||||
e.help_mv(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`"))
|
||||
.note_mv(CFG_ATTR_NOTE_REF)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -55,11 +55,10 @@ impl<'a> Parser<'a> {
|
||||
} else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
|
||||
if attr_style != ast::AttrStyle::Outer {
|
||||
let span = self.token.span;
|
||||
let mut err = self.dcx().struct_span_err_with_code(
|
||||
span,
|
||||
fluent::parse_inner_doc_comment_not_permitted,
|
||||
error_code!(E0753),
|
||||
);
|
||||
let mut err = self
|
||||
.dcx()
|
||||
.struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted);
|
||||
err.code(error_code!(E0753));
|
||||
if let Some(replacement_span) = self.annotate_following_item_if_applicable(
|
||||
&mut err,
|
||||
span,
|
||||
@ -200,23 +199,22 @@ impl<'a> Parser<'a> {
|
||||
if let InnerAttrPolicy::Forbidden(reason) = policy {
|
||||
let mut diag = match reason.as_ref().copied() {
|
||||
Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => {
|
||||
let mut diag = self.dcx().struct_span_err(
|
||||
attr_sp,
|
||||
fluent::parse_inner_attr_not_permitted_after_outer_doc_comment,
|
||||
);
|
||||
diag.span_label(attr_sp, fluent::parse_label_attr)
|
||||
.span_label(prev_doc_comment_span, fluent::parse_label_prev_doc_comment);
|
||||
diag
|
||||
self.dcx()
|
||||
.struct_span_err(
|
||||
attr_sp,
|
||||
fluent::parse_inner_attr_not_permitted_after_outer_doc_comment,
|
||||
)
|
||||
.span_label_mv(attr_sp, fluent::parse_label_attr)
|
||||
.span_label_mv(prev_doc_comment_span, fluent::parse_label_prev_doc_comment)
|
||||
}
|
||||
Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => {
|
||||
let mut diag = self.dcx().struct_span_err(
|
||||
Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => self
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
attr_sp,
|
||||
fluent::parse_inner_attr_not_permitted_after_outer_attr,
|
||||
);
|
||||
diag.span_label(attr_sp, fluent::parse_label_attr)
|
||||
.span_label(prev_outer_attr_sp, fluent::parse_label_prev_attr);
|
||||
diag
|
||||
}
|
||||
)
|
||||
.span_label_mv(attr_sp, fluent::parse_label_attr)
|
||||
.span_label_mv(prev_outer_attr_sp, fluent::parse_label_prev_attr),
|
||||
Some(InnerAttrForbiddenReason::InCodeBlock) | None => {
|
||||
self.dcx().struct_span_err(attr_sp, fluent::parse_inner_attr_not_permitted)
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ use rustc_ast::{
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{
|
||||
pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalError,
|
||||
PResult,
|
||||
pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
|
||||
ErrorGuaranteed, FatalError, PErr, PResult,
|
||||
};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
use rustc_span::source_map::Spanned;
|
||||
@ -896,7 +896,7 @@ impl<'a> Parser<'a> {
|
||||
let struct_expr = snapshot.parse_expr_struct(None, path, false);
|
||||
let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
|
||||
return Some(match (struct_expr, block_tail) {
|
||||
(Ok(expr), Err(mut err)) => {
|
||||
(Ok(expr), Err(err)) => {
|
||||
// We have encountered the following:
|
||||
// fn foo() -> Foo {
|
||||
// field: value,
|
||||
@ -1049,9 +1049,9 @@ impl<'a> Parser<'a> {
|
||||
&mut self,
|
||||
segment: &PathSegment,
|
||||
end: &[&TokenKind],
|
||||
) -> bool {
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if !self.may_recover() {
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
|
||||
// This function is intended to be invoked after parsing a path segment where there are two
|
||||
@ -1086,7 +1086,7 @@ impl<'a> Parser<'a> {
|
||||
parsed_angle_bracket_args,
|
||||
);
|
||||
if !parsed_angle_bracket_args {
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
|
||||
// Keep the span at the start so we can highlight the sequence of `>` characters to be
|
||||
@ -1124,7 +1124,7 @@ impl<'a> Parser<'a> {
|
||||
number_of_gt, number_of_shr,
|
||||
);
|
||||
if number_of_gt < 1 && number_of_shr < 1 {
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
|
||||
// Finally, double check that we have our end token as otherwise this is the
|
||||
@ -1139,10 +1139,9 @@ impl<'a> Parser<'a> {
|
||||
let span = lo.until(self.token.span);
|
||||
|
||||
let num_extra_brackets = number_of_gt + number_of_shr * 2;
|
||||
self.dcx().emit_err(UnmatchedAngleBrackets { span, num_extra_brackets });
|
||||
return true;
|
||||
return Some(self.dcx().emit_err(UnmatchedAngleBrackets { span, num_extra_brackets }));
|
||||
}
|
||||
false
|
||||
None
|
||||
}
|
||||
|
||||
/// Check if a method call with an intended turbofish has been written without surrounding
|
||||
@ -1212,29 +1211,32 @@ impl<'a> Parser<'a> {
|
||||
match x {
|
||||
Ok((_, _, false)) => {
|
||||
if self.eat(&token::Gt) {
|
||||
// We made sense of it. Improve the error message.
|
||||
e.span_suggestion_verbose(
|
||||
binop.span.shrink_to_lo(),
|
||||
fluent::parse_sugg_turbofish_syntax,
|
||||
"::",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
);
|
||||
match self.parse_expr() {
|
||||
Ok(_) => {
|
||||
// The subsequent expression is valid. Mark
|
||||
// `expr` as erroneous and emit `e` now, but
|
||||
// return `Ok` so parsing can continue.
|
||||
e.emit();
|
||||
*expr = self.mk_expr_err(expr.span.to(self.prev_token.span));
|
||||
return Ok(());
|
||||
}
|
||||
Err(err) => {
|
||||
*expr = self.mk_expr_err(expr.span);
|
||||
err.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((_, _, true)) => {}
|
||||
Err(err) => {
|
||||
err.cancel();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Err(e)
|
||||
@ -2041,17 +2043,12 @@ impl<'a> Parser<'a> {
|
||||
&mut self,
|
||||
delim: Delimiter,
|
||||
lo: Span,
|
||||
result: PResult<'a, P<Expr>>,
|
||||
err: PErr<'a>,
|
||||
) -> P<Expr> {
|
||||
match result {
|
||||
Ok(x) => x,
|
||||
Err(mut err) => {
|
||||
err.emit();
|
||||
// Recover from parse error, callers expect the closing delim to be consumed.
|
||||
self.consume_block(delim, ConsumeClosingDelim::Yes);
|
||||
self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err)
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
// Recover from parse error, callers expect the closing delim to be consumed.
|
||||
self.consume_block(delim, ConsumeClosingDelim::Yes);
|
||||
self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err)
|
||||
}
|
||||
|
||||
/// Eats tokens until we can be relatively sure we reached the end of the
|
||||
@ -2470,7 +2467,7 @@ impl<'a> Parser<'a> {
|
||||
return Ok(true); // Continue
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
args.push(arg);
|
||||
// We will emit a more generic error later.
|
||||
err.delay_as_bug();
|
||||
@ -2848,15 +2845,16 @@ impl<'a> Parser<'a> {
|
||||
let label = self.eat_label().expect("just checked if a label exists");
|
||||
self.bump(); // eat `:`
|
||||
let span = label.ident.span.to(self.prev_token.span);
|
||||
let mut err = self.dcx().struct_span_err(span, "block label not supported here");
|
||||
err.span_label(span, "not supported here");
|
||||
err.tool_only_span_suggestion(
|
||||
label.ident.span.until(self.token.span),
|
||||
"remove this block label",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
self.dcx()
|
||||
.struct_span_err(span, "block label not supported here")
|
||||
.span_label_mv(span, "not supported here")
|
||||
.tool_only_span_suggestion_mv(
|
||||
label.ident.span.until(self.token.span),
|
||||
"remove this block label",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
true
|
||||
}
|
||||
|
||||
@ -2946,7 +2944,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
pub fn recover_diff_marker(&mut self) {
|
||||
if let Err(mut err) = self.err_diff_marker() {
|
||||
if let Err(err) = self.err_diff_marker() {
|
||||
err.emit();
|
||||
FatalError.raise();
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ impl<'a> Parser<'a> {
|
||||
fn parse_expr_catch_underscore(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
|
||||
match self.parse_expr_res(restrictions, None) {
|
||||
Ok(expr) => Ok(expr),
|
||||
Err(mut err) => match self.token.ident() {
|
||||
Err(err) => match self.token.ident() {
|
||||
Some((Ident { name: kw::Underscore, .. }, false))
|
||||
if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) =>
|
||||
{
|
||||
@ -1272,15 +1272,13 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
let open_paren = self.token.span;
|
||||
|
||||
let mut seq = self
|
||||
let seq = self
|
||||
.parse_expr_paren_seq()
|
||||
.map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
|
||||
if let Some(expr) =
|
||||
self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
|
||||
{
|
||||
return expr;
|
||||
match self.maybe_recover_struct_lit_bad_delims(lo, open_paren, seq, snapshot) {
|
||||
Ok(expr) => expr,
|
||||
Err(err) => self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err),
|
||||
}
|
||||
self.recover_seq_parse_error(Delimiter::Parenthesis, lo, seq)
|
||||
}
|
||||
|
||||
/// If we encounter a parser state that looks like the user has written a `struct` literal with
|
||||
@ -1290,14 +1288,11 @@ impl<'a> Parser<'a> {
|
||||
&mut self,
|
||||
lo: Span,
|
||||
open_paren: Span,
|
||||
seq: &mut PResult<'a, P<Expr>>,
|
||||
seq: PResult<'a, P<Expr>>,
|
||||
snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
|
||||
) -> Option<P<Expr>> {
|
||||
if !self.may_recover() {
|
||||
return None;
|
||||
}
|
||||
match (seq.as_mut(), snapshot) {
|
||||
(Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
match (self.may_recover(), seq, snapshot) {
|
||||
(true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
|
||||
snapshot.bump(); // `(`
|
||||
match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) {
|
||||
Ok((fields, ..))
|
||||
@ -1315,11 +1310,13 @@ impl<'a> Parser<'a> {
|
||||
if !fields.is_empty() &&
|
||||
// `token.kind` should not be compared here.
|
||||
// This is because the `snapshot.token.kind` is treated as the same as
|
||||
// that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different.
|
||||
// that of the open delim in `TokenTreesReader::parse_token_tree`, even
|
||||
// if they are different.
|
||||
self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")")
|
||||
{
|
||||
let mut replacement_err =
|
||||
self.dcx().create_err(errors::ParenthesesWithStructFields {
|
||||
err.cancel();
|
||||
self.dcx()
|
||||
.create_err(errors::ParenthesesWithStructFields {
|
||||
span,
|
||||
r#type: path,
|
||||
braces_for_struct: errors::BracesForStructLiteral {
|
||||
@ -1332,23 +1329,22 @@ impl<'a> Parser<'a> {
|
||||
.map(|field| field.span.until(field.expr.span))
|
||||
.collect(),
|
||||
},
|
||||
});
|
||||
replacement_err.emit();
|
||||
|
||||
let old_err = mem::replace(err, replacement_err);
|
||||
old_err.cancel();
|
||||
})
|
||||
.emit();
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
return Some(self.mk_expr_err(span));
|
||||
Ok(self.mk_expr_err(span))
|
||||
}
|
||||
Ok(_) => Err(err),
|
||||
Err(err2) => {
|
||||
err2.cancel();
|
||||
Err(err)
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(err) => err.cancel(),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
(_, seq, _) => seq,
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Parse an indexing expression `expr[...]`.
|
||||
@ -1552,7 +1548,7 @@ impl<'a> Parser<'a> {
|
||||
) {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, Err(err)));
|
||||
return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err));
|
||||
}
|
||||
};
|
||||
let kind = if es.len() == 1 && !trailing_comma {
|
||||
@ -1756,9 +1752,8 @@ impl<'a> Parser<'a> {
|
||||
mk_lit_char: impl FnOnce(Symbol, Span) -> L,
|
||||
err: impl FnOnce(&Self) -> DiagnosticBuilder<'a>,
|
||||
) -> L {
|
||||
if let Some(mut diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
if let Some(diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) {
|
||||
diag.span_suggestion_verbose_mv(
|
||||
lifetime.span.shrink_to_hi(),
|
||||
"add `'` to close the char literal",
|
||||
"'",
|
||||
@ -1767,7 +1762,7 @@ impl<'a> Parser<'a> {
|
||||
.emit();
|
||||
} else {
|
||||
err(self)
|
||||
.span_suggestion_verbose(
|
||||
.span_suggestion_verbose_mv(
|
||||
lifetime.span.shrink_to_hi(),
|
||||
"add `'` to close the char literal",
|
||||
"'",
|
||||
@ -2903,7 +2898,7 @@ impl<'a> Parser<'a> {
|
||||
while self.token != token::CloseDelim(Delimiter::Brace) {
|
||||
match self.parse_arm() {
|
||||
Ok(arm) => arms.push(arm),
|
||||
Err(mut e) => {
|
||||
Err(e) => {
|
||||
// Recover by skipping to the end of the block.
|
||||
e.emit();
|
||||
self.recover_stmt();
|
||||
@ -3437,7 +3432,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
match self.parse_expr() {
|
||||
Ok(e) => base = ast::StructRest::Base(e),
|
||||
Err(mut e) if recover => {
|
||||
Err(e) if recover => {
|
||||
e.emit();
|
||||
self.recover_stmt();
|
||||
}
|
||||
|
@ -77,7 +77,6 @@ impl<'a> Parser<'a> {
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
@ -141,17 +140,18 @@ impl<'a> Parser<'a> {
|
||||
// Parse optional const generics default value.
|
||||
let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None };
|
||||
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
mistyped_const_ident.span,
|
||||
format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
|
||||
);
|
||||
err.span_suggestion_verbose(
|
||||
mistyped_const_ident.span,
|
||||
"use the `const` keyword",
|
||||
kw::Const.as_str(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
self.dcx()
|
||||
.struct_span_err(
|
||||
mistyped_const_ident.span,
|
||||
format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
|
||||
)
|
||||
.span_suggestion_verbose_mv(
|
||||
mistyped_const_ident.span,
|
||||
"use the `const` keyword",
|
||||
kw::Const.as_str(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
|
||||
Ok(GenericParam {
|
||||
ident,
|
||||
|
@ -739,11 +739,14 @@ impl<'a> Parser<'a> {
|
||||
break;
|
||||
}
|
||||
Ok(Some(item)) => items.extend(item),
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
|
||||
err.span_label(open_brace_span, "while parsing this item list starting here")
|
||||
.span_label(self.prev_token.span, "the item list ends here")
|
||||
.emit();
|
||||
err.span_label_mv(
|
||||
open_brace_span,
|
||||
"while parsing this item list starting here",
|
||||
)
|
||||
.span_label_mv(self.prev_token.span, "the item list ends here")
|
||||
.emit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -762,8 +765,8 @@ impl<'a> Parser<'a> {
|
||||
E0584,
|
||||
"found a documentation comment that doesn't document anything",
|
||||
)
|
||||
.span_label(self.token.span, "this doc comment doesn't document anything")
|
||||
.help(
|
||||
.span_label_mv(self.token.span, "this doc comment doesn't document anything")
|
||||
.help_mv(
|
||||
"doc comments must come before what they document, if a comment was \
|
||||
intended use `//`",
|
||||
)
|
||||
@ -1106,8 +1109,7 @@ impl<'a> Parser<'a> {
|
||||
&& self.token.is_keyword(kw::Unsafe)
|
||||
&& self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace))
|
||||
{
|
||||
let mut err = self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err();
|
||||
err.emit();
|
||||
self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err().emit();
|
||||
unsafety = Unsafe::Yes(self.token.span);
|
||||
self.eat_keyword(kw::Unsafe);
|
||||
}
|
||||
@ -1198,7 +1200,7 @@ impl<'a> Parser<'a> {
|
||||
defaultness: Defaultness,
|
||||
) -> PResult<'a, ItemInfo> {
|
||||
let impl_span = self.token.span;
|
||||
let mut err = self.expected_ident_found_err();
|
||||
let err = self.expected_ident_found_err();
|
||||
|
||||
// Only try to recover if this is implementing a trait for a type
|
||||
let mut impl_info = match self.parse_item_impl(attrs, defaultness) {
|
||||
@ -1216,7 +1218,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let before_trait = trai.path.span.shrink_to_lo();
|
||||
let const_up_to_impl = const_span.with_hi(impl_span.lo());
|
||||
err.multipart_suggestion(
|
||||
err.multipart_suggestion_mv(
|
||||
"you might have meant to write a const trait impl",
|
||||
vec![(const_up_to_impl, "".to_owned()), (before_trait, "const ".to_owned())],
|
||||
Applicability::MaybeIncorrect,
|
||||
@ -1454,8 +1456,8 @@ impl<'a> Parser<'a> {
|
||||
let ident = this.parse_field_ident("enum", vlo)?;
|
||||
|
||||
if this.token == token::Not {
|
||||
if let Err(mut err) = this.unexpected::<()>() {
|
||||
err.note(fluent::parse_macro_expands_to_enum_variant).emit();
|
||||
if let Err(err) = this.unexpected::<()>() {
|
||||
err.note_mv(fluent::parse_macro_expands_to_enum_variant).emit();
|
||||
}
|
||||
|
||||
this.bump();
|
||||
@ -1791,37 +1793,36 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
_ => {
|
||||
let sp = self.prev_token.span.shrink_to_hi();
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
sp,
|
||||
format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)),
|
||||
);
|
||||
let msg =
|
||||
format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token));
|
||||
|
||||
// Try to recover extra trailing angle brackets
|
||||
let mut recovered = false;
|
||||
if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind {
|
||||
if let Some(last_segment) = segments.last() {
|
||||
recovered = self.check_trailing_angle_brackets(
|
||||
let guar = self.check_trailing_angle_brackets(
|
||||
last_segment,
|
||||
&[&token::Comma, &token::CloseDelim(Delimiter::Brace)],
|
||||
);
|
||||
if recovered {
|
||||
if let Some(_guar) = guar {
|
||||
// Handle a case like `Vec<u8>>,` where we can continue parsing fields
|
||||
// after the comma
|
||||
self.eat(&token::Comma);
|
||||
// `check_trailing_angle_brackets` already emitted a nicer error
|
||||
// NOTE(eddyb) this was `.cancel()`, but `err`
|
||||
// gets returned, so we can't fully defuse it.
|
||||
err.delay_as_bug();
|
||||
|
||||
// `check_trailing_angle_brackets` already emitted a nicer error, as
|
||||
// proven by the presence of `_guar`. We can continue parsing.
|
||||
return Ok(a_var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut err = self.dcx().struct_span_err(sp, msg);
|
||||
|
||||
if self.token.is_ident()
|
||||
|| (self.token.kind == TokenKind::Pound
|
||||
&& (self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Bracket))))
|
||||
{
|
||||
// This is likely another field, TokenKind::Pound is used for `#[..]` attribute for next field,
|
||||
// emit the diagnostic and keep going
|
||||
// This is likely another field, TokenKind::Pound is used for `#[..]`
|
||||
// attribute for next field. Emit the diagnostic and continue parsing.
|
||||
err.span_suggestion(
|
||||
sp,
|
||||
"try adding a comma",
|
||||
@ -1829,14 +1830,6 @@ impl<'a> Parser<'a> {
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
recovered = true;
|
||||
}
|
||||
|
||||
if recovered {
|
||||
// Make sure an error was emitted (either by recovering an angle bracket,
|
||||
// or by finding an identifier as the next token), since we're
|
||||
// going to continue parsing
|
||||
assert!(self.dcx().has_errors().is_some());
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
@ -1846,7 +1839,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
|
||||
if let Err(mut err) = self.expect(&token::Colon) {
|
||||
if let Err(err) = self.expect(&token::Colon) {
|
||||
let sm = self.sess.source_map();
|
||||
let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start());
|
||||
let semi_typo = self.token.kind == token::Semi
|
||||
@ -1862,7 +1855,7 @@ impl<'a> Parser<'a> {
|
||||
if eq_typo || semi_typo {
|
||||
self.bump();
|
||||
// Gracefully handle small typos.
|
||||
err.span_suggestion_short(
|
||||
err.span_suggestion_short_mv(
|
||||
self.prev_token.span,
|
||||
"field names and their types are separated with `:`",
|
||||
":",
|
||||
@ -1938,15 +1931,14 @@ impl<'a> Parser<'a> {
|
||||
Case::Insensitive,
|
||||
) {
|
||||
Ok(_) => {
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
self.dcx().struct_span_err(
|
||||
lo.to(self.prev_token.span),
|
||||
format!("functions are not allowed in {adt_ty} definitions"),
|
||||
);
|
||||
err.help(
|
||||
)
|
||||
.help_mv(
|
||||
"unlike in C++, Java, and C#, functions are declared in `impl` blocks",
|
||||
);
|
||||
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
|
||||
err
|
||||
)
|
||||
.help_mv("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
|
||||
}
|
||||
Err(err) => {
|
||||
err.cancel();
|
||||
@ -1956,14 +1948,13 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
} else if self.eat_keyword(kw::Struct) {
|
||||
match self.parse_item_struct() {
|
||||
Ok((ident, _)) => {
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
Ok((ident, _)) => self
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
lo.with_hi(ident.span.hi()),
|
||||
format!("structs are not allowed in {adt_ty} definitions"),
|
||||
);
|
||||
err.help("consider creating a new `struct` definition instead of nesting");
|
||||
err
|
||||
}
|
||||
)
|
||||
.help_mv("consider creating a new `struct` definition instead of nesting"),
|
||||
Err(err) => {
|
||||
err.cancel();
|
||||
self.restore_snapshot(snapshot);
|
||||
@ -2598,7 +2589,7 @@ impl<'a> Parser<'a> {
|
||||
let (mut params, _) = self.parse_paren_comma_seq(|p| {
|
||||
p.recover_diff_marker();
|
||||
let snapshot = p.create_snapshot_for_diagnostic();
|
||||
let param = p.parse_param_general(req_name, first_param).or_else(|mut e| {
|
||||
let param = p.parse_param_general(req_name, first_param).or_else(|e| {
|
||||
e.emit();
|
||||
let lo = p.prev_token.span;
|
||||
p.restore_snapshot(snapshot);
|
||||
|
@ -499,7 +499,7 @@ impl<'a> Parser<'a> {
|
||||
let (ident, is_raw) = self.ident_or_err(recover)?;
|
||||
|
||||
if !is_raw && ident.is_reserved() {
|
||||
let mut err = self.expected_ident_found_err();
|
||||
let err = self.expected_ident_found_err();
|
||||
if recover {
|
||||
err.emit();
|
||||
} else {
|
||||
@ -847,7 +847,7 @@ impl<'a> Parser<'a> {
|
||||
pprust::token_to_string(&self.prev_token)
|
||||
);
|
||||
expect_err
|
||||
.span_suggestion_verbose(
|
||||
.span_suggestion_verbose_mv(
|
||||
self.prev_token.span.shrink_to_hi().until(self.token.span),
|
||||
msg,
|
||||
" @ ",
|
||||
@ -863,7 +863,7 @@ impl<'a> Parser<'a> {
|
||||
// Parsed successfully, therefore most probably the code only
|
||||
// misses a separator.
|
||||
expect_err
|
||||
.span_suggestion_short(
|
||||
.span_suggestion_short_mv(
|
||||
sp,
|
||||
format!("missing `{token_str}`"),
|
||||
token_str,
|
||||
|
@ -144,7 +144,7 @@ impl<'a> Parser<'a> {
|
||||
// Parse the first pattern (`p_0`).
|
||||
let mut first_pat = match self.parse_pat_no_top_alt(expected, syntax_loc) {
|
||||
Ok(pat) => pat,
|
||||
Err(mut err)
|
||||
Err(err)
|
||||
if self.token.is_reserved_ident()
|
||||
&& !self.token.is_keyword(kw::In)
|
||||
&& !self.token.is_keyword(kw::If) =>
|
||||
@ -242,7 +242,7 @@ impl<'a> Parser<'a> {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
|
||||
};
|
||||
|
||||
let mut err = self.dcx().create_err(match syntax_loc {
|
||||
let err = self.dcx().create_err(match syntax_loc {
|
||||
PatternLocation::LetBinding => {
|
||||
TopLevelOrPatternNotAllowed::LetBinding { span, sub }
|
||||
}
|
||||
@ -252,8 +252,9 @@ impl<'a> Parser<'a> {
|
||||
});
|
||||
if trailing_vert {
|
||||
err.delay_as_bug();
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
Ok((pat, colon))
|
||||
@ -460,9 +461,10 @@ impl<'a> Parser<'a> {
|
||||
super::token_descr(&self_.token)
|
||||
);
|
||||
|
||||
let mut err = self_.dcx().struct_span_err(self_.token.span, msg);
|
||||
err.span_label(self_.token.span, format!("expected {expected}"));
|
||||
err
|
||||
self_
|
||||
.dcx()
|
||||
.struct_span_err(self_.token.span, msg)
|
||||
.span_label_mv(self_.token.span, format!("expected {expected}"))
|
||||
});
|
||||
PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
|
||||
} else {
|
||||
@ -1028,7 +1030,7 @@ impl<'a> Parser<'a> {
|
||||
let attrs = match self.parse_outer_attributes() {
|
||||
Ok(attrs) => attrs,
|
||||
Err(err) => {
|
||||
if let Some(mut delayed) = delayed_err {
|
||||
if let Some(delayed) = delayed_err {
|
||||
delayed.emit();
|
||||
}
|
||||
return Err(err);
|
||||
@ -1040,7 +1042,7 @@ impl<'a> Parser<'a> {
|
||||
if !ate_comma {
|
||||
let mut err =
|
||||
self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span });
|
||||
if let Some(mut delayed) = delayed_err {
|
||||
if let Some(delayed) = delayed_err {
|
||||
delayed.emit();
|
||||
}
|
||||
self.recover_misplaced_pattern_modifiers(&fields, &mut err);
|
||||
@ -1113,14 +1115,14 @@ impl<'a> Parser<'a> {
|
||||
// This way we avoid "pattern missing fields" errors afterwards.
|
||||
// We delay this error until the end in order to have a span for a
|
||||
// suggested fix.
|
||||
if let Some(mut delayed_err) = delayed_err {
|
||||
if let Some(delayed_err) = delayed_err {
|
||||
delayed_err.emit();
|
||||
return Err(err);
|
||||
} else {
|
||||
delayed_err = Some(err);
|
||||
}
|
||||
} else {
|
||||
if let Some(mut err) = delayed_err {
|
||||
if let Some(err) = delayed_err {
|
||||
err.emit();
|
||||
}
|
||||
return Err(err);
|
||||
@ -1132,7 +1134,7 @@ impl<'a> Parser<'a> {
|
||||
let field = match this.parse_pat_field(lo, attrs) {
|
||||
Ok(field) => Ok(field),
|
||||
Err(err) => {
|
||||
if let Some(mut delayed_err) = delayed_err.take() {
|
||||
if let Some(delayed_err) = delayed_err.take() {
|
||||
delayed_err.emit();
|
||||
}
|
||||
return Err(err);
|
||||
|
@ -128,7 +128,7 @@ impl<'a> Parser<'a> {
|
||||
self.prev_token.span,
|
||||
"found single colon before projection in qualified path",
|
||||
)
|
||||
.span_suggestion(
|
||||
.span_suggestion_mv(
|
||||
self.prev_token.span,
|
||||
"use double colon",
|
||||
"::",
|
||||
@ -493,7 +493,7 @@ impl<'a> Parser<'a> {
|
||||
self.angle_bracket_nesting -= 1;
|
||||
Ok(args)
|
||||
}
|
||||
Err(mut e) if self.angle_bracket_nesting > 10 => {
|
||||
Err(e) if self.angle_bracket_nesting > 10 => {
|
||||
self.angle_bracket_nesting -= 1;
|
||||
// When encountering severely malformed code where there are several levels of
|
||||
// nested unclosed angle args (`f::<f::<f::<f::<...`), we avoid severe O(n^2)
|
||||
|
@ -32,7 +32,7 @@ impl<'a> Parser<'a> {
|
||||
/// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
|
||||
// Public for rustfmt usage.
|
||||
pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
|
||||
Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|mut e| {
|
||||
Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| {
|
||||
e.emit();
|
||||
self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
|
||||
None
|
||||
@ -663,7 +663,7 @@ impl<'a> Parser<'a> {
|
||||
match expect_result {
|
||||
// Recover from parser, skip type error to avoid extra errors.
|
||||
Ok(true) => true,
|
||||
Err(mut e) => {
|
||||
Err(e) => {
|
||||
if self.recover_colon_as_semi() {
|
||||
// recover_colon_as_semi has already emitted a nicer error.
|
||||
e.delay_as_bug();
|
||||
@ -716,7 +716,7 @@ impl<'a> Parser<'a> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Err(mut e) =
|
||||
if let Err(e) =
|
||||
self.check_mistyped_turbofish_with_multiple_type_params(e, expr)
|
||||
{
|
||||
if recover.no() {
|
||||
|
@ -300,7 +300,7 @@ impl<'a> Parser<'a> {
|
||||
let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
|
||||
let kind =
|
||||
self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?;
|
||||
let mut err = self.dcx().create_err(errors::TransposeDynOrImpl {
|
||||
let err = self.dcx().create_err(errors::TransposeDynOrImpl {
|
||||
span: kw.span,
|
||||
kw: kw.name.as_str(),
|
||||
sugg: errors::TransposeDynOrImplSugg {
|
||||
@ -487,7 +487,7 @@ impl<'a> Parser<'a> {
|
||||
fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
|
||||
let elt_ty = match self.parse_ty() {
|
||||
Ok(ty) => ty,
|
||||
Err(mut err)
|
||||
Err(err)
|
||||
if self.look_ahead(1, |t| t.kind == token::CloseDelim(Delimiter::Bracket))
|
||||
| self.look_ahead(1, |t| t.kind == token::Semi) =>
|
||||
{
|
||||
@ -1109,20 +1109,19 @@ impl<'a> Parser<'a> {
|
||||
lifetime_defs.append(&mut generic_params);
|
||||
|
||||
let generic_args_span = generic_args.span();
|
||||
let mut err = self
|
||||
.dcx()
|
||||
.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters");
|
||||
let snippet = format!(
|
||||
"for<{}> ",
|
||||
lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
|
||||
);
|
||||
let before_fn_path = fn_path.span.shrink_to_lo();
|
||||
err.multipart_suggestion(
|
||||
"consider using a higher-ranked trait bound instead",
|
||||
vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
self.dcx()
|
||||
.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
|
||||
.multipart_suggestion_mv(
|
||||
"consider using a higher-ranked trait bound instead",
|
||||
vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ pub fn check_attr(sess: &ParseSess, attr: &Attribute) {
|
||||
_ if let AttrArgs::Eq(..) = attr.get_normal_item().args => {
|
||||
// All key-value attributes are restricted to meta-item syntax.
|
||||
parse_meta(sess, attr)
|
||||
.map_err(|mut err| {
|
||||
.map_err(|err| {
|
||||
err.emit();
|
||||
})
|
||||
.ok();
|
||||
@ -139,7 +139,7 @@ pub fn check_builtin_attribute(
|
||||
) {
|
||||
match parse_meta(sess, attr) {
|
||||
Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template),
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
@ -208,7 +208,7 @@ fn emit_malformed_attribute(
|
||||
} else {
|
||||
sess.dcx
|
||||
.struct_span_err(span, error_msg)
|
||||
.span_suggestions(
|
||||
.span_suggestions_mv(
|
||||
span,
|
||||
if suggestions.len() == 1 {
|
||||
"must be of the form"
|
||||
|
@ -48,7 +48,7 @@ impl DebuggerVisualizerCollector<'_> {
|
||||
let file =
|
||||
match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) {
|
||||
Ok(file) => file,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return;
|
||||
}
|
||||
|
@ -1040,7 +1040,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> {
|
||||
// This error is redundant, we will have already emitted a
|
||||
// suggestion to use the label when `segment` wasn't found
|
||||
// (hence the `Res::Err` check).
|
||||
diag.delay_as_bug();
|
||||
diag.downgrade_to_delayed_bug();
|
||||
}
|
||||
_ => {
|
||||
diag.span_suggestion(
|
||||
|
@ -124,7 +124,7 @@ fn handle_cycle_error<Q, Qcx>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
cycle_error: &CycleError,
|
||||
mut error: DiagnosticBuilder<'_>,
|
||||
error: DiagnosticBuilder<'_>,
|
||||
) -> Q::Value
|
||||
where
|
||||
Q: QueryConfig<Qcx>,
|
||||
|
@ -818,7 +818,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
self.r
|
||||
.dcx()
|
||||
.struct_span_err(item.span, "`extern crate self;` requires renaming")
|
||||
.span_suggestion(
|
||||
.span_suggestion_mv(
|
||||
item.span,
|
||||
"rename the `self` crate to be able to import it",
|
||||
"extern crate self as name;",
|
||||
@ -999,7 +999,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
let msg = format!("`{name}` is already in scope");
|
||||
let note =
|
||||
"macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
|
||||
self.r.dcx().struct_span_err(span, msg).note(note).emit();
|
||||
self.r.dcx().struct_span_err(span, msg).note_mv(note).emit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1110,10 +1110,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||
let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`";
|
||||
let mut err = self.r.dcx().struct_span_warn(attr.span, msg);
|
||||
if let ast::AttrStyle::Inner = attr.style {
|
||||
err.help("try an outer attribute: `#[macro_use]`").emit();
|
||||
} else {
|
||||
err.emit();
|
||||
err.help("try an outer attribute: `#[macro_use]`");
|
||||
}
|
||||
err.emit();
|
||||
} else if !attr.has_name(sym::macro_use) {
|
||||
continue;
|
||||
}
|
||||
|
@ -944,16 +944,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
trait_item_span,
|
||||
trait_path,
|
||||
} => {
|
||||
let mut err = self.dcx().struct_span_err_with_code(
|
||||
self.dcx().struct_span_err(
|
||||
span,
|
||||
format!(
|
||||
"item `{name}` is an associated {kind}, which doesn't match its trait `{trait_path}`",
|
||||
),
|
||||
code,
|
||||
);
|
||||
err.span_label(span, "does not match trait");
|
||||
err.span_label(trait_item_span, "item in trait");
|
||||
err
|
||||
)
|
||||
.code_mv(code)
|
||||
.span_label_mv(span, "does not match trait")
|
||||
.span_label_mv(trait_item_span, "item in trait")
|
||||
}
|
||||
ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
|
||||
.dcx()
|
||||
|
@ -1233,7 +1233,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
);
|
||||
} else {
|
||||
if ns == TypeNS {
|
||||
let mut err = if crate_private_reexport {
|
||||
let err = if crate_private_reexport {
|
||||
self.dcx().create_err(CannotBeReexportedCratePublicNS {
|
||||
span: import.span,
|
||||
ident,
|
||||
|
@ -2600,7 +2600,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||
E0637,
|
||||
"`'_` cannot be used here"
|
||||
)
|
||||
.span_label(param.ident.span, "`'_` is a reserved lifetime name")
|
||||
.span_label_mv(param.ident.span, "`'_` is a reserved lifetime name")
|
||||
.emit();
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
@ -2615,7 +2615,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||
"invalid lifetime parameter name: `{}`",
|
||||
param.ident,
|
||||
)
|
||||
.span_label(param.ident.span, "'static is a reserved lifetime name")
|
||||
.span_label_mv(param.ident.span, "'static is a reserved lifetime name")
|
||||
.emit();
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
|
@ -429,8 +429,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||
let base_error = self.make_base_error(path, span, source, res);
|
||||
|
||||
let code = source.error_code(res.is_some());
|
||||
let mut err =
|
||||
self.r.dcx().struct_span_err_with_code(base_error.span, base_error.msg.clone(), code);
|
||||
let mut err = self.r.dcx().struct_span_err(base_error.span, base_error.msg.clone());
|
||||
err.code(code);
|
||||
|
||||
self.suggest_at_operator_in_slice_pat_with_range(&mut err, path);
|
||||
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
|
||||
@ -2603,25 +2603,23 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||
) {
|
||||
debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime);
|
||||
let mut err = if let Some(outer) = outer_lifetime_ref {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.r.dcx(),
|
||||
lifetime_ref.ident.span,
|
||||
E0401,
|
||||
"can't use generic parameters from outer item",
|
||||
);
|
||||
err.span_label(lifetime_ref.ident.span, "use of generic parameter from outer item");
|
||||
err.span_label(outer.span, "lifetime parameter from outer item");
|
||||
err
|
||||
)
|
||||
.span_label_mv(lifetime_ref.ident.span, "use of generic parameter from outer item")
|
||||
.span_label_mv(outer.span, "lifetime parameter from outer item")
|
||||
} else {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.r.dcx(),
|
||||
lifetime_ref.ident.span,
|
||||
E0261,
|
||||
"use of undeclared lifetime name `{}`",
|
||||
lifetime_ref.ident
|
||||
);
|
||||
err.span_label(lifetime_ref.ident.span, "undeclared lifetime");
|
||||
err
|
||||
)
|
||||
.span_label_mv(lifetime_ref.ident.span, "undeclared lifetime")
|
||||
};
|
||||
self.suggest_introducing_lifetime(
|
||||
&mut err,
|
||||
@ -3284,16 +3282,16 @@ fn mk_where_bound_predicate(
|
||||
|
||||
/// Report lifetime/lifetime shadowing as an error.
|
||||
pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
sess.dcx(),
|
||||
shadower.span,
|
||||
E0496,
|
||||
"lifetime name `{}` shadows a lifetime name that is already in scope",
|
||||
orig.name,
|
||||
);
|
||||
err.span_label(orig.span, "first declared here");
|
||||
err.span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name));
|
||||
err.emit();
|
||||
)
|
||||
.span_label_mv(orig.span, "first declared here")
|
||||
.span_label_mv(shadower.span, format!("lifetime `{}` already in scope", orig.name))
|
||||
.emit();
|
||||
}
|
||||
|
||||
struct LifetimeFinder<'ast> {
|
||||
@ -3319,11 +3317,12 @@ impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> {
|
||||
pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) {
|
||||
let name = shadower.name;
|
||||
let shadower = shadower.span;
|
||||
let mut err = sess.dcx().struct_span_warn(
|
||||
shadower,
|
||||
format!("label name `{name}` shadows a label name that is already in scope"),
|
||||
);
|
||||
err.span_label(orig, "first declared here");
|
||||
err.span_label(shadower, format!("label `{name}` already in scope"));
|
||||
err.emit();
|
||||
sess.dcx()
|
||||
.struct_span_warn(
|
||||
shadower,
|
||||
format!("label name `{name}` shadows a label name that is already in scope"),
|
||||
)
|
||||
.span_label_mv(orig, "first declared here")
|
||||
.span_label_mv(shadower, format!("label `{name}` already in scope"))
|
||||
.emit();
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
|
||||
let msg = format!("{} `{}` was already registered", "tool", ident);
|
||||
tcx.dcx()
|
||||
.struct_span_err(ident.span, msg)
|
||||
.span_label(old_ident.span, "already registered here")
|
||||
.span_label_mv(old_ident.span, "already registered here")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
@ -137,7 +137,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
|
||||
let span = nested_meta.span();
|
||||
tcx.dcx()
|
||||
.struct_span_err(span, msg)
|
||||
.span_label(span, "not an identifier")
|
||||
.span_label_mv(span, "not an identifier")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
@ -576,10 +576,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
|
||||
}
|
||||
|
||||
let mut err = self.dcx().create_err(err);
|
||||
err.span_label(path.span, format!("not {article} {expected}"));
|
||||
|
||||
err.emit();
|
||||
self.dcx()
|
||||
.create_err(err)
|
||||
.span_label_mv(path.span, format!("not {article} {expected}"))
|
||||
.emit();
|
||||
|
||||
return Ok((self.dummy_ext(kind), Res::Err));
|
||||
}
|
||||
@ -830,7 +830,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
expected,
|
||||
ident,
|
||||
});
|
||||
|
||||
self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident, krate);
|
||||
err.emit();
|
||||
}
|
||||
@ -955,7 +954,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
E0773,
|
||||
"attempted to define built-in macro more than once"
|
||||
)
|
||||
.span_note(span, "previously defined here")
|
||||
.span_note_mv(span, "previously defined here")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,9 @@ pub struct FeatureGateError {
|
||||
impl<'a> IntoDiagnostic<'a> for FeatureGateError {
|
||||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, self.explain);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0658));
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, self.explain)
|
||||
.span_mv(self.span)
|
||||
.code_mv(error_code!(E0658))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1491,7 +1491,10 @@ impl EarlyDiagCtxt {
|
||||
jobserver::initialize_checked(|err| {
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
self.dcx.struct_warn(err).note("the build environment is likely misconfigured").emit()
|
||||
self.dcx
|
||||
.struct_warn(err)
|
||||
.note_mv("the build environment is likely misconfigured")
|
||||
.emit()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TestOutput {
|
||||
let TestOutput { span, kind, content } = self;
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, format!("{kind}({content})"));
|
||||
diag.span(span);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, format!("{kind}({content})")).span_mv(span)
|
||||
}
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user