From 6bb4aad51f40536447cd7603ab5be7792bab0a3d Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 12 May 2018 20:44:50 -0700 Subject: [PATCH 1/2] introducing `span_suggestion_short_with_applicability` Some would argue that this 40-character method name is ludicrously unwieldy (even ironic), but it's the unique continuation of the precedent set by the other suggestion methods. (And there is some hope that someday we'll just fold `Applicability` into the signature of the "basic" method `span_suggestion`.) This is in support of #50723. --- src/librustc_errors/diagnostic.rs | 17 +++++++++++++++++ src/librustc_errors/diagnostic_builder.rs | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 75401f21862b6..bb2badaf293b6 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -311,6 +311,23 @@ impl Diagnostic { self } + pub fn span_suggestion_short_with_applicability( + &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability + ) -> &mut Self { + self.suggestions.push(CodeSuggestion { + substitutions: vec![Substitution { + parts: vec![SubstitutionPart { + snippet: suggestion, + span: sp, + }], + }], + msg: msg.to_owned(), + show_code_when_inline: false, + applicability: applicability, + }); + self + } + pub fn set_span>(&mut self, sp: S) -> &mut Self { self.span = sp.into(); self diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 7e9ca8633a53e..41c3f7ce841e3 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -200,6 +200,12 @@ impl<'a> DiagnosticBuilder<'a> { suggestions: Vec, applicability: Applicability) -> &mut Self); + forward!(pub fn span_suggestion_short_with_applicability(&mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability) + -> &mut Self); forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); From 98a04291e4db92ae86d7e3a20b5763cb926ebfbf Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 19 May 2018 14:52:24 -0700 Subject: [PATCH 2/2] suggestion applicabilities for libsyntax and librustc, run-rustfix tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consider this a down payment on #50723. To recap, an `Applicability` enum was recently (#50204) added, to convey to Rustfix and other tools whether we think it's OK for them to blindly apply the suggestion, or whether to prompt a human for guidance (because the suggestion might contain placeholders that we can't infer, or because we think it has a sufficiently high probability of being wrong even though it's— presumably—right often enough to be worth emitting in the first place). When a suggestion is marked as `MaybeIncorrect`, we try to use comments to indicate precisely why (although there are a few places where we just say `// speculative` because the present author's subjective judgement balked at the idea that the suggestion has no false positives). The `run-rustfix` directive is opporunistically set on some relevant UI tests (and a couple tests that were in the `test/ui/suggestions` directory, even if the suggestions didn't originate in librustc or libsyntax). This is less trivial than it sounds, because a surprising number of test files aren't equipped to be tested as fixed even when they contain successfully fixable errors, because, e.g., there are more, not-directly-related errors after fixing. Some test files need an attribute or underscore to avoid unused warnings tripping up the "fixed code is still producing diagnostics" check despite the fixes being correct; this is an interesting contrast-to/inconsistency-with the behavior of UI tests (which secretly pass `-A unused`), a behavior which we probably ought to resolve one way or the other (filed issue #50926). A few suggestion labels are reworded (e.g., to avoid phrasing it as a question, which which is discouraged by the style guidelines listed in `.span_suggestion`'s doc-comment). --- src/librustc/infer/error_reporting/mod.rs | 7 +- src/librustc/lint/levels.rs | 7 +- src/librustc/middle/liveness.rs | 13 +- src/librustc/traits/error_reporting.rs | 35 ++-- src/libsyntax/attr.rs | 20 +- src/libsyntax/ext/expand.rs | 8 +- src/libsyntax/parse/lexer/mod.rs | 13 +- src/libsyntax/parse/parser.rs | 192 +++++++++++++----- src/test/ui/extern-const.fixed | 25 +++ src/test/ui/extern-const.rs | 8 +- src/test/ui/extern-const.stderr | 4 +- src/test/ui/issue-42954.fixed | 24 +++ src/test/ui/issue-42954.rs | 4 + src/test/ui/issue-42954.stderr | 2 +- src/test/ui/issue-44406.stderr | 2 +- src/test/ui/issue-48636.fixed | 21 ++ src/test/ui/issue-48636.rs | 4 + src/test/ui/issue-48636.stderr | 2 +- ...-arg-count-expected-type-issue-47244.fixed | 30 +++ ...ure-arg-count-expected-type-issue-47244.rs | 11 +- ...arg-count-expected-type-issue-47244.stderr | 14 +- src/test/ui/repr-align-assign.fixed | 21 ++ src/test/ui/repr-align-assign.rs | 4 + src/test/ui/repr-align-assign.stderr | 4 +- .../issue-32354-suggest-import-rename.fixed | 26 +++ .../issue-32354-suggest-import-rename.rs | 4 + .../issue-32354-suggest-import-rename.stderr | 2 +- .../pub-ident-fn-or-struct-2.stderr | 2 +- .../suggestions/pub-ident-fn-or-struct.stderr | 2 +- src/test/ui/suggestions/pub-ident-fn.fixed | 18 ++ src/test/ui/suggestions/pub-ident-fn.rs | 4 +- src/test/ui/suggestions/pub-ident-fn.stderr | 6 +- ...ascription-instead-of-statement-end.stderr | 2 +- 33 files changed, 424 insertions(+), 117 deletions(-) create mode 100644 src/test/ui/extern-const.fixed create mode 100644 src/test/ui/issue-42954.fixed create mode 100644 src/test/ui/issue-48636.fixed create mode 100644 src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed create mode 100644 src/test/ui/repr-align-assign.fixed create mode 100644 src/test/ui/suggestions/issue-32354-suggest-import-rename.fixed create mode 100644 src/test/ui/suggestions/pub-ident-fn.fixed diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index da93156b0b0bd..4bde363672dcc 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -70,7 +70,7 @@ use ty::{self, Region, Ty, TyCtxt, TypeFoldable, TypeVariants}; use ty::error::TypeError; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; -use errors::{DiagnosticBuilder, DiagnosticStyledString}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_data_structures::indexed_vec::Idx; @@ -1097,7 +1097,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some((sp, has_lifetimes)) = type_param_span { let tail = if has_lifetimes { " + " } else { "" }; let suggestion = format!("{}: {}{}", bound_kind, sub, tail); - err.span_suggestion_short(sp, consider, suggestion); + err.span_suggestion_short_with_applicability( + sp, consider, suggestion, + Applicability::MaybeIncorrect // Issue #41966 + ); } else { err.help(consider); } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index d158f52c643ce..3393a2bf89d4b 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -10,7 +10,7 @@ use std::cmp; -use errors::DiagnosticBuilder; +use errors::{Applicability, DiagnosticBuilder}; use hir::HirId; use ich::StableHashingContext; use lint::builtin; @@ -265,10 +265,11 @@ impl<'a> LintLevelsBuilder<'a> { store.check_lint_name(&name_lower) { db.emit(); } else { - db.span_suggestion( + db.span_suggestion_with_applicability( li.span, "lowercase the lint name", - name_lower + name_lower, + Applicability::MachineApplicable ).emit(); } } else { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 3db8c746713fd..0ac0fdd79cbb8 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -109,6 +109,7 @@ use self::VarKind::*; use hir::def::*; use ty::{self, TyCtxt}; use lint; +use errors::Applicability; use util::nodemap::{NodeMap, NodeSet}; use std::collections::VecDeque; @@ -1541,11 +1542,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let mut err = self.ir.tcx .struct_span_lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, &msg); if self.ir.variable_is_shorthand(var) { - err.span_suggestion(sp, "try ignoring the field", - format!("{}: _", name)); + err.span_suggestion_with_applicability(sp, "try ignoring the field", + format!("{}: _", name), + Applicability::MachineApplicable); } else { - err.span_suggestion_short(sp, &suggest_underscore_msg, - format!("_{}", name)); + err.span_suggestion_short_with_applicability( + sp, &suggest_underscore_msg, + format!("_{}", name), + Applicability::MachineApplicable, + ); } err.emit() } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 97ce730c59ec5..66eee3e7c1ac8 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -27,7 +27,7 @@ use super::{ Overflow, }; -use errors::DiagnosticBuilder; +use errors::{Applicability, DiagnosticBuilder}; use hir; use hir::def_id::DefId; use infer::{self, InferCtxt}; @@ -856,9 +856,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(ref expr) = local.init { if let hir::ExprIndex(_, _) = expr.node { if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(expr.span) { - err.span_suggestion(expr.span, - "consider borrowing here", - format!("&{}", snippet)); + err.span_suggestion_with_applicability( + expr.span, + "consider borrowing here", + format!("&{}", snippet), + Applicability::MachineApplicable + ); } } } @@ -901,7 +904,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let format_str = format!("consider removing {} leading `&`-references", remove_refs); - err.span_suggestion_short(sp, &format_str, String::from("")); + err.span_suggestion_short_with_applicability( + sp, &format_str, String::from(""), Applicability::MachineApplicable + ); break; } } else { @@ -1046,10 +1051,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let sugg = fields.iter() .map(|(name, _)| name.to_owned()) .collect::>().join(", "); - err.span_suggestion(found_span, - "change the closure to take multiple arguments instead of \ - a single tuple", - format!("|{}|", sugg)); + err.span_suggestion_with_applicability(found_span, + "change the closure to take multiple \ + arguments instead of a single tuple", + format!("|{}|", sugg), + Applicability::MachineApplicable); } } if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { @@ -1077,10 +1083,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "".to_owned() }, ); - err.span_suggestion(found_span, - "change the closure to accept a tuple instead of \ - individual arguments", - sugg); + err.span_suggestion_with_applicability( + found_span, + "change the closure to accept a tuple instead of \ + individual arguments", + sugg, + Applicability::MachineApplicable + ); } } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index fcda6ce9b164d..076b6d1765848 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -20,7 +20,7 @@ use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind}; use codemap::{BytePos, Spanned, respan, dummy_spanned}; use syntax_pos::Span; -use errors::Handler; +use errors::{Applicability, Handler}; use feature_gate::{Features, GatedCfg}; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use parse::parser::Parser; @@ -1067,14 +1067,20 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec "incorrect `repr(align)` attribute format"); match value.node { ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - err.span_suggestion(item.span, - "use parentheses instead", - format!("align({})", int)); + err.span_suggestion_with_applicability( + item.span, + "use parentheses instead", + format!("align({})", int), + Applicability::MachineApplicable + ); } ast::LitKind::Str(s, _) => { - err.span_suggestion(item.span, - "use parentheses instead", - format!("align({})", s)); + err.span_suggestion_with_applicability( + item.span, + "use parentheses instead", + format!("align({})", s), + Applicability::MachineApplicable + ); } _ => {} } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 146db632c07ba..0bee8e20009a6 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -13,7 +13,7 @@ use ast::{MacStmtStyle, StmtKind, ItemKind}; use attr::{self, HasAttrs}; use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute, dummy_spanned, respan}; use config::{is_test_or_bench, StripUnconfigured}; -use errors::FatalError; +use errors::{Applicability, FatalError}; use ext::base::*; use ext::derive::{add_derived_markers, collect_derives}; use ext::hygiene::{self, Mark, SyntaxContext}; @@ -331,7 +331,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let trait_list = traits.iter() .map(|t| format!("{}", t)).collect::>(); let suggestion = format!("#[derive({})]", trait_list.join(", ")); - err.span_suggestion(span, "try an outer attribute", suggestion); + err.span_suggestion_with_applicability( + span, "try an outer attribute", suggestion, + // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT + Applicability::MaybeIncorrect + ); } err.emit(); } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index bbece1ee5e3d4..b665f528cfc03 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -11,7 +11,7 @@ use ast::{self, Ident}; use syntax_pos::{self, BytePos, CharPos, Pos, Span, NO_EXPANSION}; use codemap::{CodeMap, FilePathMapping}; -use errors::{FatalError, DiagnosticBuilder}; +use errors::{Applicability, FatalError, DiagnosticBuilder}; use parse::{token, ParseSess}; use str::char_at; use symbol::{Symbol, keywords}; @@ -1345,11 +1345,12 @@ impl<'a> StringReader<'a> { self.sess.span_diagnostic .struct_span_err(span, "character literal may only contain one codepoint") - .span_suggestion(span, - "if you meant to write a `str` literal, \ - use double quotes", - format!("\"{}\"", &self.src[start..end])) - .emit(); + .span_suggestion_with_applicability( + span, + "if you meant to write a `str` literal, use double quotes", + format!("\"{}\"", &self.src[start..end]), + Applicability::MachineApplicable + ).emit(); return Ok(token::Literal(token::Str_(Symbol::intern("??")), None)) } if self.ch_is('\n') || self.is_eof() || self.ch_is('/') { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3e9869494f934..1a7f897802aa9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -43,7 +43,7 @@ use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; use codemap::{self, CodeMap, Spanned, respan}; use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, DUMMY_SP}; -use errors::{self, DiagnosticBuilder}; +use errors::{self, Applicability, DiagnosticBuilder}; use parse::{self, classify, token}; use parse::common::SeqSep; use parse::lexer::TokenAndSpan; @@ -1648,8 +1648,12 @@ impl<'a> Parser<'a> { if !allow_plus && impl_dyn_multi { let sum_with_parens = format!("({})", pprust::ty_to_string(&ty)); self.struct_span_err(ty.span, "ambiguous `+` in a type") - .span_suggestion(ty.span, "use parentheses to disambiguate", sum_with_parens) - .emit(); + .span_suggestion_with_applicability( + ty.span, + "use parentheses to disambiguate", + sum_with_parens, + Applicability::MachineApplicable + ).emit(); } } @@ -1679,7 +1683,12 @@ impl<'a> Parser<'a> { s.print_bounds(" +", &bounds)?; s.pclose() }); - err.span_suggestion(sum_span, "try adding parentheses", sum_with_parens); + err.span_suggestion_with_applicability( + sum_span, + "try adding parentheses", + sum_with_parens, + Applicability::MachineApplicable + ); } TyKind::Ptr(..) | TyKind::BareFn(..) => { err.span_label(sum_span, "perhaps you forgot parentheses?"); @@ -1714,7 +1723,9 @@ impl<'a> Parser<'a> { self.diagnostic() .struct_span_err(span, "missing angle brackets in associated item path") - .span_suggestion(span, "try", recovered.to_string()).emit(); + .span_suggestion_with_applicability( // this is a best-effort recovery + span, "try", recovered.to_string(), Applicability::MaybeIncorrect + ).emit(); Ok(recovered) } @@ -2465,7 +2476,12 @@ impl<'a> Parser<'a> { exp_span.to(self.prev_span), "cannot use a comma after the base struct", ); - err.span_suggestion_short(self.span, "remove this comma", "".to_owned()); + err.span_suggestion_short_with_applicability( + self.span, + "remove this comma", + "".to_owned(), + Applicability::MachineApplicable + ); err.note("the base struct must always be the last field"); err.emit(); self.recover_stmt(); @@ -2638,10 +2654,12 @@ impl<'a> Parser<'a> { s.s.word(".")?; s.s.word(fstr.splitn(2, ".").last().unwrap()) }); - err.span_suggestion( + err.span_suggestion_with_applicability( lo.to(self.prev_span), "try parenthesizing the first index", - sugg); + sugg, + Applicability::MachineApplicable + ); } return Err(err); @@ -2781,9 +2799,12 @@ impl<'a> Parser<'a> { let span_of_tilde = lo; let mut err = self.diagnostic().struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator"); - err.span_suggestion_short(span_of_tilde, - "use `!` to perform bitwise negation", - "!".to_owned()); + err.span_suggestion_short_with_applicability( + span_of_tilde, + "use `!` to perform bitwise negation", + "!".to_owned(), + Applicability::MachineApplicable + ); err.emit(); (lo.to(span), self.mk_unary(UnOp::Not, e)) } @@ -2840,9 +2861,12 @@ impl<'a> Parser<'a> { // trailing whitespace after the `!` in our suggestion let to_replace = self.sess.codemap() .span_until_non_whitespace(lo.to(self.span)); - err.span_suggestion_short(to_replace, - "use `!` to perform logical negation", - "!".to_owned()); + err.span_suggestion_short_with_applicability( + to_replace, + "use `!` to perform logical negation", + "!".to_owned(), + Applicability::MachineApplicable + ); err.emit(); // —and recover! (just as if we were in the block // for the `token::Not` arm) @@ -2937,9 +2961,12 @@ impl<'a> Parser<'a> { let cur_pos = cm.lookup_char_pos(self.span.lo()); let op_pos = cm.lookup_char_pos(cur_op_span.hi()); if cur_pos.line != op_pos.line { - err.span_suggestion_short(cur_op_span, - "did you mean to use `;` here?", - ";".to_string()); + err.span_suggestion_with_applicability( + cur_op_span, + "try using a semicolon", + ";".to_string(), + Applicability::MaybeIncorrect // speculative + ); } return Err(err); } @@ -3091,9 +3118,12 @@ impl<'a> Parser<'a> { let expr_str = self.sess.codemap().span_to_snippet(expr.span) .unwrap_or(pprust::expr_to_string(&expr)); - err.span_suggestion(expr.span, - &format!("try {} the cast value", op_verb), - format!("({})", expr_str)); + err.span_suggestion_with_applicability( + expr.span, + &format!("try {} the cast value", op_verb), + format!("({})", expr_str), + Applicability::MachineApplicable + ); err.emit(); Ok(expr) @@ -3301,7 +3331,11 @@ impl<'a> Parser<'a> { let in_span = self.prev_span.between(self.span); let mut err = self.sess.span_diagnostic .struct_span_err(in_span, "missing `in` in `for` loop"); - err.span_suggestion_short(in_span, "try adding `in` here", " in ".into()); + err.span_suggestion_short_with_applicability( + in_span, "try adding `in` here", " in ".into(), + // has been misleading, at least in the past (closed Issue #48492) + Applicability::MaybeIncorrect + ); err.emit(); } let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; @@ -3367,7 +3401,12 @@ impl<'a> Parser<'a> { None)?; if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) { if self.token == token::Token::Semi { - e.span_suggestion_short(match_span, "try removing this `match`", "".to_owned()); + e.span_suggestion_short_with_applicability( + match_span, + "try removing this `match`", + "".to_owned(), + Applicability::MaybeIncorrect // speculative + ); } return Err(e) } @@ -3439,10 +3478,11 @@ impl<'a> Parser<'a> { // | - ^^ self.span // | | // | parsed until here as `"y" & X` - err.span_suggestion_short( + err.span_suggestion_short_with_applicability( cm.next_point(arm_start_span), "missing a comma here to end this `match` arm", - ",".to_owned() + ",".to_owned(), + Applicability::MachineApplicable ); } _ => { @@ -3511,9 +3551,12 @@ impl<'a> Parser<'a> { if self.token == token::OrOr { let mut err = self.struct_span_err(self.span, "unexpected token `||` after pattern"); - err.span_suggestion(self.span, - "use a single `|` to specify multiple patterns", - "|".to_owned()); + err.span_suggestion_with_applicability( + self.span, + "use a single `|` to specify multiple patterns", + "|".to_owned(), + Applicability::MachineApplicable + ); err.emit(); self.bump(); } else if self.check(&token::BinOp(token::Or)) { @@ -3643,9 +3686,12 @@ impl<'a> Parser<'a> { if self.token == token::DotDotDot { // Issue #46718 let mut err = self.struct_span_err(self.span, "expected field pattern, found `...`"); - err.span_suggestion(self.span, - "to omit remaining fields, use one fewer `.`", - "..".to_owned()); + err.span_suggestion_with_applicability( + self.span, + "to omit remaining fields, use one fewer `.`", + "..".to_owned(), + Applicability::MachineApplicable + ); err.emit(); } @@ -3776,8 +3822,12 @@ impl<'a> Parser<'a> { let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); if let Ok(seq_snippet) = self.sess.codemap().span_to_snippet(seq_span) { - err.span_suggestion(seq_span, "try adding parentheses", - format!("({})", seq_snippet)); + err.span_suggestion_with_applicability( + seq_span, + "try adding parentheses", + format!("({})", seq_snippet), + Applicability::MachineApplicable + ); } return Err(err); } @@ -3836,8 +3886,12 @@ impl<'a> Parser<'a> { let binding_mode = if self.eat_keyword(keywords::Ref) { self.diagnostic() .struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") - .span_suggestion(mutref_span, "try switching the order", "ref mut".into()) - .emit(); + .span_suggestion_with_applicability( + mutref_span, + "try switching the order", + "ref mut".into(), + Applicability::MachineApplicable + ).emit(); BindingMode::ByRef(Mutability::Mutable) } else { BindingMode::ByValue(Mutability::Mutable) @@ -3962,10 +4016,12 @@ impl<'a> Parser<'a> { pat.span, "the range pattern here has ambiguous interpretation", ); - err.span_suggestion( + err.span_suggestion_with_applicability( pat.span, "add parentheses to clarify the precedence", format!("({})", pprust::pat_to_string(&pat)), + // "ambiguous interpretation" implies that we have to be guessing + Applicability::MaybeIncorrect ); return Err(err); } @@ -4036,9 +4092,12 @@ impl<'a> Parser<'a> { (Ok(init), Some((_, colon_sp, mut err))) => { // init parsed, ty error // Could parse the type as if it were the initializer, it is likely there was a // typo in the code: `:` instead of `=`. Add suggestion and emit the error. - err.span_suggestion_short(colon_sp, - "use `=` if you meant to assign", - "=".to_string()); + err.span_suggestion_short_with_applicability( + colon_sp, + "use `=` if you meant to assign", + "=".to_string(), + Applicability::MachineApplicable + ); err.emit(); // As this was parsed successfully, continue as if the code has been fixed for the // rest of the file. It will still fail due to the emitted error, but we avoid @@ -4526,7 +4585,13 @@ impl<'a> Parser<'a> { s.print_stmt(&stmt)?; s.bclose_maybe_open(stmt.span, INDENT_UNIT, false) }); - e.span_suggestion(stmt_span, "try placing this code inside a block", sugg); + e.span_suggestion_with_applicability( + stmt_span, + "try placing this code inside a block", + sugg, + // speculative, has been misleading in the past (closed Issue #46836) + Applicability::MaybeIncorrect + ); } Err(mut e) => { self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); @@ -5370,9 +5435,12 @@ impl<'a> Parser<'a> { if is_macro_rules { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); - err.span_suggestion(sp, - "try exporting the macro", - "#[macro_export]".to_owned()); + err.span_suggestion_with_applicability( + sp, + "try exporting the macro", + "#[macro_export]".to_owned(), + Applicability::MaybeIncorrect // speculative + ); Err(err) } else { let mut err = self.diagnostic() @@ -5793,7 +5861,12 @@ impl<'a> Parser<'a> { } else { if seen_comma == false { let sp = self.sess.codemap().next_point(previous_span); - err.span_suggestion(sp, "missing comma here", ",".into()); + err.span_suggestion_with_applicability( + sp, + "missing comma here", + ",".into(), + Applicability::MachineApplicable + ); } return Err(err); } @@ -5883,7 +5956,9 @@ impl<'a> Parser<'a> { let help_msg = format!("make this visible only to module `{}` with `in`", path); self.expect(&token::CloseDelim(token::Paren))?; // `)` let mut err = self.span_fatal_help(path_span, msg, suggestion); - err.span_suggestion(path_span, &help_msg, format!("in {}", path)); + err.span_suggestion_with_applicability( + path_span, &help_msg, format!("in {}", path), Applicability::MachineApplicable + ); err.emit(); // emit diagnostic, but continue with public visibility } } @@ -5921,7 +5996,9 @@ impl<'a> Parser<'a> { let mut err = self.fatal(&format!("expected item, found `{}`", token_str)); if token_str == ";" { let msg = "consider removing this semicolon"; - err.span_suggestion_short(self.span, msg, "".to_string()); + err.span_suggestion_short_with_applicability( + self.span, msg, "".to_string(), Applicability::MachineApplicable + ); } else { err.span_label(self.span, "expected item"); } @@ -6735,7 +6812,9 @@ impl<'a> Parser<'a> { ident); let mut err = self.diagnostic() .struct_span_err(sp, "missing `struct` for struct definition"); - err.span_suggestion_short(sp, &msg, " struct ".into()); + err.span_suggestion_short_with_applicability( + sp, &msg, " struct ".into(), Applicability::MaybeIncorrect // speculative + ); return Err(err); } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { let ident = self.parse_ident().unwrap(); @@ -6758,13 +6837,18 @@ impl<'a> Parser<'a> { kw, ident, kw_name); - err.span_suggestion_short(sp, &suggestion, format!(" {} ", kw)); + err.span_suggestion_short_with_applicability( + sp, &suggestion, format!(" {} ", kw), Applicability::MachineApplicable + ); } else { if let Ok(snippet) = self.sess.codemap().span_to_snippet(ident_sp) { - err.span_suggestion( + err.span_suggestion_with_applicability( full_sp, - "if you meant to call a macro, write instead", - format!("{}!", snippet)); + "if you meant to call a macro, try", + format!("{}!", snippet), + // this is the `ambiguous` conditional branch + Applicability::MaybeIncorrect + ); } else { err.help("if you meant to call a macro, remove the `pub` \ and add a trailing `!` after the identifier"); @@ -6790,8 +6874,12 @@ impl<'a> Parser<'a> { if self.token.is_keyword(keywords::Const) { self.diagnostic() .struct_span_err(self.span, "extern items cannot be `const`") - .span_suggestion(self.span, "instead try using", "static".to_owned()) - .emit(); + .span_suggestion_with_applicability( + self.span, + "try using a static value", + "static".to_owned(), + Applicability::MachineApplicable + ).emit(); } self.bump(); // `static` or `const` return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?)); diff --git a/src/test/ui/extern-const.fixed b/src/test/ui/extern-const.fixed new file mode 100644 index 0000000000000..6e131ca41aa97 --- /dev/null +++ b/src/test/ui/extern-const.fixed @@ -0,0 +1,25 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix +// compile-flags: -Z continue-parse-after-error + +extern "C" { + static C: u8; //~ ERROR extern items cannot be `const` +} + +fn main() { + // We suggest turning the (illegal) extern `const` into an extern `static`, + // but this also requires `unsafe` (a deny-by-default lint at comment time, + // future error; Issue #36247) + unsafe { + let _x = C; + } +} diff --git a/src/test/ui/extern-const.rs b/src/test/ui/extern-const.rs index a77d7b1189566..4a766b9724dc2 100644 --- a/src/test/ui/extern-const.rs +++ b/src/test/ui/extern-const.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix // compile-flags: -Z continue-parse-after-error extern "C" { @@ -15,5 +16,10 @@ extern "C" { } fn main() { - let x = C; + // We suggest turning the (illegal) extern `const` into an extern `static`, + // but this also requires `unsafe` (a deny-by-default lint at comment time, + // future error; Issue #36247) + unsafe { + let _x = C; + } } diff --git a/src/test/ui/extern-const.stderr b/src/test/ui/extern-const.stderr index f416f596b2552..cbed5e56c76c4 100644 --- a/src/test/ui/extern-const.stderr +++ b/src/test/ui/extern-const.stderr @@ -1,8 +1,8 @@ error: extern items cannot be `const` - --> $DIR/extern-const.rs:14:5 + --> $DIR/extern-const.rs:15:5 | LL | const C: u8; //~ ERROR extern items cannot be `const` - | ^^^^^ help: instead try using: `static` + | ^^^^^ help: try using a static value: `static` error: aborting due to previous error diff --git a/src/test/ui/issue-42954.fixed b/src/test/ui/issue-42954.fixed new file mode 100644 index 0000000000000..d05996fb8b91b --- /dev/null +++ b/src/test/ui/issue-42954.fixed @@ -0,0 +1,24 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![allow(unused_must_use, unused_comparisons)] + +macro_rules! is_plainly_printable { + ($i: ident) => { + ($i as u32) < 0 //~ `<` is interpreted as a start of generic arguments + }; +} + +fn main() { + let c = 'a'; + is_plainly_printable!(c); +} diff --git a/src/test/ui/issue-42954.rs b/src/test/ui/issue-42954.rs index 6fa2c69bf6696..8226cedc0c421 100644 --- a/src/test/ui/issue-42954.rs +++ b/src/test/ui/issue-42954.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + +#![allow(unused_must_use, unused_comparisons)] + macro_rules! is_plainly_printable { ($i: ident) => { $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments diff --git a/src/test/ui/issue-42954.stderr b/src/test/ui/issue-42954.stderr index 9164434006f61..aa332602f9e8f 100644 --- a/src/test/ui/issue-42954.stderr +++ b/src/test/ui/issue-42954.stderr @@ -1,5 +1,5 @@ error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison - --> $DIR/issue-42954.rs:13:19 + --> $DIR/issue-42954.rs:17:19 | LL | $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments | --------- ^ - interpreted as generic arguments diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr index de7c11732e4a3..5cd9b3f065eb8 100644 --- a/src/test/ui/issue-44406.stderr +++ b/src/test/ui/issue-44406.stderr @@ -8,7 +8,7 @@ error: expected type, found keyword `true` --> $DIR/issue-44406.rs:18:10 | LL | bar(baz: $rest) - | - help: did you mean to use `;` here? + | - help: try using a semicolon: `;` ... LL | foo!(true); //~ ERROR expected type, found keyword | ^^^^ expecting a type here because of type ascription diff --git a/src/test/ui/issue-48636.fixed b/src/test/ui/issue-48636.fixed new file mode 100644 index 0000000000000..0ff33c42b1c82 --- /dev/null +++ b/src/test/ui/issue-48636.fixed @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![allow(dead_code)] + +struct S { + x: u8, + /// The id of the parent core + y: u8, +} +//~^^^ ERROR found a documentation comment that doesn't document anything +fn main() {} diff --git a/src/test/ui/issue-48636.rs b/src/test/ui/issue-48636.rs index 03e45d88e6cf1..2ac41211347b5 100644 --- a/src/test/ui/issue-48636.rs +++ b/src/test/ui/issue-48636.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + +#![allow(dead_code)] + struct S { x: u8 /// The id of the parent core diff --git a/src/test/ui/issue-48636.stderr b/src/test/ui/issue-48636.stderr index 4e014a5bd1d1d..c4706f982ed74 100644 --- a/src/test/ui/issue-48636.stderr +++ b/src/test/ui/issue-48636.stderr @@ -1,5 +1,5 @@ error[E0585]: found a documentation comment that doesn't document anything - --> $DIR/issue-48636.rs:13:5 + --> $DIR/issue-48636.rs:17:5 | LL | x: u8 | - help: missing comma here: `,` diff --git a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed new file mode 100644 index 0000000000000..1a7608fea6e27 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed @@ -0,0 +1,30 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #47244: in this specific scenario, when the +// expected type indicated 1 argument but the closure takes two, we +// would (early on) create type variables for the type of `b`. If the +// user then attempts to invoke a method on `b`, we would get an error +// saying that the type of `b` must be known, which was not very +// helpful. + +// run-rustfix + +use std::collections::HashMap; + +fn main() { + let mut m = HashMap::new(); + m.insert("foo", "bar"); + + let _n = m.iter().map(|(_, b)| { + //~^ ERROR closure is expected to take a single 2-tuple + b.to_string() + }); +} diff --git a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs index b6463ca067b7f..0ca0753490a2f 100644 --- a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs +++ b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs @@ -15,15 +15,16 @@ // saying that the type of `b` must be known, which was not very // helpful. +// run-rustfix + use std::collections::HashMap; -fn main() { - let m = HashMap::new(); - m.insert( "foo", "bar" ); +fn main() { + let mut m = HashMap::new(); + m.insert("foo", "bar"); - m.iter().map( |_, b| { + let _n = m.iter().map(|_, b| { //~^ ERROR closure is expected to take a single 2-tuple - b.to_string() }); } diff --git a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr index 262c4aa1a7c7a..c95d8157b0ce1 100644 --- a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr @@ -1,14 +1,14 @@ error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments - --> $DIR/closure-arg-count-expected-type-issue-47244.rs:24:14 + --> $DIR/closure-arg-count-expected-type-issue-47244.rs:26:23 | -LL | m.iter().map( |_, b| { - | ^^^ ------ takes 2 distinct arguments - | | - | expected closure that takes a single 2-tuple as argument +LL | let _n = m.iter().map(|_, b| { + | ^^^ ------ takes 2 distinct arguments + | | + | expected closure that takes a single 2-tuple as argument help: change the closure to accept a tuple instead of individual arguments | -LL | m.iter().map( |(_, b)| { - | ^^^^^^^^ +LL | let _n = m.iter().map(|(_, b)| { + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/repr-align-assign.fixed b/src/test/ui/repr-align-assign.fixed new file mode 100644 index 0000000000000..62147e7625eb2 --- /dev/null +++ b/src/test/ui/repr-align-assign.fixed @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![allow(dead_code)] + +#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format +struct A(u64); + +#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format +struct B(u64); + +fn main() {} diff --git a/src/test/ui/repr-align-assign.rs b/src/test/ui/repr-align-assign.rs index c9780dde235bc..3bc3b5c64ce25 100644 --- a/src/test/ui/repr-align-assign.rs +++ b/src/test/ui/repr-align-assign.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + +#![allow(dead_code)] + #[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format struct A(u64); diff --git a/src/test/ui/repr-align-assign.stderr b/src/test/ui/repr-align-assign.stderr index 1fa1263b9467e..c325b6968fe43 100644 --- a/src/test/ui/repr-align-assign.stderr +++ b/src/test/ui/repr-align-assign.stderr @@ -1,11 +1,11 @@ error[E0693]: incorrect `repr(align)` attribute format - --> $DIR/repr-align-assign.rs:11:8 + --> $DIR/repr-align-assign.rs:15:8 | LL | #[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format | ^^^^^^^ help: use parentheses instead: `align(8)` error[E0693]: incorrect `repr(align)` attribute format - --> $DIR/repr-align-assign.rs:14:8 + --> $DIR/repr-align-assign.rs:18:8 | LL | #[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format | ^^^^^^^^^ help: use parentheses instead: `align(8)` diff --git a/src/test/ui/suggestions/issue-32354-suggest-import-rename.fixed b/src/test/ui/suggestions/issue-32354-suggest-import-rename.fixed new file mode 100644 index 0000000000000..251f7eb9a2487 --- /dev/null +++ b/src/test/ui/suggestions/issue-32354-suggest-import-rename.fixed @@ -0,0 +1,26 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![allow(unused_imports)] + +pub mod extension1 { + pub trait ConstructorExtension {} +} + +pub mod extension2 { + pub trait ConstructorExtension {} +} + +use extension1::ConstructorExtension; +use extension2::ConstructorExtension as OtherConstructorExtension; //~ ERROR is defined multiple times + +fn main() {} diff --git a/src/test/ui/suggestions/issue-32354-suggest-import-rename.rs b/src/test/ui/suggestions/issue-32354-suggest-import-rename.rs index 9d71ab1a788eb..57cbeb47a1e04 100644 --- a/src/test/ui/suggestions/issue-32354-suggest-import-rename.rs +++ b/src/test/ui/suggestions/issue-32354-suggest-import-rename.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + +#![allow(unused_imports)] + pub mod extension1 { pub trait ConstructorExtension {} } diff --git a/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr b/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr index 7cf7a1d15a27a..f45a5f7dd619b 100644 --- a/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr +++ b/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr @@ -1,5 +1,5 @@ error[E0252]: the name `ConstructorExtension` is defined multiple times - --> $DIR/issue-32354-suggest-import-rename.rs:20:5 + --> $DIR/issue-32354-suggest-import-rename.rs:24:5 | LL | use extension1::ConstructorExtension; | -------------------------------- previous import of the trait `ConstructorExtension` here diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr b/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr index c945033ad74ab..e492a8c47567e 100644 --- a/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr +++ b/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr @@ -2,7 +2,7 @@ error: missing `fn` or `struct` for method or struct definition --> $DIR/pub-ident-fn-or-struct-2.rs:11:4 | LL | pub S(); - | ---^- help: if you meant to call a macro, write instead: `S!` + | ---^- help: if you meant to call a macro, try: `S!` error: aborting due to previous error diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr b/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr index 9528c15dfa18f..c1bff34cec3e6 100644 --- a/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr +++ b/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr @@ -2,7 +2,7 @@ error: missing `fn` or `struct` for method or struct definition --> $DIR/pub-ident-fn-or-struct.rs:11:4 | LL | pub S (foo) bar - | ---^- help: if you meant to call a macro, write instead: `S!` + | ---^- help: if you meant to call a macro, try: `S!` error: aborting due to previous error diff --git a/src/test/ui/suggestions/pub-ident-fn.fixed b/src/test/ui/suggestions/pub-ident-fn.fixed new file mode 100644 index 0000000000000..f2d0c6c3e1d3f --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-fn.fixed @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +pub fn foo(_s: usize) -> bool { true } +//~^ ERROR missing `fn` for method definition + +fn main() { + foo(2); +} diff --git a/src/test/ui/suggestions/pub-ident-fn.rs b/src/test/ui/suggestions/pub-ident-fn.rs index 1d64199642093..82c32f57eeae0 100644 --- a/src/test/ui/suggestions/pub-ident-fn.rs +++ b/src/test/ui/suggestions/pub-ident-fn.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub foo(s: usize) -> bool { true } +// run-rustfix + +pub foo(_s: usize) -> bool { true } //~^ ERROR missing `fn` for method definition fn main() { diff --git a/src/test/ui/suggestions/pub-ident-fn.stderr b/src/test/ui/suggestions/pub-ident-fn.stderr index de7ee71d1b40f..f7c96b8b9f4bb 100644 --- a/src/test/ui/suggestions/pub-ident-fn.stderr +++ b/src/test/ui/suggestions/pub-ident-fn.stderr @@ -1,11 +1,11 @@ error: missing `fn` for method definition - --> $DIR/pub-ident-fn.rs:11:4 + --> $DIR/pub-ident-fn.rs:13:4 | -LL | pub foo(s: usize) -> bool { true } +LL | pub foo(_s: usize) -> bool { true } | ^^^ help: add `fn` here to parse `foo` as a public method | -LL | pub fn foo(s: usize) -> bool { true } +LL | pub fn foo(_s: usize) -> bool { true } | ^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/type-ascription-instead-of-statement-end.stderr b/src/test/ui/suggestions/type-ascription-instead-of-statement-end.stderr index 02a80d86c846d..314c9060d4f7d 100644 --- a/src/test/ui/suggestions/type-ascription-instead-of-statement-end.stderr +++ b/src/test/ui/suggestions/type-ascription-instead-of-statement-end.stderr @@ -2,7 +2,7 @@ error: expected type, found `0` --> $DIR/type-ascription-instead-of-statement-end.rs:15:5 | LL | println!("test"): - | - help: did you mean to use `;` here? + | - help: try using a semicolon: `;` LL | 0; //~ ERROR expected type, found `0` | ^ expecting a type here because of type ascription