diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index d83470354ac..8486bf782b0 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -354,7 +354,7 @@ impl<'a> Context<'a> { } } if self.rejected_via_kind.len() > 0 { - self.sess.span_help(self.span, "please recompile this crate using \ + self.sess.fileline_help(self.span, "please recompile this crate using \ --crate-type lib"); let mismatches = self.rejected_via_kind.iter(); for (i, &CrateMismatch { ref path, .. }) in mismatches.enumerate() { diff --git a/src/librustc/metadata/macro_import.rs b/src/librustc/metadata/macro_import.rs index d25dc4f58a5..19a29b8eb1b 100644 --- a/src/librustc/metadata/macro_import.rs +++ b/src/librustc/metadata/macro_import.rs @@ -84,7 +84,7 @@ impl<'a, 'v> Visitor<'v> for MacroLoader<'a> { } "plugin" => { self.sess.span_err(attr.span, "#[plugin] on `extern crate` is deprecated"); - self.sess.span_help(attr.span, &format!("use a crate attribute instead, \ + self.sess.fileline_help(attr.span, &format!("use a crate attribute instead, \ i.e. #![plugin({})]", item.ident.as_str())); } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index f8a2c507e42..10885359985 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -246,7 +246,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) "pattern binding `{}` is named the same as one \ of the variants of the type `{}`", &token::get_ident(ident.node), ty_to_string(cx.tcx, pat_ty)); - span_help!(cx.tcx.sess, p.span, + fileline_help!(cx.tcx.sess, p.span, "if you meant to match on a variant, \ consider making the path in the pattern qualified: `{}::{}`", ty_to_string(cx.tcx, pat_ty), &token::get_ident(ident.node)); diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index da4df813030..a7f5c2c8437 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -444,7 +444,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { // Does the required lifetime have a nice name we can print? span_err!(self.tcx.sess, origin.span(), E0309, "{} may not live long enough", labeled_user_string); - self.tcx.sess.span_help( + self.tcx.sess.fileline_help( origin.span(), &format!( "consider adding an explicit lifetime bound `{}: {}`...", @@ -456,7 +456,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { // Does the required lifetime have a nice name we can print? span_err!(self.tcx.sess, origin.span(), E0310, "{} may not live long enough", labeled_user_string); - self.tcx.sess.span_help( + self.tcx.sess.fileline_help( origin.span(), &format!( "consider adding an explicit lifetime bound `{}: 'static`...", @@ -468,7 +468,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span_err!(self.tcx.sess, origin.span(), E0311, "{} may not live long enough", labeled_user_string); - self.tcx.sess.span_help( + self.tcx.sess.fileline_help( origin.span(), &format!( "consider adding an explicit lifetime bound for `{}`", diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index 53761eb1471..84636ebaae4 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -165,7 +165,7 @@ fn note_move_destination(bccx: &BorrowckCtxt, bccx.span_note( move_to_span, "attempting to move value to here"); - bccx.span_help( + bccx.fileline_help( move_to_span, &format!("to prevent the move, \ use `ref {0}` or `ref mut {0}` to capture value by \ diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index f6df2acce59..42b3555b54e 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -643,7 +643,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { ol, moved_lp_msg, pat_ty.user_string(self.tcx))); - self.tcx.sess.span_help(span, + self.tcx.sess.fileline_help(span, "use `ref` to override"); } @@ -675,7 +675,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { moved_lp_msg, expr_ty.user_string(self.tcx), suggestion)); - self.tcx.sess.span_help(expr_span, help); + self.tcx.sess.fileline_help(expr_span, help); } } @@ -741,6 +741,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_help(s, m); } + pub fn fileline_help(&self, s: Span, m: &str) { + self.tcx.sess.fileline_help(s, m); + } + pub fn bckerr_to_string(&self, err: &BckError<'tcx>) -> String { match err.code { err_mutbl => { @@ -870,7 +874,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } if is_closure { - self.tcx.sess.span_help( + self.tcx.sess.fileline_help( span, "closures behind references must be called via `&mut`"); } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 22311a71583..56b1f269e17 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1921,7 +1921,8 @@ impl LintPass for UnconditionalRecursion { for call in &self_call_spans { sess.span_note(*call, "recursive call site") } - sess.span_help(sp, "a `loop` may express intention better if this is on purpose") + sess.fileline_help(sp, "a `loop` may express intention \ + better if this is on purpose") } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 78ce9abe07d..0ddfd707f00 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4115,10 +4115,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { uses it like a function name", path_name)); - self.session.span_help(expr.span, - &format!("Did you mean to write: \ - `{} {{ /* fields */ }}`?", - path_name)); + let msg = format!("Did you mean to write: \ + `{} {{ /* fields */ }}`?", + path_name); + if self.emit_errors { + self.session.fileline_help(expr.span, &msg); + } else { + self.session.span_help(expr.span, &msg); + } } else { // Write the result into the def map. debug!("(resolving expr) resolved `{}`", @@ -4146,18 +4150,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match type_res.map(|r| r.base_def) { Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { - self.resolve_error(expr.span, + self.resolve_error(expr.span, &format!("`{}` is a structure name, but \ this expression \ uses it like a function name", path_name)); - self.session.span_help(expr.span, - &format!("Did you mean to write: \ - `{} {{ /* fields */ }}`?", - path_name)); - - } + let msg = format!("Did you mean to write: \ + `{} {{ /* fields */ }}`?", + path_name); + if self.emit_errors { + self.session.fileline_help(expr.span, &msg); + } else { + self.session.span_help(expr.span, &msg); + } + } _ => { // Keep reporting some errors even if they're ignored above. self.resolve_path(expr.id, path, 0, ValueNS, true); diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index efae76c5ef4..b0383e355e4 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -440,7 +440,7 @@ fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) { &format!("use of SIMD type `{}` in FFI is highly experimental and \ may result in invalid code", pprust::ty_to_string(ast_ty))); - tcx.sess.span_help(ast_ty.span, + tcx.sess.fileline_help(ast_ty.span, "add #![feature(simd_ffi)] to the crate attributes to enable"); } }; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1e7b90d5a18..aba039a8e9d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -212,18 +212,18 @@ pub fn opt_ast_region_to_region<'tcx>( } } if len == 1 { - span_help!(this.tcx().sess, default_span, + fileline_help!(this.tcx().sess, default_span, "this function's return type contains a borrowed value, but \ the signature does not say which {} it is borrowed from", m); } else if len == 0 { - span_help!(this.tcx().sess, default_span, + fileline_help!(this.tcx().sess, default_span, "this function's return type contains a borrowed value, but \ there is no value for it to be borrowed from"); - span_help!(this.tcx().sess, default_span, + fileline_help!(this.tcx().sess, default_span, "consider giving it a 'static lifetime"); } else { - span_help!(this.tcx().sess, default_span, + fileline_help!(this.tcx().sess, default_span, "this function's return type contains a borrowed value, but \ the signature does not say whether it is borrowed from {}", m); @@ -705,7 +705,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( span_err!(this.tcx().sess, span, E0215, "angle-bracket notation is not stable when \ used with the `Fn` family of traits, use parentheses"); - span_help!(this.tcx().sess, span, + fileline_help!(this.tcx().sess, span, "add `#![feature(unboxed_closures)]` to \ the crate attributes to enable"); } @@ -719,7 +719,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( span_err!(this.tcx().sess, span, E0216, "parenthetical notation is only stable when \ used with the `Fn` family of traits"); - span_help!(this.tcx().sess, span, + fileline_help!(this.tcx().sess, span, "add `#![feature(unboxed_closures)]` to \ the crate attributes to enable"); } @@ -944,14 +944,14 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, pprust::ty_to_string(ty)); match ty.node { ast::TyRptr(None, ref mut_ty) => { - span_help!(this.tcx().sess, ty.span, + fileline_help!(this.tcx().sess, ty.span, "perhaps you meant `&{}({} +{})`? (per RFC 438)", ppaux::mutability_to_string(mut_ty.mutbl), pprust::ty_to_string(&*mut_ty.ty), pprust::bounds_to_string(bounds)); } ast::TyRptr(Some(ref lt), ref mut_ty) => { - span_help!(this.tcx().sess, ty.span, + fileline_help!(this.tcx().sess, ty.span, "perhaps you meant `&{} {}({} +{})`? (per RFC 438)", pprust::lifetime_to_string(lt), ppaux::mutability_to_string(mut_ty.mutbl), @@ -960,7 +960,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, } _ => { - span_help!(this.tcx().sess, ty.span, + fileline_help!(this.tcx().sess, ty.span, "perhaps you forgot parentheses? (per RFC 438)"); } } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index f31dbf5138b..6ba21e25e1f 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -63,7 +63,7 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: span_err!(tcx.sess, span, E0174, "explicit use of unboxed closure method `{}` is experimental", method); - span_help!(tcx.sess, span, + fileline_help!(tcx.sess, span, "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a12ff04912c..48fb12ce833 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3098,7 +3098,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }, expr_t, None); - tcx.sess.span_help(field.span, + tcx.sess.fileline_help(field.span, "maybe a `()` to call it is missing? \ If not, try an anonymous function"); } else { @@ -4480,7 +4480,7 @@ pub fn check_instantiable(tcx: &ty::ctxt, span_err!(tcx.sess, sp, E0073, "this type cannot be instantiated without an \ instance of itself"); - span_help!(tcx.sess, sp, "consider using `Option<{}>`", + fileline_help!(tcx.sess, sp, "consider using `Option<{}>`", ppaux::ty_to_string(tcx, item_ty)); false } else { diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index e024526d001..ee567575106 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -400,7 +400,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { match suggested_marker_id { Some(def_id) => { - self.tcx().sess.span_help( + self.tcx().sess.fileline_help( span, format!("consider removing `{}` or using a marker such as `{}`", param_name.user_string(self.tcx()), diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 58b67d31ab5..9a8545f3dd5 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -524,7 +524,7 @@ fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id: return // everything OK }; span_err!(tcx.sess, sp, E0183, "manual implementations of `{}` are experimental", trait_name); - span_help!(tcx.sess, sp, + fileline_help!(tcx.sess, sp, "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 74fed6cbf39..9e63382acb1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1217,7 +1217,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it.span, "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ which traits can use parenthetical notation"); - span_help!(ccx.tcx.sess, it.span, + fileline_help!(ccx.tcx.sess, it.span, "add `#![feature(unboxed_closures)]` to \ the crate attributes to use it"); } diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index 54689a1f77a..055ade46a3f 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -52,6 +52,13 @@ macro_rules! span_help { }) } +#[macro_export] +macro_rules! fileline_help { + ($session:expr, $span:expr, $($message:tt)*) => ({ + ($session).fileline_help($span, &format!($($message)*)) + }) +} + #[macro_export] macro_rules! register_diagnostics { ($($code:tt),*) => ( diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index f6bdd693cfa..a8c35c1fdb1 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -753,6 +753,10 @@ impl<'a> ExtCtxt<'a> { self.print_backtrace(); self.parse_sess.span_diagnostic.span_help(sp, msg); } + pub fn fileline_help(&self, sp: Span, msg: &str) { + self.print_backtrace(); + self.parse_sess.span_diagnostic.fileline_help(sp, msg); + } pub fn bug(&self, msg: &str) -> ! { self.print_backtrace(); self.parse_sess.span_diagnostic.handler().bug(msg); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index bea57ae14e4..8896a8e0c4f 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -571,7 +571,7 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool fld.cx.span_warn(attr.span, "macro_escape is a deprecated synonym for macro_use"); is_use = true; if let ast::AttrInner = attr.node.style { - fld.cx.span_help(attr.span, "consider an outer attribute, \ + fld.cx.fileline_help(attr.span, "consider an outer attribute, \ #[macro_use] mod ..."); } }; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 18d3f85f4b5..c2ad8554674 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -362,7 +362,7 @@ impl<'a> Context<'a> { pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: &str) { diag.span_err(span, explain); - diag.span_help(span, &format!("add #![feature({})] to the \ + diag.fileline_help(span, &format!("add #![feature({})] to the \ crate attributes to enable", feature)); } @@ -370,7 +370,7 @@ pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain: &str) { diag.span_warn(span, explain); if diag.handler.can_emit_warnings { - diag.span_help(span, &format!("add #![feature({})] to the \ + diag.fileline_help(span, &format!("add #![feature({})] to the \ crate attributes to silence this warning", feature)); } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index a0e2b4dbf5a..db5583cf13a 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -77,7 +77,7 @@ impl<'a> ParserAttr for Parser<'a> { self.span_err(span, "an inner attribute is not permitted in \ this context"); - self.span_help(span, + self.fileline_help(span, "place inner attribute at the top of the module or block"); } ast::AttrInner diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 8d3e93d35dd..72ff501c648 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -781,7 +781,7 @@ impl<'a> StringReader<'a> { self.span_diagnostic .span_warn(sp, "\\U00ABCD12 and \\uABCD escapes are deprecated"); self.span_diagnostic - .span_help(sp, "use \\u{ABCD12} escapes instead"); + .fileline_help(sp, "use \\u{ABCD12} escapes instead"); } /// Scan for a single (possibly escaped) byte or char diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index def5963e6f4..58d58551df3 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -724,7 +724,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> &suf[1..])); } else { sd.span_err(sp, &*format!("illegal suffix `{}` for numeric literal", suf)); - sd.span_help(sp, "the suffix must be one of the integral types \ + sd.fileline_help(sp, "the suffix must be one of the integral types \ (`u32`, `isize`, etc)"); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 88df6d6d4cd..28d757e9be9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -974,7 +974,7 @@ impl<'a> Parser<'a> { } pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> ! { self.span_err(sp, m); - self.span_help(sp, help); + self.fileline_help(sp, help); panic!(diagnostic::FatalError); } pub fn span_note(&self, sp: Span, m: &str) { @@ -983,6 +983,9 @@ impl<'a> Parser<'a> { pub fn span_help(&self, sp: Span, m: &str) { self.sess.span_diagnostic.span_help(sp, m) } + pub fn fileline_help(&self, sp: Span, m: &str) { + self.sess.span_diagnostic.fileline_help(sp, m) + } pub fn bug(&self, m: &str) -> ! { self.sess.span_diagnostic.span_bug(self.span, m) } @@ -2532,7 +2535,7 @@ impl<'a> Parser<'a> { Some(f) => f, None => continue, }; - self.span_help(last_span, + self.fileline_help(last_span, &format!("try parenthesizing the first index; e.g., `(foo.{}){}`", float.trunc() as usize, &float.fract().to_string()[1..])); @@ -2943,7 +2946,7 @@ impl<'a> Parser<'a> { self.span_err(op_span, "chained comparison operators require parentheses"); if op.node == BiLt && outer_op == BiGt { - self.span_help(op_span, + self.fileline_help(op_span, "use `::<...>` instead of `<...>` if you meant to specify type arguments"); } } @@ -4699,7 +4702,7 @@ impl<'a> Parser<'a> { match visa { Public => { self.span_err(span, "can't qualify macro invocation with `pub`"); - self.span_help(span, "try adjusting the macro to put `pub` inside \ + self.fileline_help(span, "try adjusting the macro to put `pub` inside \ the invocation"); } Inherited => (), @@ -5445,7 +5448,7 @@ impl<'a> Parser<'a> { if self.token.is_ident() { self.bump(); } self.span_err(span, "expected `;`, found `as`"); - self.span_help(span, + self.fileline_help(span, &format!("perhaps you meant to enclose the crate name `{}` in \ a string?", the_ident.as_str())); @@ -5756,7 +5759,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::Mut) { let last_span = self.last_span; self.span_err(last_span, "const globals cannot be mutable"); - self.span_help(last_span, "did you mean to declare a static?"); + self.fileline_help(last_span, "did you mean to declare a static?"); } let (ident, item_, extra_attrs) = self.parse_item_const(None); let last_span = self.last_span;