diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index da93156b0b0b..4bde363672dc 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -70,7 +70,7 @@ 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 @@ fn binding_suggestion<'tcx, S: fmt::Display>( 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 d158f52c643c..3393a2bf89d4 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 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { 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 ad39f48972f6..3633d6f9934e 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -109,6 +109,7 @@ 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 @@ fn warn_about_unused(&self, 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 aacfbd065558..dc4233436c66 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -27,7 +27,7 @@ Overflow, }; -use errors::DiagnosticBuilder; +use errors::{Applicability, DiagnosticBuilder}; use hir; use hir::def_id::DefId; use infer::{self, InferCtxt}; @@ -852,9 +852,12 @@ fn suggest_borrow_on_unsized_slice(&self, 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 @@ fn suggest_remove_reference(&self, 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 @@ pub fn report_arg_count_mismatch( 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 @@ pub fn report_arg_count_mismatch( "".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 81b32f436c8d..de73295b499f 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -330,6 +330,23 @@ pub fn span_suggestions_with_applicability(&mut self, sp: Span, msg: &str, 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 b813edadc577..562c28f08405 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -205,6 +205,12 @@ pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self 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 fcda6ce9b164..076b6d176584 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -20,7 +20,7 @@ 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 667105a534aa..83e7dd84cbff 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -13,7 +13,7 @@ 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 @@ fn expand(&mut self, expansion: Expansion) -> Expansion { 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 c39eb1594b28..c396fb0fbc0c 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 @@ fn next_token_inner(&mut self) -> Result { 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 716faaa4e397..28f93328e953 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -43,7 +43,7 @@ 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 @@ fn maybe_report_ambiguous_plus(&mut self, allow_plus: bool, impl_dyn_multi: bool 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 @@ fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PRe 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 @@ fn maybe_recover_from_bad_qpath(&mut self, base: T, allow_recov 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 @@ fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec, lo: Span) -> PResult<'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 @@ pub fn parse_prefix_expr(&mut self, 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 @@ pub fn parse_prefix_expr(&mut self, // 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 @@ pub fn parse_assoc_expr_with(&mut self, 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 @@ fn parse_assoc_op_cast(&mut self, lhs: P, lhs_span: Span, 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 @@ pub fn parse_for_expr(&mut self, opt_label: Option