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 ad39f48972f69..3633d6f9934ec 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; @@ -1535,11 +1536,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 aacfbd065558f..dc4233436c660 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}; @@ -852,9 +852,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 + ); } } } @@ -897,7 +900,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 { @@ -1042,10 +1047,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[..] { @@ -1073,10 +1079,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/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 81b32f436c8dd..de73295b499fa 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -330,6 +330,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 b813edadc577e..562c28f08405a 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -205,6 +205,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); 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 667105a534aa3..83e7dd84cbff2 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 c39eb1594b28b..c396fb0fbc0c4 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}; @@ -1379,11 +1379,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 716faaa4e397a..28f93328e9534 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; @@ -1655,8 +1655,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(); } } @@ -1686,7 +1690,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?"); @@ -1724,7 +1733,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) } @@ -2498,7 +2509,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(); @@ -2671,10 +2687,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); @@ -2814,9 +2832,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)) } @@ -2884,9 +2905,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) @@ -2981,9 +3005,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); } @@ -3137,9 +3164,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) @@ -3347,7 +3377,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)?; @@ -3413,7 +3447,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) } @@ -3485,10 +3524,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 ); } _ => { @@ -3557,9 +3597,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)) { @@ -3689,9 +3732,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(); } @@ -3822,8 +3868,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); } @@ -3882,8 +3932,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) @@ -4008,10 +4062,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); } @@ -4082,9 +4138,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 @@ -4572,7 +4631,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); @@ -5416,9 +5481,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() @@ -5839,7 +5907,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); } @@ -5938,7 +6011,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 } } @@ -5976,7 +6051,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"); } @@ -6793,7 +6870,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(); @@ -6816,13 +6895,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"); @@ -6848,8 +6932,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