Make DiagnosticBuilder::emit
consuming.
This works for most of its call sites. This is nice, because `emit` very much makes sense as a consuming operation -- indeed, `DiagnosticBuilderState` exists to ensure no diagnostic is emitted twice, but it uses runtime checks. For the small number of call sites where a consuming emit doesn't work, the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will be removed in subsequent commits.) Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes consuming, while `delay_as_bug_without_consuming` is added (which will also be removed in subsequent commits.) All this requires significant changes to `DiagnosticBuilder`'s chaining methods. Currently `DiagnosticBuilder` method chaining uses a non-consuming `&mut self -> &mut Self` style, which allows chaining to be used when the chain ends in `emit()`, like so: ``` struct_err(msg).span(span).emit(); ``` But it doesn't work when producing a `DiagnosticBuilder` value, requiring this: ``` let mut err = self.struct_err(msg); err.span(span); err ``` This style of chaining won't work with consuming `emit` though. For that, we need to use to a `self -> Self` style. That also would allow `DiagnosticBuilder` production to be chained, e.g.: ``` self.struct_err(msg).span(span) ``` However, removing the `&mut self -> &mut Self` style would require that individual modifications of a `DiagnosticBuilder` go from this: ``` err.span(span); ``` to this: ``` err = err.span(span); ``` There are *many* such places. I have a high tolerance for tedious refactorings, but even I gave up after a long time trying to convert them all. Instead, this commit has it both ways: the existing `&mut self -> Self` chaining methods are kept, and new `self -> Self` chaining methods are added, all of which have a `_mv` suffix (short for "move"). Changes to the existing `forward!` macro lets this happen with very little additional boilerplate code. I chose to add the suffix to the new chaining methods rather than the existing ones, because the number of changes required is much smaller that way. This doubled chainging is a bit clumsy, but I think it is worthwhile because it allows a *lot* of good things to subsequently happen. In this commit, there are many `mut` qualifiers removed in places where diagnostics are emitted without being modified. In subsequent commits: - chaining can be used more, making the code more concise; - more use of chaining also permits the removal of redundant diagnostic APIs like `struct_err_with_code`, which can be replaced easily with `struct_err` + `code_mv`; - `emit_without_diagnostic` can be removed, which simplifies a lot of machinery, removing the need for `DiagnosticBuilderState`.
This commit is contained in:
parent
ca2fc426a9
commit
b1b9278851
86 changed files with 329 additions and 312 deletions
|
@ -278,7 +278,7 @@ impl<'a> TokenTreesReader<'a> {
|
|||
}
|
||||
if !diff_errs.is_empty() {
|
||||
errs.iter_mut().for_each(|err| {
|
||||
err.delay_as_bug();
|
||||
err.delay_as_bug_without_consuming();
|
||||
});
|
||||
return diff_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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
@ -1218,7 +1218,7 @@ impl<'a> Parser<'a> {
|
|||
"::",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
.emit_without_consuming();
|
||||
match self.parse_expr() {
|
||||
Ok(_) => {
|
||||
*expr = self.mk_expr_err(expr.span.to(self.prev_token.span));
|
||||
|
@ -2045,7 +2045,7 @@ impl<'a> Parser<'a> {
|
|||
) -> P<Expr> {
|
||||
match result {
|
||||
Ok(x) => x,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
// Recover from parse error, callers expect the closing delim to be consumed.
|
||||
self.consume_block(delim, ConsumeClosingDelim::Yes);
|
||||
|
@ -2470,7 +2470,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();
|
||||
|
@ -2946,7 +2946,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) =>
|
||||
{
|
||||
|
@ -1333,12 +1333,12 @@ impl<'a> Parser<'a> {
|
|||
.collect(),
|
||||
},
|
||||
});
|
||||
replacement_err.emit();
|
||||
replacement_err.emit_without_consuming();
|
||||
|
||||
let old_err = mem::replace(err, replacement_err);
|
||||
old_err.cancel();
|
||||
} else {
|
||||
err.emit();
|
||||
err.emit_without_consuming();
|
||||
}
|
||||
return Some(self.mk_expr_err(span));
|
||||
}
|
||||
|
@ -1756,9 +1756,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 +1766,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 +2902,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 +3436,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,7 @@ impl<'a> Parser<'a> {
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
err.emit_without_consuming();
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,7 +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();
|
||||
let err = self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err();
|
||||
err.emit();
|
||||
unsafety = Unsafe::Yes(self.token.span);
|
||||
self.eat_keyword(kw::Unsafe);
|
||||
|
@ -1198,7 +1201,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 +1219,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 +1457,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();
|
||||
|
@ -1811,7 +1814,7 @@ impl<'a> Parser<'a> {
|
|||
// `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();
|
||||
err.delay_as_bug_without_consuming();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1828,7 +1831,7 @@ impl<'a> Parser<'a> {
|
|||
",",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
err.emit_without_consuming();
|
||||
recovered = true;
|
||||
}
|
||||
|
||||
|
@ -1846,7 +1849,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 +1865,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 `:`",
|
||||
":",
|
||||
|
@ -2598,7 +2601,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) =>
|
||||
|
@ -251,7 +251,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
});
|
||||
if trailing_vert {
|
||||
err.delay_as_bug();
|
||||
err.delay_as_bug_without_consuming();
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
@ -1028,7 +1028,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 +1040,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 +1113,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 +1132,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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue