提交 ec28b4a6 编写于 作者: B bors

auto merge of #18132 : P1start/rust/more-help, r=jakub-

Closes #18126.

At the moment this mostly only changes notes that are particularly help-oriented or directly suggest the user to do something to help messages, and does not change messages that simply explain an error message further. If it is decided that those messages should also be help messages, I can add them to this PR, but for now I’m excluding them as I believe that changing those messages might leave very few places where notes would be appropriate.
...@@ -777,7 +777,7 @@ fn add_one(x: int) -> int { ...@@ -777,7 +777,7 @@ fn add_one(x: int) -> int {
x + 1; x + 1;
} }
note: consider removing this semicolon: help: consider removing this semicolon:
x + 1; x + 1;
^ ^
``` ```
......
...@@ -789,7 +789,7 @@ fn check_assignment(&self, ...@@ -789,7 +789,7 @@ fn check_assignment(&self,
assignment_span, assignment_span,
format!("cannot assign to {}", format!("cannot assign to {}",
self.bccx.cmt_to_string(&*assignee_cmt)).as_slice()); self.bccx.cmt_to_string(&*assignee_cmt)).as_slice());
self.bccx.span_note( self.bccx.span_help(
self.tcx().map.span(upvar_id.closure_expr_id), self.tcx().map.span(upvar_id.closure_expr_id),
"consider changing this closure to take self by mutable reference"); "consider changing this closure to take self by mutable reference");
} else { } else {
......
...@@ -148,9 +148,12 @@ fn note_move_destination(bccx: &BorrowckCtxt, ...@@ -148,9 +148,12 @@ fn note_move_destination(bccx: &BorrowckCtxt,
if is_first_note { if is_first_note {
bccx.span_note( bccx.span_note(
move_to_span, move_to_span,
format!("attempting to move value to here (to prevent the move, \ "attempting to move value to here");
bccx.span_help(
move_to_span,
format!("to prevent the move, \
use `ref {0}` or `ref mut {0}` to capture value by \ use `ref {0}` or `ref mut {0}` to capture value by \
reference)", reference",
pat_name).as_slice()); pat_name).as_slice());
} else { } else {
bccx.span_note(move_to_span, bccx.span_note(move_to_span,
......
...@@ -527,8 +527,8 @@ pub fn report_use_of_moved_value(&self, ...@@ -527,8 +527,8 @@ pub fn report_use_of_moved_value(&self,
r).as_slice()) r).as_slice())
} }
}; };
let suggestion = move_suggestion(self.tcx, expr_ty, let (suggestion, _) = move_suggestion(self.tcx, expr_ty,
"moved by default (use `copy` to override)"); ("moved by default", ""));
self.tcx.sess.span_note( self.tcx.sess.span_note(
expr_span, expr_span,
format!("`{}` moved here{} because it has type `{}`, which is {}", format!("`{}` moved here{} because it has type `{}`, which is {}",
...@@ -540,13 +540,15 @@ pub fn report_use_of_moved_value(&self, ...@@ -540,13 +540,15 @@ pub fn report_use_of_moved_value(&self,
move_data::MovePat => { move_data::MovePat => {
let pat_ty = ty::node_id_to_type(self.tcx, the_move.id); let pat_ty = ty::node_id_to_type(self.tcx, the_move.id);
self.tcx.sess.span_note(self.tcx.map.span(the_move.id), let span = self.tcx.map.span(the_move.id);
self.tcx.sess.span_note(span,
format!("`{}` moved here{} because it has type `{}`, \ format!("`{}` moved here{} because it has type `{}`, \
which is moved by default (use `ref` to \ which is moved by default",
override)",
ol, ol,
moved_lp_msg, moved_lp_msg,
pat_ty.user_string(self.tcx)).as_slice()); pat_ty.user_string(self.tcx)).as_slice());
self.tcx.sess.span_help(span,
"use `ref` to override");
} }
move_data::Captured => { move_data::Captured => {
...@@ -563,9 +565,9 @@ pub fn report_use_of_moved_value(&self, ...@@ -563,9 +565,9 @@ pub fn report_use_of_moved_value(&self,
r).as_slice()) r).as_slice())
} }
}; };
let suggestion = move_suggestion(self.tcx, expr_ty, let (suggestion, help) = move_suggestion(self.tcx, expr_ty,
"moved by default (make a copy and \ ("moved by default", "make a copy and \
capture that instead to override)"); capture that instead to override"));
self.tcx.sess.span_note( self.tcx.sess.span_note(
expr_span, expr_span,
format!("`{}` moved into closure environment here{} because it \ format!("`{}` moved into closure environment here{} because it \
...@@ -574,21 +576,23 @@ pub fn report_use_of_moved_value(&self, ...@@ -574,21 +576,23 @@ pub fn report_use_of_moved_value(&self,
moved_lp_msg, moved_lp_msg,
expr_ty.user_string(self.tcx), expr_ty.user_string(self.tcx),
suggestion).as_slice()); suggestion).as_slice());
self.tcx.sess.span_help(expr_span, help);
} }
} }
fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msg: &'static str) fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msgs: (&'static str, &'static str))
-> &'static str { -> (&'static str, &'static str) {
match ty::get(ty).sty { match ty::get(ty).sty {
ty::ty_closure(box ty::ClosureTy { ty::ty_closure(box ty::ClosureTy {
store: ty::RegionTraitStore(..), store: ty::RegionTraitStore(..),
.. ..
}) => }) =>
"a non-copyable stack closure (capture it in a new closure, \ ("a non-copyable stack closure",
e.g. `|x| f(x)`, to override)", "capture it in a new closure, e.g. `|x| f(x)`, to override"),
_ if ty::type_moves_by_default(tcx, ty) => _ if ty::type_moves_by_default(tcx, ty) =>
"non-copyable (perhaps you meant to use clone()?)", ("non-copyable",
_ => default_msg, "perhaps you meant to use `clone()`?"),
_ => default_msgs,
} }
} }
} }
...@@ -733,7 +737,7 @@ pub fn report_aliasability_violation(&self, ...@@ -733,7 +737,7 @@ pub fn report_aliasability_violation(&self,
self.tcx.sess.span_err(span, self.tcx.sess.span_err(span,
format!("{} in a captured outer \ format!("{} in a captured outer \
variable in an `Fn` closure", prefix).as_slice()); variable in an `Fn` closure", prefix).as_slice());
span_note!(self.tcx.sess, self.tcx.map.span(id), span_help!(self.tcx.sess, self.tcx.map.span(id),
"consider changing this closure to take self by mutable reference"); "consider changing this closure to take self by mutable reference");
} }
mc::AliasableStatic(..) | mc::AliasableStatic(..) |
...@@ -750,7 +754,7 @@ pub fn report_aliasability_violation(&self, ...@@ -750,7 +754,7 @@ pub fn report_aliasability_violation(&self,
} }
if is_closure { if is_closure {
self.tcx.sess.span_note( self.tcx.sess.span_help(
span, span,
"closures behind references must be called via `&mut`"); "closures behind references must be called via `&mut`");
} }
...@@ -770,7 +774,7 @@ pub fn note_and_explain_bckerr(&self, err: BckError) { ...@@ -770,7 +774,7 @@ pub fn note_and_explain_bckerr(&self, err: BckError) {
_ => unreachable!() _ => unreachable!()
}; };
if kind == ty::FnUnboxedClosureKind { if kind == ty::FnUnboxedClosureKind {
self.tcx.sess.span_note( self.tcx.sess.span_help(
self.tcx.map.span(upvar_id.closure_expr_id), self.tcx.map.span(upvar_id.closure_expr_id),
"consider changing this closure to take \ "consider changing this closure to take \
self by mutable reference"); self by mutable reference");
...@@ -787,15 +791,20 @@ pub fn note_and_explain_bckerr(&self, err: BckError) { ...@@ -787,15 +791,20 @@ pub fn note_and_explain_bckerr(&self, err: BckError) {
sub_scope, sub_scope,
"..."); "...");
let suggestion = if is_statement_scope(self.tcx, super_scope) { let suggestion = if is_statement_scope(self.tcx, super_scope) {
"; consider using a `let` binding to increase its lifetime" Some("consider using a `let` binding to increase its lifetime")
} else { } else {
"" None
}; };
note_and_explain_region( let span = note_and_explain_region(
self.tcx, self.tcx,
"...but borrowed value is only valid for ", "...but borrowed value is only valid for ",
super_scope, super_scope,
suggestion); "");
match (span, suggestion) {
(_, None) => {},
(Some(span), Some(msg)) => self.tcx.sess.span_help(span, msg),
(None, Some(msg)) => self.tcx.sess.help(msg),
}
} }
err_borrowed_pointer_too_short(loan_scope, ptr_scope) => { err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
......
...@@ -213,7 +213,7 @@ fn add_library(sess: &session::Session, ...@@ -213,7 +213,7 @@ fn add_library(sess: &session::Session,
sess.err(format!("cannot satisfy dependencies so `{}` only \ sess.err(format!("cannot satisfy dependencies so `{}` only \
shows up once", shows up once",
data.name).as_slice()); data.name).as_slice());
sess.note("having upstream crates all available in one format \ sess.help("having upstream crates all available in one format \
will likely make this go away"); will likely make this go away");
} }
} }
......
...@@ -1568,7 +1568,7 @@ fn check_ret(&self, ...@@ -1568,7 +1568,7 @@ fn check_ret(&self,
hi: original_span.hi, hi: original_span.hi,
expn_id: original_span.expn_id expn_id: original_span.expn_id
}; };
self.ir.tcx.sess.span_note( self.ir.tcx.sess.span_help(
span_semicolon, "consider removing this semicolon:"); span_semicolon, "consider removing this semicolon:");
} }
} }
......
...@@ -5868,7 +5868,7 @@ fn resolve_expr(&mut self, expr: &Expr) { ...@@ -5868,7 +5868,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
uses it like a function name", uses it like a function name",
wrong_name).as_slice()); wrong_name).as_slice());
self.session.span_note(expr.span, self.session.span_help(expr.span,
format!("Did you mean to write: \ format!("Did you mean to write: \
`{} {{ /* fields */ }}`?", `{} {{ /* fields */ }}`?",
wrong_name).as_slice()); wrong_name).as_slice());
......
...@@ -172,18 +172,18 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -172,18 +172,18 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
} }
} }
if len == 1 { if len == 1 {
span_note!(this.tcx().sess, default_span, span_help!(this.tcx().sess, default_span,
"this function's return type contains a borrowed value, but \ "this function's return type contains a borrowed value, but \
the signature does not say which {} it is borrowed from", the signature does not say which {} it is borrowed from",
m); m);
} else if len == 0 { } else if len == 0 {
span_note!(this.tcx().sess, default_span, span_help!(this.tcx().sess, default_span,
"this function's return type contains a borrowed value, but \ "this function's return type contains a borrowed value, but \
there is no value for it to be borrowed from"); there is no value for it to be borrowed from");
span_note!(this.tcx().sess, default_span, span_help!(this.tcx().sess, default_span,
"consider giving it a 'static lifetime"); "consider giving it a 'static lifetime");
} else { } else {
span_note!(this.tcx().sess, default_span, span_help!(this.tcx().sess, default_span,
"this function's return type contains a borrowed value, but \ "this function's return type contains a borrowed value, but \
the signature does not say whether it is borrowed from {}", the signature does not say whether it is borrowed from {}",
m); m);
...@@ -302,7 +302,7 @@ fn ast_path_substs<'tcx,AC,RS>( ...@@ -302,7 +302,7 @@ fn ast_path_substs<'tcx,AC,RS>(
&& !this.tcx().sess.features.borrow().default_type_params { && !this.tcx().sess.features.borrow().default_type_params {
span_err!(this.tcx().sess, path.span, E0108, span_err!(this.tcx().sess, path.span, E0108,
"default type parameters are experimental and possibly buggy"); "default type parameters are experimental and possibly buggy");
span_note!(this.tcx().sess, path.span, span_help!(this.tcx().sess, path.span,
"add #![feature(default_type_params)] to the crate attributes to enable"); "add #![feature(default_type_params)] to the crate attributes to enable");
} }
...@@ -1168,6 +1168,7 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>( ...@@ -1168,6 +1168,7 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
let param_lifetimes: Vec<(String, uint)> = lifetimes_for_params.into_iter() let param_lifetimes: Vec<(String, uint)> = lifetimes_for_params.into_iter()
.map(|(n, v)| (n, v.len())) .map(|(n, v)| (n, v.len()))
.filter(|&(_, l)| l != 0)
.collect(); .collect();
let output_ty = match decl.output.node { let output_ty = match decl.output.node {
......
...@@ -1355,18 +1355,18 @@ fn check_cast(fcx: &FnCtxt, ...@@ -1355,18 +1355,18 @@ fn check_cast(fcx: &FnCtxt,
ast::MutImmutable => "" ast::MutImmutable => ""
}; };
if ty::type_is_trait(t_1) { if ty::type_is_trait(t_1) {
span_note!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr); span_help!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
} else { } else {
span_note!(fcx.tcx().sess, span, span_help!(fcx.tcx().sess, span,
"consider using an implicit coercion to `&{}{}` instead", "consider using an implicit coercion to `&{}{}` instead",
mtstr, tstr); mtstr, tstr);
} }
} }
ty::ty_uniq(..) => { ty::ty_uniq(..) => {
span_note!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr); span_help!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
} }
_ => { _ => {
span_note!(fcx.tcx().sess, e.span, span_help!(fcx.tcx().sess, e.span,
"consider using a box or reference as appropriate"); "consider using a box or reference as appropriate");
} }
} }
...@@ -2142,7 +2142,7 @@ fn try_overloaded_call<'a>(fcx: &FnCtxt, ...@@ -2142,7 +2142,7 @@ fn try_overloaded_call<'a>(fcx: &FnCtxt,
if !fcx.tcx().sess.features.borrow().overloaded_calls { if !fcx.tcx().sess.features.borrow().overloaded_calls {
span_err!(fcx.tcx().sess, call_expression.span, E0056, span_err!(fcx.tcx().sess, call_expression.span, E0056,
"overloaded calls are experimental"); "overloaded calls are experimental");
span_note!(fcx.tcx().sess, call_expression.span, span_help!(fcx.tcx().sess, call_expression.span,
"add `#![feature(overloaded_calls)]` to \ "add `#![feature(overloaded_calls)]` to \
the crate attributes to enable"); the crate attributes to enable");
} }
...@@ -3479,8 +3479,9 @@ fn check_field(fcx: &FnCtxt, ...@@ -3479,8 +3479,9 @@ fn check_field(fcx: &FnCtxt,
}, },
expr_t, None); expr_t, None);
tcx.sess.span_note(field.span, tcx.sess.span_help(field.span,
"maybe a missing `()` to call it? If not, try an anonymous function."); "maybe a `()` to call it is missing? \
If not, try an anonymous function");
} }
Err(_) => { Err(_) => {
...@@ -4787,7 +4788,8 @@ pub fn check_instantiable(tcx: &ty::ctxt, ...@@ -4787,7 +4788,8 @@ pub fn check_instantiable(tcx: &ty::ctxt,
if !ty::is_instantiable(tcx, item_ty) { if !ty::is_instantiable(tcx, item_ty) {
span_err!(tcx.sess, sp, E0073, span_err!(tcx.sess, sp, E0073,
"this type cannot be instantiated without an \ "this type cannot be instantiated without an \
instance of itself; consider using `Option<{}>`", instance of itself");
span_help!(tcx.sess, sp, "consider using `Option<{}>`",
ppaux::ty_to_string(tcx, item_ty)); ppaux::ty_to_string(tcx, item_ty));
false false
} else { } else {
......
...@@ -525,7 +525,7 @@ fn note_obligation_cause(fcx: &FnCtxt, ...@@ -525,7 +525,7 @@ fn note_obligation_cause(fcx: &FnCtxt,
span_note!(tcx.sess, obligation.cause.span, span_note!(tcx.sess, obligation.cause.span,
"cannot implement a destructor on a \ "cannot implement a destructor on a \
structure or enumeration that does not satisfy Send"); structure or enumeration that does not satisfy Send");
span_note!(tcx.sess, obligation.cause.span, span_help!(tcx.sess, obligation.cause.span,
"use \"#[unsafe_destructor]\" on the implementation \ "use \"#[unsafe_destructor]\" on the implementation \
to force the compiler to allow this"); to force the compiler to allow this");
} }
......
...@@ -438,9 +438,12 @@ fn report_param_bound_failure(&self, ...@@ -438,9 +438,12 @@ fn report_param_bound_failure(&self,
self.tcx.sess.span_err( self.tcx.sess.span_err(
origin.span(), origin.span(),
format!( format!(
"the parameter type `{}` may not live long enough; \ "the parameter type `{}` may not live long enough",
consider adding an explicit lifetime bound `{}:{}`...", param_ty.user_string(self.tcx)).as_slice());
param_ty.user_string(self.tcx), self.tcx.sess.span_help(
origin.span(),
format!(
"consider adding an explicit lifetime bound `{}: {}`...",
param_ty.user_string(self.tcx), param_ty.user_string(self.tcx),
sub.user_string(self.tcx)).as_slice()); sub.user_string(self.tcx)).as_slice());
} }
...@@ -450,9 +453,12 @@ fn report_param_bound_failure(&self, ...@@ -450,9 +453,12 @@ fn report_param_bound_failure(&self,
self.tcx.sess.span_err( self.tcx.sess.span_err(
origin.span(), origin.span(),
format!( format!(
"the parameter type `{}` may not live long enough; \ "the parameter type `{}` may not live long enough",
consider adding an explicit lifetime bound `{}:'static`...", param_ty.user_string(self.tcx)).as_slice());
param_ty.user_string(self.tcx), self.tcx.sess.span_help(
origin.span(),
format!(
"consider adding an explicit lifetime bound `{}: 'static`...",
param_ty.user_string(self.tcx)).as_slice()); param_ty.user_string(self.tcx)).as_slice());
} }
...@@ -461,9 +467,12 @@ fn report_param_bound_failure(&self, ...@@ -461,9 +467,12 @@ fn report_param_bound_failure(&self,
self.tcx.sess.span_err( self.tcx.sess.span_err(
origin.span(), origin.span(),
format!( format!(
"the parameter type `{}` may not live long enough; \ "the parameter type `{}` may not live long enough",
consider adding an explicit lifetime bound to `{}`", param_ty.user_string(self.tcx)).as_slice());
param_ty.user_string(self.tcx), self.tcx.sess.span_help(
origin.span(),
format!(
"consider adding an explicit lifetime bound to `{}`",
param_ty.user_string(self.tcx)).as_slice()); param_ty.user_string(self.tcx)).as_slice());
note_and_explain_region( note_and_explain_region(
self.tcx, self.tcx,
......
...@@ -48,16 +48,18 @@ pub trait UserString { ...@@ -48,16 +48,18 @@ pub trait UserString {
pub fn note_and_explain_region(cx: &ctxt, pub fn note_and_explain_region(cx: &ctxt,
prefix: &str, prefix: &str,
region: ty::Region, region: ty::Region,
suffix: &str) { suffix: &str) -> Option<Span> {
match explain_region_and_span(cx, region) { match explain_region_and_span(cx, region) {
(ref str, Some(span)) => { (ref str, Some(span)) => {
cx.sess.span_note( cx.sess.span_note(
span, span,
format!("{}{}{}", prefix, *str, suffix).as_slice()); format!("{}{}{}", prefix, *str, suffix).as_slice());
Some(span)
} }
(ref str, None) => { (ref str, None) => {
cx.sess.note( cx.sess.note(
format!("{}{}{}", prefix, *str, suffix).as_slice()); format!("{}{}{}", prefix, *str, suffix).as_slice());
None
} }
} }
} }
......
...@@ -22,10 +22,10 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, ...@@ -22,10 +22,10 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
tts: &[ast::TokenTree]) tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> { -> Box<base::MacResult+'cx> {
cx.span_warn(sp, "`bytes!` is deprecated, use `b\"foo\"` literals instead"); cx.span_warn(sp, "`bytes!` is deprecated, use `b\"foo\"` literals instead");
cx.parse_sess.span_diagnostic.span_note(sp, cx.parse_sess.span_diagnostic.span_help(sp,
"see http://doc.rust-lang.org/reference.html#byte-and-byte-string-literals \ "see http://doc.rust-lang.org/reference.html#byte-and-byte-string-literals \
for documentation"); for documentation");
cx.parse_sess.span_diagnostic.span_note(sp, cx.parse_sess.span_diagnostic.span_help(sp,
"see https://github.com/rust-lang/rust/blob/master/src/etc/2014-06-rewrite-bytes-macros.py \ "see https://github.com/rust-lang/rust/blob/master/src/etc/2014-06-rewrite-bytes-macros.py \
for an automated migration"); for an automated migration");
......
...@@ -131,7 +131,7 @@ impl<'a> Context<'a> { ...@@ -131,7 +131,7 @@ impl<'a> Context<'a> {
fn gate_feature(&self, feature: &str, span: Span, explain: &str) { fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
if !self.has_feature(feature) { if !self.has_feature(feature) {
self.span_handler.span_err(span, explain); self.span_handler.span_err(span, explain);
self.span_handler.span_note(span, format!("add #![feature({})] to the \ self.span_handler.span_help(span, format!("add #![feature({})] to the \
crate attributes to enable", crate attributes to enable",
feature).as_slice()); feature).as_slice());
} }
......
...@@ -2371,10 +2371,19 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P<Expr>) -> P<Expr> { ...@@ -2371,10 +2371,19 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P<Expr>) -> P<Expr> {
token::LitFloat(n) => { token::LitFloat(n) => {
self.bump(); self.bump();
let last_span = self.last_span; let last_span = self.last_span;
let fstr = n.as_str();
self.span_err(last_span, self.span_err(last_span,
format!("unexpected token: `{}`", n.as_str()).as_slice()); format!("unexpected token: `{}`", n.as_str()).as_slice());
self.span_note(last_span, if fstr.chars().all(|x| "0123456789.".contains_char(x)) {
"try parenthesizing the first index; e.g., `(foo.0).1`"); let float = match from_str::<f64>(fstr) {
Some(f) => f,
None => continue,
};
self.span_help(last_span,
format!("try parenthesizing the first index; e.g., `(foo.{}){}`",
float.trunc() as uint,
float.fract().to_string()[1..]).as_slice());
}
self.abort_if_errors(); self.abort_if_errors();
} }
...@@ -2578,7 +2587,7 @@ fn parse_non_delim_tt_tok(p: &mut Parser) -> TokenTree { ...@@ -2578,7 +2587,7 @@ fn parse_non_delim_tt_tok(p: &mut Parser) -> TokenTree {
token::Eof => { token::Eof => {
let open_braces = self.open_braces.clone(); let open_braces = self.open_braces.clone();
for sp in open_braces.iter() { for sp in open_braces.iter() {
self.span_note(*sp, "Did you mean to close this delimiter?"); self.span_help(*sp, "did you mean to close this delimiter?");
} }
// There shouldn't really be a span, but it's easier for the test runner // There shouldn't really be a span, but it's easier for the test runner
// if we give it one // if we give it one
...@@ -5352,8 +5361,8 @@ fn parse_item_or_view_item(&mut self, ...@@ -5352,8 +5361,8 @@ fn parse_item_or_view_item(&mut self,
self.bump(); self.bump();
if self.eat_keyword(keywords::Mut) { if self.eat_keyword(keywords::Mut) {
let last_span = self.last_span; let last_span = self.last_span;
self.span_err(last_span, "const globals cannot be mutable, \ self.span_err(last_span, "const globals cannot be mutable");
did you mean to declare a static?"); self.span_help(last_span, "did you mean to declare a static?");
} }
let (ident, item_, extra_attrs) = self.parse_item_const(None); let (ident, item_, extra_attrs) = self.parse_item_const(None);
let last_span = self.last_span; let last_span = self.last_span;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
fn f() { fn f() {
let x = [1i].iter(); //~ ERROR borrowed value does not live long enough let x = [1i].iter(); //~ ERROR borrowed value does not live long enough
//~^^ NOTE reference must be valid for the block //~^^ NOTE reference must be valid for the block
//~^^ NOTE consider using a `let` binding to increase its lifetime //~^^ HELP consider using a `let` binding to increase its lifetime
} }
fn main() { fn main() {
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
fn blah() -> int { //~ ERROR not all control paths return a value fn blah() -> int { //~ ERROR not all control paths return a value
1i 1i
; //~ NOTE consider removing this semicolon: ; //~ HELP consider removing this semicolon:
} }
fn main() { } fn main() { }
...@@ -15,12 +15,12 @@ fn foo() -> String { //~ ERROR not all control paths return a value ...@@ -15,12 +15,12 @@ fn foo() -> String { //~ ERROR not all control paths return a value
"world") "world")
// Put the trailing semicolon on its own line to test that the // Put the trailing semicolon on its own line to test that the
// note message gets the offending semicolon exactly // note message gets the offending semicolon exactly
; //~ NOTE consider removing this semicolon ; //~ HELP consider removing this semicolon
} }
fn bar() -> String { //~ ERROR not all control paths return a value fn bar() -> String { //~ ERROR not all control paths return a value
"foobar".to_string() "foobar".to_string()
; //~ NOTE consider removing this semicolon ; //~ HELP consider removing this semicolon
} }
pub fn main() {} pub fn main() {}
...@@ -15,8 +15,9 @@ trait ListItem<'a> { ...@@ -15,8 +15,9 @@ trait ListItem<'a> {
trait Collection { fn len(&self) -> uint; } trait Collection { fn len(&self) -> uint; }
struct List<'a, T: ListItem<'a>> { struct List<'a, T: ListItem<'a>> {
//~^ ERROR the parameter type `T` may not live long enough; consider adding an explicit lifetime bo //~^ ERROR the parameter type `T` may not live long enough
//~^^ NOTE ...so that the reference type `&'a [T]` does not outlive the data it points at //~^^ HELP consider adding an explicit lifetime bound
//~^^^ NOTE ...so that the reference type `&'a [T]` does not outlive the data it points at
slice: &'a [T] slice: &'a [T]
} }
......
...@@ -11,14 +11,14 @@ ...@@ -11,14 +11,14 @@
fn main() { fn main() {
let _foo = &[1u, 2] as [uint]; let _foo = &[1u, 2] as [uint];
//~^ ERROR cast to unsized type: `&[uint, ..2]` as `[uint]` //~^ ERROR cast to unsized type: `&[uint, ..2]` as `[uint]`
//~^^ NOTE consider using an implicit coercion to `&[uint]` instead //~^^ HELP consider using an implicit coercion to `&[uint]` instead
let _bar = box 1u as std::fmt::Show; let _bar = box 1u as std::fmt::Show;
//~^ ERROR cast to unsized type: `Box<uint>` as `core::fmt::Show` //~^ ERROR cast to unsized type: `Box<uint>` as `core::fmt::Show`
//~^^ NOTE did you mean `Box<core::fmt::Show>`? //~^^ HELP did you mean `Box<core::fmt::Show>`?
let _baz = 1u as std::fmt::Show; let _baz = 1u as std::fmt::Show;
//~^ ERROR cast to unsized type: `uint` as `core::fmt::Show` //~^ ERROR cast to unsized type: `uint` as `core::fmt::Show`
//~^^ NOTE consider using a box or reference as appropriate //~^^ HELP consider using a box or reference as appropriate
let _quux = [1u, 2] as [uint]; let _quux = [1u, 2] as [uint];
//~^ ERROR cast to unsized type: `[uint, ..2]` as `[uint]` //~^ ERROR cast to unsized type: `[uint, ..2]` as `[uint]`
//~^^ NOTE consider using a box or reference as appropriate //~^^ HELP consider using a box or reference as appropriate
} }
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
// except according to those terms. // except according to those terms.
const const
mut //~ ERROR: const globals cannot be mutable, did you mean to declare a static? mut //~ ERROR: const globals cannot be mutable
//~^ HELP did you mean to declare a static?
FOO: uint = 3; FOO: uint = 3;
fn main() { fn main() {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
fn foo() { //~ NOTE Did you mean to close this delimiter? fn foo() { //~ HELP did you mean to close this delimiter?
match Some(x) { match Some(x) {
Some(y) { panic!(); } Some(y) { panic!(); }
None { panic!(); } None { panic!(); }
......
...@@ -15,5 +15,5 @@ struct Monster { ...@@ -15,5 +15,5 @@ struct Monster {
fn main() { fn main() {
let _m = Monster(); //~ ERROR `Monster` is a structure name, but let _m = Monster(); //~ ERROR `Monster` is a structure name, but
//~^ NOTE Did you mean to write: `Monster { /* fields */ }`? //~^ HELP Did you mean to write: `Monster { /* fields */ }`?
} }
...@@ -10,13 +10,13 @@ ...@@ -10,13 +10,13 @@
// Lifetime annotation needed because we have no arguments. // Lifetime annotation needed because we have no arguments.
fn f() -> &int { //~ ERROR missing lifetime specifier fn f() -> &int { //~ ERROR missing lifetime specifier
//~^ NOTE there is no value for it to be borrowed from //~^ HELP there is no value for it to be borrowed from
panic!() panic!()
} }
// Lifetime annotation needed because we have two by-reference parameters. // Lifetime annotation needed because we have two by-reference parameters.
fn g(_x: &int, _y: &int) -> &int { //~ ERROR missing lifetime specifier fn g(_x: &int, _y: &int) -> &int { //~ ERROR missing lifetime specifier
//~^ NOTE the signature does not say whether it is borrowed from `_x` or `_y` //~^ HELP the signature does not say whether it is borrowed from `_x` or `_y`
panic!() panic!()
} }
...@@ -27,7 +27,13 @@ struct Foo<'a> { ...@@ -27,7 +27,13 @@ struct Foo<'a> {
// Lifetime annotation needed because we have two lifetimes: one as a parameter // Lifetime annotation needed because we have two lifetimes: one as a parameter
// and one on the reference. // and one on the reference.
fn h(_x: &Foo) -> &int { //~ ERROR missing lifetime specifier fn h(_x: &Foo) -> &int { //~ ERROR missing lifetime specifier
//~^ NOTE the signature does not say which one of `_x`'s 2 elided lifetimes it is borrowed from //~^ HELP the signature does not say which one of `_x`'s 2 elided lifetimes it is borrowed from
panic!()
}
fn i(_x: int) -> &int { //~ ERROR missing lifetime specifier
//~^ HELP this function's return type contains a borrowed value
//~^^ HELP consider giving it a 'static lifetime
panic!() panic!()
} }
......
...@@ -14,12 +14,12 @@ ...@@ -14,12 +14,12 @@
macro_rules! test ( () => { fn foo() -> int { 1i; } } ) macro_rules! test ( () => { fn foo() -> int { 1i; } } )
//~^ ERROR not all control paths return a value //~^ ERROR not all control paths return a value
//~^^ NOTE consider removing this semicolon //~^^ HELP consider removing this semicolon
fn no_return() -> int {} //~ ERROR not all control paths return a value fn no_return() -> int {} //~ ERROR not all control paths return a value
fn bar(x: u32) -> u32 { //~ ERROR not all control paths return a value fn bar(x: u32) -> u32 { //~ ERROR not all control paths return a value
x * 2; //~ NOTE consider removing this semicolon x * 2; //~ HELP consider removing this semicolon
} }
fn baz(x: u64) -> u32 { //~ ERROR not all control paths return a value fn baz(x: u64) -> u32 { //~ ERROR not all control paths return a value
......
...@@ -30,7 +30,7 @@ fn main() { ...@@ -30,7 +30,7 @@ fn main() {
let point: Point = Point::new(); let point: Point = Point::new();
let px: int = point let px: int = point
.get_x;//~ ERROR attempted to take value of method `get_x` on type `Point` .get_x;//~ ERROR attempted to take value of method `get_x` on type `Point`
//~^ NOTE maybe a missing `()` to call it? If not, try an anonymous //~^ HELP maybe a `()` to call it is missing
// Ensure the span is useful // Ensure the span is useful
let ys = &[1i,2,3,4,5,6,7]; let ys = &[1i,2,3,4,5,6,7];
...@@ -38,6 +38,6 @@ fn main() { ...@@ -38,6 +38,6 @@ fn main() {
.map(|x| x) .map(|x| x)
.filter(|&&x| x == 1) .filter(|&&x| x == 1)
.filter_map; //~ ERROR attempted to take value of method `filter_map` on type .filter_map; //~ ERROR attempted to take value of method `filter_map` on type
//~^ NOTE maybe a missing `()` to call it? If not, try an anonymous function. //~^ HELP maybe a `()` to call it is missing
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册