rollup merge of #18132 : P1start/more-help

This commit is contained in:
Alex Crichton 2014-11-03 15:28:54 -08:00
commit 59d47a3ca4
26 changed files with 123 additions and 80 deletions

View File

@ -777,7 +777,7 @@ fn add_one(x: int) -> int {
x + 1;
}
note: consider removing this semicolon:
help: consider removing this semicolon:
x + 1;
^
```

View File

@ -789,7 +789,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
assignment_span,
format!("cannot assign to {}",
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),
"consider changing this closure to take self by mutable reference");
} else {

View File

@ -148,9 +148,12 @@ fn note_move_destination(bccx: &BorrowckCtxt,
if is_first_note {
bccx.span_note(
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 \
reference)",
reference",
pat_name).as_slice());
} else {
bccx.span_note(move_to_span,

View File

@ -527,8 +527,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
r).as_slice())
}
};
let suggestion = move_suggestion(self.tcx, expr_ty,
"moved by default (use `copy` to override)");
let (suggestion, _) = move_suggestion(self.tcx, expr_ty,
("moved by default", ""));
self.tcx.sess.span_note(
expr_span,
format!("`{}` moved here{} because it has type `{}`, which is {}",
@ -540,13 +540,15 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
move_data::MovePat => {
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 `{}`, \
which is moved by default (use `ref` to \
override)",
which is moved by default",
ol,
moved_lp_msg,
pat_ty.user_string(self.tcx)).as_slice());
self.tcx.sess.span_help(span,
"use `ref` to override");
}
move_data::Captured => {
@ -563,9 +565,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
r).as_slice())
}
};
let suggestion = move_suggestion(self.tcx, expr_ty,
"moved by default (make a copy and \
capture that instead to override)");
let (suggestion, help) = move_suggestion(self.tcx, expr_ty,
("moved by default", "make a copy and \
capture that instead to override"));
self.tcx.sess.span_note(
expr_span,
format!("`{}` moved into closure environment here{} because it \
@ -574,21 +576,23 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
moved_lp_msg,
expr_ty.user_string(self.tcx),
suggestion).as_slice());
self.tcx.sess.span_help(expr_span, help);
}
}
fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msg: &'static str)
-> &'static str {
fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msgs: (&'static str, &'static str))
-> (&'static str, &'static str) {
match ty::get(ty).sty {
ty::ty_closure(box ty::ClosureTy {
store: ty::RegionTraitStore(..),
..
}) =>
"a non-copyable stack closure (capture it in a new closure, \
e.g. `|x| f(x)`, to override)",
("a non-copyable stack closure",
"capture it in a new closure, e.g. `|x| f(x)`, to override"),
_ if ty::type_moves_by_default(tcx, ty) =>
"non-copyable (perhaps you meant to use clone()?)",
_ => default_msg,
("non-copyable",
"perhaps you meant to use `clone()`?"),
_ => default_msgs,
}
}
}
@ -733,7 +737,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
self.tcx.sess.span_err(span,
format!("{} in a captured outer \
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");
}
mc::AliasableStatic(..) |
@ -750,7 +754,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
if is_closure {
self.tcx.sess.span_note(
self.tcx.sess.span_help(
span,
"closures behind references must be called via `&mut`");
}
@ -770,7 +774,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
_ => unreachable!()
};
if kind == ty::FnUnboxedClosureKind {
self.tcx.sess.span_note(
self.tcx.sess.span_help(
self.tcx.map.span(upvar_id.closure_expr_id),
"consider changing this closure to take \
self by mutable reference");
@ -787,15 +791,20 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
sub_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 {
""
None
};
note_and_explain_region(
let span = note_and_explain_region(
self.tcx,
"...but borrowed value is only valid for ",
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) => {

View File

@ -213,7 +213,7 @@ fn add_library(sess: &session::Session,
sess.err(format!("cannot satisfy dependencies so `{}` only \
shows up once",
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");
}
}

View File

@ -1568,7 +1568,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hi: original_span.hi,
expn_id: original_span.expn_id
};
self.ir.tcx.sess.span_note(
self.ir.tcx.sess.span_help(
span_semicolon, "consider removing this semicolon:");
}
}

View File

@ -5868,7 +5868,7 @@ impl<'a> Resolver<'a> {
uses it like a function name",
wrong_name).as_slice());
self.session.span_note(expr.span,
self.session.span_help(expr.span,
format!("Did you mean to write: \
`{} {{ /* fields */ }}`?",
wrong_name).as_slice());

View File

@ -172,18 +172,18 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
}
}
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 \
the signature does not say which {} it is borrowed from",
m);
} 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 \
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");
} 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 \
the signature does not say whether it is borrowed from {}",
m);
@ -302,7 +302,7 @@ fn ast_path_substs<'tcx,AC,RS>(
&& !this.tcx().sess.features.borrow().default_type_params {
span_err!(this.tcx().sess, path.span, E0108,
"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");
}
@ -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()
.map(|(n, v)| (n, v.len()))
.filter(|&(_, l)| l != 0)
.collect();
let output_ty = match decl.output.node {

View File

@ -1355,18 +1355,18 @@ fn check_cast(fcx: &FnCtxt,
ast::MutImmutable => ""
};
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 {
span_note!(fcx.tcx().sess, span,
span_help!(fcx.tcx().sess, span,
"consider using an implicit coercion to `&{}{}` instead",
mtstr, tstr);
}
}
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");
}
}
@ -2142,7 +2142,7 @@ fn try_overloaded_call<'a>(fcx: &FnCtxt,
if !fcx.tcx().sess.features.borrow().overloaded_calls {
span_err!(fcx.tcx().sess, call_expression.span, E0056,
"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 \
the crate attributes to enable");
}
@ -3479,8 +3479,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
},
expr_t, None);
tcx.sess.span_note(field.span,
"maybe a missing `()` to call it? If not, try an anonymous function.");
tcx.sess.span_help(field.span,
"maybe a `()` to call it is missing? \
If not, try an anonymous function");
}
Err(_) => {
@ -4787,7 +4788,8 @@ pub fn check_instantiable(tcx: &ty::ctxt,
if !ty::is_instantiable(tcx, item_ty) {
span_err!(tcx.sess, sp, E0073,
"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));
false
} else {

View File

@ -525,7 +525,7 @@ fn note_obligation_cause(fcx: &FnCtxt,
span_note!(tcx.sess, obligation.cause.span,
"cannot implement a destructor on a \
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 \
to force the compiler to allow this");
}

View File

@ -438,9 +438,12 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> {
self.tcx.sess.span_err(
origin.span(),
format!(
"the parameter type `{}` may not live long enough; \
consider adding an explicit lifetime bound `{}:{}`...",
param_ty.user_string(self.tcx),
"the parameter type `{}` may not live long enough",
param_ty.user_string(self.tcx)).as_slice());
self.tcx.sess.span_help(
origin.span(),
format!(
"consider adding an explicit lifetime bound `{}: {}`...",
param_ty.user_string(self.tcx),
sub.user_string(self.tcx)).as_slice());
}
@ -450,9 +453,12 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> {
self.tcx.sess.span_err(
origin.span(),
format!(
"the parameter type `{}` may not live long enough; \
consider adding an explicit lifetime bound `{}:'static`...",
param_ty.user_string(self.tcx),
"the parameter type `{}` may not live long enough",
param_ty.user_string(self.tcx)).as_slice());
self.tcx.sess.span_help(
origin.span(),
format!(
"consider adding an explicit lifetime bound `{}: 'static`...",
param_ty.user_string(self.tcx)).as_slice());
}
@ -461,9 +467,12 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> {
self.tcx.sess.span_err(
origin.span(),
format!(
"the parameter type `{}` may not live long enough; \
consider adding an explicit lifetime bound to `{}`",
param_ty.user_string(self.tcx),
"the parameter type `{}` may not live long enough",
param_ty.user_string(self.tcx)).as_slice());
self.tcx.sess.span_help(
origin.span(),
format!(
"consider adding an explicit lifetime bound to `{}`",
param_ty.user_string(self.tcx)).as_slice());
note_and_explain_region(
self.tcx,

View File

@ -48,16 +48,18 @@ pub trait UserString {
pub fn note_and_explain_region(cx: &ctxt,
prefix: &str,
region: ty::Region,
suffix: &str) {
suffix: &str) -> Option<Span> {
match explain_region_and_span(cx, region) {
(ref str, Some(span)) => {
cx.sess.span_note(
span,
format!("{}{}{}", prefix, *str, suffix).as_slice());
Some(span)
}
(ref str, None) => {
cx.sess.note(
format!("{}{}{}", prefix, *str, suffix).as_slice());
None
}
}
}

View File

@ -22,10 +22,10 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
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 \
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 \
for an automated migration");

View File

@ -131,7 +131,7 @@ impl<'a> Context<'a> {
fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
if !self.has_feature(feature) {
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",
feature).as_slice());
}

View File

@ -2371,10 +2371,19 @@ impl<'a> Parser<'a> {
token::LitFloat(n) => {
self.bump();
let last_span = self.last_span;
let fstr = n.as_str();
self.span_err(last_span,
format!("unexpected token: `{}`", n.as_str()).as_slice());
self.span_note(last_span,
"try parenthesizing the first index; e.g., `(foo.0).1`");
if fstr.chars().all(|x| "0123456789.".contains_char(x)) {
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();
}
@ -2578,7 +2587,7 @@ impl<'a> Parser<'a> {
token::Eof => {
let open_braces = self.open_braces.clone();
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
// if we give it one
@ -5352,8 +5361,8 @@ impl<'a> Parser<'a> {
self.bump();
if self.eat_keyword(keywords::Mut) {
let last_span = self.last_span;
self.span_err(last_span, "const globals cannot be mutable, \
did you mean to declare a static?");
self.span_err(last_span, "const globals cannot be mutable");
self.span_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;

View File

@ -11,7 +11,7 @@
fn f() {
let x = [1i].iter(); //~ ERROR borrowed value does not live long enough
//~^^ 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() {

View File

@ -11,7 +11,7 @@
fn blah() -> int { //~ ERROR not all control paths return a value
1i
; //~ NOTE consider removing this semicolon:
; //~ HELP consider removing this semicolon:
}
fn main() { }

View File

@ -15,12 +15,12 @@ fn foo() -> String { //~ ERROR not all control paths return a value
"world")
// Put the trailing semicolon on its own line to test that the
// 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
"foobar".to_string()
; //~ NOTE consider removing this semicolon
; //~ HELP consider removing this semicolon
}
pub fn main() {}

View File

@ -15,8 +15,9 @@ trait ListItem<'a> {
trait Collection { fn len(&self) -> uint; }
struct List<'a, T: ListItem<'a>> {
//~^ ERROR the parameter type `T` may not live long enough; consider adding an explicit lifetime bo
//~^^ NOTE ...so that the reference type `&'a [T]` does not outlive the data it points at
//~^ ERROR the parameter type `T` may not live long enough
//~^^ 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]
}

View File

@ -11,14 +11,14 @@
fn main() {
let _foo = &[1u, 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;
//~^ 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;
//~^ 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];
//~^ 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
}

View File

@ -9,7 +9,8 @@
// except according to those terms.
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;
fn main() {

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// 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) {
Some(y) { panic!(); }
None { panic!(); }

View File

@ -15,5 +15,5 @@ struct Monster {
fn main() {
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 */ }`?
}

View File

@ -10,13 +10,13 @@
// Lifetime annotation needed because we have no arguments.
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!()
}
// Lifetime annotation needed because we have two by-reference parameters.
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!()
}
@ -27,7 +27,13 @@ struct Foo<'a> {
// Lifetime annotation needed because we have two lifetimes: one as a parameter
// and one on the reference.
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!()
}

View File

@ -14,12 +14,12 @@
macro_rules! test ( () => { fn foo() -> int { 1i; } } )
//~^ 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 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

View File

@ -30,7 +30,7 @@ fn main() {
let point: Point = Point::new();
let px: int = 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
let ys = &[1i,2,3,4,5,6,7];
@ -38,6 +38,6 @@ fn main() {
.map(|x| x)
.filter(|&&x| x == 1)
.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
}