mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Auto merge of #33619 - jonathandturner:improve_structured_errors, r=nikomatsakis
Batch of improvements to errors for new error format This is a batch of improvements to existing errors to help get the most out of the new error format. * Added labels to primary spans (^^^) for a set of errors that didn't currently have them * Highlight the source blue under the secondary notes for better readability * Move some of the "Note:" into secondary spans+labels * Fix span_label to take &mut instead, which makes it work the same as other methods in that set
This commit is contained in:
commit
5ebe41835f
@ -482,10 +482,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
trace.origin);
|
||||
|
||||
if !is_simple_error {
|
||||
err = err.note_expected_found(&"type", &expected, &found);
|
||||
err.note_expected_found(&"type", &expected, &found);
|
||||
}
|
||||
|
||||
err = err.span_label(trace.origin.span(), &terr);
|
||||
err.span_label(trace.origin.span(), &terr);
|
||||
|
||||
self.check_and_note_conflicting_crates(&mut err, terr, trace.origin.span());
|
||||
|
||||
|
@ -475,99 +475,104 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||
|
||||
let mut err = match (new_loan.kind, old_loan.kind) {
|
||||
(ty::MutBorrow, ty::MutBorrow) => {
|
||||
struct_span_err!(self.bccx, new_loan.span, E0499,
|
||||
"cannot borrow `{}`{} as mutable \
|
||||
more than once at a time",
|
||||
nl, new_loan_msg)
|
||||
.span_label(
|
||||
let mut err = struct_span_err!(self.bccx, new_loan.span, E0499,
|
||||
"cannot borrow `{}`{} as mutable \
|
||||
more than once at a time",
|
||||
nl, new_loan_msg);
|
||||
err.span_label(
|
||||
old_loan.span,
|
||||
&format!("first mutable borrow occurs here{}", old_loan_msg))
|
||||
.span_label(
|
||||
&format!("first mutable borrow occurs here{}", old_loan_msg));
|
||||
err.span_label(
|
||||
new_loan.span,
|
||||
&format!("second mutable borrow occurs here{}", new_loan_msg))
|
||||
.span_label(
|
||||
&format!("second mutable borrow occurs here{}", new_loan_msg));
|
||||
err.span_label(
|
||||
previous_end_span,
|
||||
&format!("first borrow ends here"))
|
||||
&format!("first borrow ends here"));
|
||||
err
|
||||
}
|
||||
|
||||
(ty::UniqueImmBorrow, ty::UniqueImmBorrow) => {
|
||||
struct_span_err!(self.bccx, new_loan.span, E0524,
|
||||
let mut err = struct_span_err!(self.bccx, new_loan.span, E0524,
|
||||
"two closures require unique access to `{}` \
|
||||
at the same time",
|
||||
nl)
|
||||
.span_label(
|
||||
nl);
|
||||
err.span_label(
|
||||
old_loan.span,
|
||||
&format!("first closure is constructed here"))
|
||||
.span_label(
|
||||
&format!("first closure is constructed here"));
|
||||
err.span_label(
|
||||
new_loan.span,
|
||||
&format!("second closure is constructed here"))
|
||||
.span_label(
|
||||
&format!("second closure is constructed here"));
|
||||
err.span_label(
|
||||
previous_end_span,
|
||||
&format!("borrow from first closure ends here"))
|
||||
&format!("borrow from first closure ends here"));
|
||||
err
|
||||
}
|
||||
|
||||
(ty::UniqueImmBorrow, _) => {
|
||||
struct_span_err!(self.bccx, new_loan.span, E0500,
|
||||
"closure requires unique access to `{}` \
|
||||
but {} is already borrowed{}",
|
||||
nl, ol_pronoun, old_loan_msg)
|
||||
.span_label(
|
||||
let mut err = struct_span_err!(self.bccx, new_loan.span, E0500,
|
||||
"closure requires unique access to `{}` \
|
||||
but {} is already borrowed{}",
|
||||
nl, ol_pronoun, old_loan_msg);
|
||||
err.span_label(
|
||||
new_loan.span,
|
||||
&format!("closure construction occurs here{}", new_loan_msg))
|
||||
.span_label(
|
||||
&format!("closure construction occurs here{}", new_loan_msg));
|
||||
err.span_label(
|
||||
old_loan.span,
|
||||
&format!("borrow occurs here{}", old_loan_msg))
|
||||
.span_label(
|
||||
&format!("borrow occurs here{}", old_loan_msg));
|
||||
err.span_label(
|
||||
previous_end_span,
|
||||
&format!("borrow ends here"))
|
||||
&format!("borrow ends here"));
|
||||
err
|
||||
}
|
||||
|
||||
(_, ty::UniqueImmBorrow) => {
|
||||
struct_span_err!(self.bccx, new_loan.span, E0501,
|
||||
"cannot borrow `{}`{} as {} because \
|
||||
previous closure requires unique access",
|
||||
nl, new_loan_msg, new_loan.kind.to_user_str())
|
||||
.span_label(
|
||||
let mut err = struct_span_err!(self.bccx, new_loan.span, E0501,
|
||||
"cannot borrow `{}`{} as {} because \
|
||||
previous closure requires unique access",
|
||||
nl, new_loan_msg, new_loan.kind.to_user_str());
|
||||
err.span_label(
|
||||
new_loan.span,
|
||||
&format!("borrow occurs here{}", new_loan_msg))
|
||||
.span_label(
|
||||
&format!("borrow occurs here{}", new_loan_msg));
|
||||
err.span_label(
|
||||
old_loan.span,
|
||||
&format!("closure construction occurs here{}", old_loan_msg))
|
||||
.span_label(
|
||||
&format!("closure construction occurs here{}", old_loan_msg));
|
||||
err.span_label(
|
||||
previous_end_span,
|
||||
&format!("borrow from closure ends here"))
|
||||
&format!("borrow from closure ends here"));
|
||||
err
|
||||
}
|
||||
|
||||
(_, _) => {
|
||||
struct_span_err!(self.bccx, new_loan.span, E0502,
|
||||
"cannot borrow `{}`{} as {} because \
|
||||
{} is also borrowed as {}{}",
|
||||
nl,
|
||||
new_loan_msg,
|
||||
new_loan.kind.to_user_str(),
|
||||
ol_pronoun,
|
||||
old_loan.kind.to_user_str(),
|
||||
old_loan_msg)
|
||||
.span_label(
|
||||
let mut err = struct_span_err!(self.bccx, new_loan.span, E0502,
|
||||
"cannot borrow `{}`{} as {} because \
|
||||
{} is also borrowed as {}{}",
|
||||
nl,
|
||||
new_loan_msg,
|
||||
new_loan.kind.to_user_str(),
|
||||
ol_pronoun,
|
||||
old_loan.kind.to_user_str(),
|
||||
old_loan_msg);
|
||||
err.span_label(
|
||||
new_loan.span,
|
||||
&format!("{} borrow occurs here{}",
|
||||
new_loan.kind.to_user_str(),
|
||||
new_loan_msg))
|
||||
.span_label(
|
||||
new_loan_msg));
|
||||
err.span_label(
|
||||
old_loan.span,
|
||||
&format!("{} borrow occurs here{}",
|
||||
old_loan.kind.to_user_str(),
|
||||
old_loan_msg))
|
||||
.span_label(
|
||||
old_loan_msg));
|
||||
err.span_label(
|
||||
previous_end_span,
|
||||
&format!("{} borrow ends here",
|
||||
old_loan.kind.to_user_str()))
|
||||
old_loan.kind.to_user_str()));
|
||||
err
|
||||
}
|
||||
};
|
||||
|
||||
match new_loan.cause {
|
||||
euv::ClosureCapture(span) => {
|
||||
err = err.span_label(
|
||||
err.span_label(
|
||||
span,
|
||||
&format!("borrow occurs due to use of `{}` in closure", nl));
|
||||
}
|
||||
@ -576,7 +581,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||
|
||||
match old_loan.cause {
|
||||
euv::ClosureCapture(span) => {
|
||||
err = err.span_label(
|
||||
err.span_label(
|
||||
span,
|
||||
&format!("previous borrow occurs due to use of `{}` in closure",
|
||||
ol));
|
||||
@ -663,23 +668,41 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||
UseOk => { }
|
||||
UseWhileBorrowed(loan_path, loan_span) => {
|
||||
let mut err = match move_kind {
|
||||
move_data::Captured =>
|
||||
struct_span_err!(self.bccx, span, E0504,
|
||||
move_data::Captured => {
|
||||
let mut err = struct_span_err!(self.bccx, span, E0504,
|
||||
"cannot move `{}` into closure because it is borrowed",
|
||||
&self.bccx.loan_path_to_string(move_path)),
|
||||
&self.bccx.loan_path_to_string(move_path));
|
||||
err.span_label(
|
||||
loan_span,
|
||||
&format!("borrow of `{}` occurs here",
|
||||
&self.bccx.loan_path_to_string(&loan_path))
|
||||
);
|
||||
err.span_label(
|
||||
span,
|
||||
&format!("move into closure occurs here")
|
||||
);
|
||||
err
|
||||
}
|
||||
move_data::Declared |
|
||||
move_data::MoveExpr |
|
||||
move_data::MovePat =>
|
||||
struct_span_err!(self.bccx, span, E0505,
|
||||
move_data::MovePat => {
|
||||
let mut err = struct_span_err!(self.bccx, span, E0505,
|
||||
"cannot move out of `{}` because it is borrowed",
|
||||
&self.bccx.loan_path_to_string(move_path))
|
||||
&self.bccx.loan_path_to_string(move_path));
|
||||
err.span_label(
|
||||
loan_span,
|
||||
&format!("borrow of `{}` occurs here",
|
||||
&self.bccx.loan_path_to_string(&loan_path))
|
||||
);
|
||||
err.span_label(
|
||||
span,
|
||||
&format!("move out of `{}` occurs here",
|
||||
&self.bccx.loan_path_to_string(move_path))
|
||||
);
|
||||
err
|
||||
}
|
||||
};
|
||||
|
||||
err.span_note(
|
||||
loan_span,
|
||||
&format!("borrow of `{}` occurs here",
|
||||
&self.bccx.loan_path_to_string(&loan_path))
|
||||
);
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
@ -845,9 +868,12 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||
struct_span_err!(self.bccx, span, E0506,
|
||||
"cannot assign to `{}` because it is borrowed",
|
||||
self.bccx.loan_path_to_string(loan_path))
|
||||
.span_note(loan.span,
|
||||
.span_label(loan.span,
|
||||
&format!("borrow of `{}` occurs here",
|
||||
self.bccx.loan_path_to_string(loan_path)))
|
||||
.span_label(span,
|
||||
&format!("assignment to `{}` occurs here",
|
||||
self.bccx.loan_path_to_string(loan_path)))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
let mut err = report_cannot_move_out_of(bccx, error.move_from.clone());
|
||||
let mut is_first_note = true;
|
||||
for move_to in &error.move_to_places {
|
||||
note_move_destination(&mut err, move_to.span,
|
||||
err = note_move_destination(err, move_to.span,
|
||||
move_to.name, is_first_note);
|
||||
is_first_note = false;
|
||||
}
|
||||
@ -121,18 +121,25 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
Categorization::Deref(_, _, mc::Implicit(..)) |
|
||||
Categorization::Deref(_, _, mc::UnsafePtr(..)) |
|
||||
Categorization::StaticItem => {
|
||||
struct_span_err!(bccx, move_from.span, E0507,
|
||||
let mut err = struct_span_err!(bccx, move_from.span, E0507,
|
||||
"cannot move out of {}",
|
||||
move_from.descriptive_string(bccx.tcx))
|
||||
move_from.descriptive_string(bccx.tcx));
|
||||
err.span_label(
|
||||
move_from.span,
|
||||
&format!("move occurs here")
|
||||
);
|
||||
err
|
||||
}
|
||||
|
||||
Categorization::Interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
|
||||
let expr = bccx.tcx.map.expect_expr(move_from.id);
|
||||
if let hir::ExprIndex(..) = expr.node {
|
||||
struct_span_err!(bccx, move_from.span, E0508,
|
||||
"cannot move out of type `{}`, \
|
||||
a non-copy fixed-size array",
|
||||
b.ty)
|
||||
let mut err = struct_span_err!(bccx, move_from.span, E0508,
|
||||
"cannot move out of type `{}`, \
|
||||
a non-copy fixed-size array",
|
||||
b.ty);
|
||||
err.span_label(move_from.span, &format!("can not move out of here"));
|
||||
err
|
||||
} else {
|
||||
span_bug!(move_from.span, "this path should not cause illegal move");
|
||||
}
|
||||
@ -143,10 +150,12 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
match b.ty.sty {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyEnum(def, _) if def.has_dtor() => {
|
||||
struct_span_err!(bccx, move_from.span, E0509,
|
||||
"cannot move out of type `{}`, \
|
||||
which defines the `Drop` trait",
|
||||
b.ty)
|
||||
let mut err = struct_span_err!(bccx, move_from.span, E0509,
|
||||
"cannot move out of type `{}`, \
|
||||
which defines the `Drop` trait",
|
||||
b.ty);
|
||||
err.span_label(move_from.span, &format!("can not move out of here"));
|
||||
err
|
||||
},
|
||||
_ => {
|
||||
span_bug!(move_from.span, "this path should not cause illegal move");
|
||||
@ -159,22 +168,24 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn note_move_destination(err: &mut DiagnosticBuilder,
|
||||
fn note_move_destination(mut err: DiagnosticBuilder,
|
||||
move_to_span: codemap::Span,
|
||||
pat_name: ast::Name,
|
||||
is_first_note: bool) {
|
||||
is_first_note: bool) -> DiagnosticBuilder {
|
||||
if is_first_note {
|
||||
err.span_note(
|
||||
err.span_label(
|
||||
move_to_span,
|
||||
"attempting to move value to here");
|
||||
&format!("attempting to move value to here"));
|
||||
err.help(
|
||||
&format!("to prevent the move, \
|
||||
use `ref {0}` or `ref mut {0}` to capture value by \
|
||||
reference",
|
||||
pat_name));
|
||||
err
|
||||
} else {
|
||||
err.span_note(move_to_span,
|
||||
&format!("and here (use `ref {0}` or `ref mut {0}`)",
|
||||
pat_name));
|
||||
err
|
||||
}
|
||||
}
|
||||
|
@ -620,10 +620,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// General fallback.
|
||||
let span = err.span.clone();
|
||||
let mut db = self.struct_span_err(
|
||||
err.span,
|
||||
&self.bckerr_to_string(&err));
|
||||
self.note_and_explain_bckerr(&mut db, err);
|
||||
self.note_and_explain_bckerr(&mut db, err, span);
|
||||
db.emit();
|
||||
}
|
||||
|
||||
@ -647,7 +648,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
self.tcx.sess, use_span, E0381,
|
||||
"{} of possibly uninitialized variable: `{}`",
|
||||
verb,
|
||||
self.loan_path_to_string(lp)).emit();
|
||||
self.loan_path_to_string(lp))
|
||||
.span_label(use_span, &format!("use of possibly uninitialized `{}`",
|
||||
self.loan_path_to_string(lp)))
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
@ -716,10 +720,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
err.span_label(
|
||||
use_span,
|
||||
&format!("value moved{} here in previous iteration of loop",
|
||||
move_note))
|
||||
move_note));
|
||||
err
|
||||
} else {
|
||||
err.span_label(use_span, &format!("value {} here after move", verb_participle))
|
||||
.span_label(move_span, &format!("value moved{} here", move_note))
|
||||
.span_label(move_span, &format!("value moved{} here", move_note));
|
||||
err
|
||||
};
|
||||
|
||||
err.note(&format!("move occurs because `{}` has type `{}`, \
|
||||
@ -946,7 +952,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
.emit();
|
||||
}
|
||||
|
||||
pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>) {
|
||||
pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>,
|
||||
error_span: Span) {
|
||||
let code = err.code;
|
||||
match code {
|
||||
err_mutbl => {
|
||||
@ -971,13 +978,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
let span = self.tcx.map.span(local_id);
|
||||
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
|
||||
if snippet != "self" {
|
||||
db.span_suggestion(
|
||||
span,
|
||||
&format!("to make the {} mutable, use `mut` as shown:",
|
||||
self.cmt_to_string(&err.cmt)),
|
||||
format!("mut {}", snippet));
|
||||
db.span_label(span,
|
||||
&format!("use `mut {}` here to make mutable", snippet));
|
||||
}
|
||||
}
|
||||
db.span_label(error_span, &format!("cannot borrow mutably"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -995,6 +1000,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
super_scope,
|
||||
"");
|
||||
if let Some(span) = statement_scope_span(self.tcx, super_scope) {
|
||||
db.span_label(error_span, &format!("does not live long enough"));
|
||||
db.span_help(span,
|
||||
"consider using a `let` binding to increase its lifetime");
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ enum ResolutionError<'a> {
|
||||
SelfUsedOutsideImplOrTrait,
|
||||
/// error E0412: use of undeclared
|
||||
UseOfUndeclared(&'a str, &'a str, SuggestedCandidates),
|
||||
/// error E0413: declaration shadows an enum variant or unit-like struct in scope
|
||||
/// error E0413: cannot be named the same as an enum variant or unit-like struct in scope
|
||||
DeclarationShadowsEnumVariantOrUnitLikeStruct(Name),
|
||||
/// error E0414: only irrefutable patterns allowed here
|
||||
ConstantForIrrefutableBinding(Name),
|
||||
@ -200,11 +200,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
||||
|
||||
match resolution_error {
|
||||
ResolutionError::TypeParametersFromOuterFunction => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0401,
|
||||
"can't use type parameters from outer function; try using a local \
|
||||
type parameter instead")
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0401,
|
||||
"can't use type parameters from outer function; \
|
||||
try using a local type parameter instead");
|
||||
err.span_label(span, &format!("use of type variable from outer function"));
|
||||
err
|
||||
}
|
||||
ResolutionError::OuterTypeParameterContext => {
|
||||
struct_span_err!(resolver.session,
|
||||
@ -230,6 +232,7 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
||||
"trait `{}` is not in scope",
|
||||
name);
|
||||
show_candidates(&mut err, &candidates);
|
||||
err.span_label(span, &format!("`{}` is not in scope", name));
|
||||
err
|
||||
}
|
||||
ResolutionError::UndeclaredAssociatedType => {
|
||||
@ -278,10 +281,12 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
||||
pattern_number)
|
||||
}
|
||||
ResolutionError::SelfUsedOutsideImplOrTrait => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0411,
|
||||
"use of `Self` outside of an impl or trait")
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0411,
|
||||
"use of `Self` outside of an impl or trait");
|
||||
err.span_label(span, &format!("used outside of impl or trait"));
|
||||
err
|
||||
}
|
||||
ResolutionError::UseOfUndeclared(kind, name, candidates) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
@ -291,44 +296,52 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
||||
kind,
|
||||
name);
|
||||
show_candidates(&mut err, &candidates);
|
||||
err.span_label(span, &format!("undefined or not in scope"));
|
||||
err
|
||||
}
|
||||
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0413,
|
||||
"declaration of `{}` shadows an enum variant \
|
||||
"`{}` cannot be named the same as an enum variant \
|
||||
or unit-like struct in scope",
|
||||
name)
|
||||
name);
|
||||
err.span_label(span,
|
||||
&format!("has same name as enum variant or unit-like struct"));
|
||||
err
|
||||
}
|
||||
ResolutionError::ConstantForIrrefutableBinding(name) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0414,
|
||||
"variable bindings cannot shadow constants");
|
||||
err.span_note(span,
|
||||
"there already is a constant in scope sharing the same \
|
||||
name as this pattern");
|
||||
"let variables cannot be named the same as const variables");
|
||||
err.span_label(span,
|
||||
&format!("cannot be named the same as a const variable"));
|
||||
if let Some(binding) = resolver.current_module
|
||||
.resolve_name_in_lexical_scope(name, ValueNS) {
|
||||
let participle = if binding.is_import() { "imported" } else { "defined" };
|
||||
err.span_note(binding.span, &format!("constant {} here", participle));
|
||||
err.span_label(binding.span, &format!("a constant `{}` is {} here",
|
||||
name, participle));
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
|
||||
struct_span_err!(resolver.session,
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0415,
|
||||
"identifier `{}` is bound more than once in this parameter list",
|
||||
identifier)
|
||||
identifier);
|
||||
err.span_label(span, &format!("used as parameter more than once"));
|
||||
err
|
||||
}
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
|
||||
struct_span_err!(resolver.session,
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0416,
|
||||
"identifier `{}` is bound more than once in the same pattern",
|
||||
identifier)
|
||||
identifier);
|
||||
err.span_label(span, &format!("used in a pattern more than once"));
|
||||
err
|
||||
}
|
||||
ResolutionError::StaticVariableReference(binding) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
@ -336,9 +349,10 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
||||
E0417,
|
||||
"static variables cannot be referenced in a \
|
||||
pattern, use a `const` instead");
|
||||
err.span_label(span, &format!("static variable used in pattern"));
|
||||
if binding.span != codemap::DUMMY_SP {
|
||||
let participle = if binding.is_import() { "imported" } else { "defined" };
|
||||
err.span_note(binding.span, &format!("static variable {} here", participle));
|
||||
err.span_label(binding.span, &format!("static variable {} here", participle));
|
||||
}
|
||||
err
|
||||
}
|
||||
@ -1804,7 +1818,9 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
// If it's a typedef, give a note
|
||||
if let Def::TyAlias(..) = path_res.base_def {
|
||||
err.note("`type` aliases cannot be used for traits");
|
||||
let trait_name = trait_path.segments.last().unwrap().identifier.name;
|
||||
err.span_label(trait_path.span,
|
||||
&format!("`{}` is not a trait", trait_name));
|
||||
|
||||
let definition_site = {
|
||||
let segments = &trait_path.segments;
|
||||
@ -1816,7 +1832,8 @@ impl<'a> Resolver<'a> {
|
||||
};
|
||||
|
||||
if definition_site != codemap::DUMMY_SP {
|
||||
err.span_note(definition_site, "type defined here");
|
||||
err.span_label(definition_site,
|
||||
&format!("type aliases cannot be used for traits"));
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
@ -3462,12 +3479,16 @@ impl<'a> Resolver<'a> {
|
||||
_ => match (old_binding.is_import(), binding.is_import()) {
|
||||
(false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
|
||||
(true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
|
||||
_ => struct_span_err!(self.session, span, E0255, "{}", msg),
|
||||
_ => {
|
||||
let mut e = struct_span_err!(self.session, span, E0255, "{}", msg);
|
||||
e.span_label(span, &format!("`{}` was already imported", name));
|
||||
e
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if old_binding.span != codemap::DUMMY_SP {
|
||||
err.span_note(old_binding.span, &format!("previous {} of `{}` here", noun, name));
|
||||
err.span_label(old_binding.span, &format!("previous {} of `{}` here", noun, name));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
@ -202,8 +202,8 @@ pub fn emit_type_err<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
terr: &ty::error::TypeError<'tcx>,
|
||||
msg: &str) {
|
||||
let mut err = struct_span_err!(tcx.sess, span, E0211, "{}", msg);
|
||||
err = err.span_label(span, &terr);
|
||||
err = err.note_expected_found(&"type", &expected_ty, &found_ty);
|
||||
err.span_label(span, &terr);
|
||||
err.note_expected_found(&"type", &expected_ty, &found_ty);
|
||||
tcx.note_and_explain_type_err(&mut err, terr, span);
|
||||
err.emit();
|
||||
}
|
||||
|
@ -235,17 +235,17 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||
/// all, and you just supplied a `Span` to create the diagnostic,
|
||||
/// then the snippet will just include that `Span`, which is
|
||||
/// called the primary span.
|
||||
pub fn span_label(mut self, span: Span, label: &fmt::Display)
|
||||
-> DiagnosticBuilder<'a> {
|
||||
pub fn span_label(&mut self, span: Span, label: &fmt::Display)
|
||||
-> &mut DiagnosticBuilder<'a> {
|
||||
self.span.push_span_label(span, format!("{}", label));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn note_expected_found(mut self,
|
||||
pub fn note_expected_found(&mut self,
|
||||
label: &fmt::Display,
|
||||
expected: &fmt::Display,
|
||||
found: &fmt::Display)
|
||||
-> DiagnosticBuilder<'a>
|
||||
-> &mut DiagnosticBuilder<'a>
|
||||
{
|
||||
// For now, just attach these as notes
|
||||
self.note(&format!("expected {} `{}`", label, expected));
|
||||
|
@ -618,6 +618,7 @@ impl FileInfo {
|
||||
styled_buffer.set_style(0, p, Style::UnderlinePrimary);
|
||||
} else {
|
||||
styled_buffer.putc(1, p, '-', Style::UnderlineSecondary);
|
||||
styled_buffer.set_style(0, p, Style::UnderlineSecondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,9 @@ fn main() {
|
||||
x; //~ value moved here
|
||||
|
||||
let y = Int(2);
|
||||
//~^use `mut y` here to make mutable
|
||||
y //~ error: cannot borrow immutable local variable `y` as mutable
|
||||
//~| cannot borrow
|
||||
+=
|
||||
Int(1);
|
||||
}
|
||||
|
@ -12,6 +12,6 @@ mod foo { pub struct bar; }
|
||||
|
||||
fn main() {
|
||||
let bar = 5;
|
||||
//~^ ERROR declaration of `bar` shadows an enum variant or unit-like struct in scope
|
||||
//~^ ERROR cannot be named the same
|
||||
use foo::bar;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
mod foo { pub mod foo { } } //~ NOTE previous definition of `foo` here
|
||||
|
||||
use foo::foo; //~ ERROR a module named `foo` has already been defined in this module
|
||||
use foo::foo;
|
||||
//~^ ERROR a module named `foo` has already been defined in this module
|
||||
//~| was already imported
|
||||
|
||||
fn main() {}
|
||||
|
@ -61,7 +61,9 @@ fn move_after_borrow() {
|
||||
let a: Box<_> = box B { x: box 0, y: box 1 };
|
||||
let _x = &a.x;
|
||||
//~^ NOTE borrow of `a.x` occurs here
|
||||
let _y = a.y; //~ ERROR cannot move
|
||||
let _y = a.y;
|
||||
//~^ ERROR cannot move
|
||||
//~| move out of
|
||||
}
|
||||
|
||||
fn copy_after_mut_borrow() {
|
||||
@ -75,7 +77,9 @@ fn move_after_mut_borrow() {
|
||||
let mut a: Box<_> = box B { x: box 0, y: box 1 };
|
||||
let _x = &mut a.x;
|
||||
//~^ NOTE borrow of `a.x` occurs here
|
||||
let _y = a.y; //~ ERROR cannot move
|
||||
let _y = a.y;
|
||||
//~^ ERROR cannot move
|
||||
//~| move out of
|
||||
}
|
||||
|
||||
fn borrow_after_mut_borrow() {
|
||||
@ -127,7 +131,9 @@ fn move_after_borrow_nested() {
|
||||
let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
|
||||
let _x = &a.x.x;
|
||||
//~^ borrow of `a.x.x` occurs here
|
||||
let _y = a.y; //~ ERROR cannot move
|
||||
let _y = a.y;
|
||||
//~^ ERROR cannot move
|
||||
//~| move out of
|
||||
}
|
||||
|
||||
fn copy_after_mut_borrow_nested() {
|
||||
@ -141,7 +147,9 @@ fn move_after_mut_borrow_nested() {
|
||||
let mut a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
|
||||
let _x = &mut a.x.x;
|
||||
//~^ NOTE borrow of `a.x.x` occurs here
|
||||
let _y = a.y; //~ ERROR cannot move
|
||||
let _y = a.y;
|
||||
//~^ ERROR cannot move
|
||||
//~| move out of
|
||||
}
|
||||
|
||||
fn borrow_after_mut_borrow_nested() {
|
||||
|
@ -26,6 +26,7 @@ fn f() {
|
||||
|
||||
v3.push(&'x'); // statement 6
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
//~| does not live long enough
|
||||
//~| NOTE ...but borrowed value is only valid for the statement
|
||||
//~| HELP consider using a `let` binding to increase its lifetime
|
||||
|
||||
@ -36,6 +37,7 @@ fn f() {
|
||||
|
||||
v4.push(&'y');
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
//~| does not live long enough
|
||||
//~| NOTE ...but borrowed value is only valid for the statement
|
||||
//~| HELP consider using a `let` binding to increase its lifetime
|
||||
|
||||
@ -46,6 +48,7 @@ fn f() {
|
||||
|
||||
v5.push(&'z');
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
//~| does not live long enough
|
||||
//~| NOTE ...but borrowed value is only valid for the statement
|
||||
//~| HELP consider using a `let` binding to increase its lifetime
|
||||
|
||||
|
@ -9,10 +9,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn f() {
|
||||
let x = [1].iter(); //~ ERROR borrowed value does not live long enough
|
||||
//~^ NOTE reference must be valid for the block suffix following statement
|
||||
//~^^ HELP consider using a `let` binding to increase its lifetime
|
||||
//~^^^ NOTE ...but borrowed value is only valid for the statement at 12:4
|
||||
let x = [1].iter();
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
//~|does not live long enough
|
||||
//~| NOTE reference must be valid for the block suffix following statement
|
||||
//~| HELP consider using a `let` binding to increase its lifetime
|
||||
//~| NOTE ...but borrowed value is only valid for the statement at 12:4
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -19,6 +19,7 @@ enum Foo {
|
||||
fn blah() {
|
||||
let f = &Foo::Foo1(box 1, box 2);
|
||||
match *f { //~ ERROR cannot move out of
|
||||
//~| move occurs here
|
||||
Foo::Foo1(num1, //~ NOTE attempting to move value to here
|
||||
num2) => (), //~ NOTE and here
|
||||
Foo::Foo2(num) => (), //~ NOTE and here
|
||||
@ -37,6 +38,7 @@ impl Drop for S {
|
||||
fn move_in_match() {
|
||||
match (S {f: "foo".to_string(), g: "bar".to_string()}) {
|
||||
S { //~ ERROR cannot move out of type `S`, which defines the `Drop` trait
|
||||
//~| can not move out of here
|
||||
f: _s, //~ NOTE attempting to move value to here
|
||||
g: _t //~ NOTE and here
|
||||
} => {}
|
||||
@ -53,6 +55,7 @@ fn free<T>(_: T) {}
|
||||
fn blah2() {
|
||||
let a = &A { a: box 1 };
|
||||
match a.a { //~ ERROR cannot move out of
|
||||
//~| move occurs here
|
||||
n => { //~ NOTE attempting to move value to here
|
||||
free(n)
|
||||
}
|
||||
|
@ -27,10 +27,12 @@ pub fn main() {
|
||||
match x {
|
||||
[_, tail..] => {
|
||||
match tail {
|
||||
[Foo { string: a }, //~ ERROR cannot move out of borrowed content
|
||||
[Foo { string: a },
|
||||
//~^ ERROR cannot move out of borrowed content
|
||||
//~| move occurs here
|
||||
//~| attempting to move value to here
|
||||
Foo { string: b }] => {
|
||||
//~^^ NOTE attempting to move value to here
|
||||
//~^^ NOTE and here
|
||||
//~^ NOTE and here
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
|
@ -19,6 +19,7 @@ fn a() {
|
||||
[box ref _a, _, _] => {
|
||||
//~^ borrow of `vec[..]` occurs here
|
||||
vec[0] = box 4; //~ ERROR cannot assign
|
||||
//~^ assignment to `vec[..]` occurs here
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,6 +31,7 @@ fn b() {
|
||||
[_b..] => {
|
||||
//~^ borrow of `vec[..]` occurs here
|
||||
vec[0] = box 4; //~ ERROR cannot assign
|
||||
//~^ assignment to `vec[..]` occurs here
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -39,8 +41,9 @@ fn c() {
|
||||
let vec: &mut [Box<isize>] = &mut vec;
|
||||
match vec {
|
||||
[_a, //~ ERROR cannot move out
|
||||
_b..] => { //~^ NOTE attempting to move value to here
|
||||
|
||||
//~| move occurs here
|
||||
//~| attempting to move value to here
|
||||
_b..] => {
|
||||
// Note: `_a` is *moved* here, but `b` is borrowing,
|
||||
// hence illegal.
|
||||
//
|
||||
@ -51,6 +54,7 @@ fn c() {
|
||||
}
|
||||
let a = vec[0]; //~ ERROR cannot move out
|
||||
//~^ NOTE attempting to move value to here
|
||||
//~| can not move out of here
|
||||
}
|
||||
|
||||
fn d() {
|
||||
@ -58,11 +62,13 @@ fn d() {
|
||||
let vec: &mut [Box<isize>] = &mut vec;
|
||||
match vec {
|
||||
[_a.., //~ ERROR cannot move out
|
||||
//~^ move occurs here
|
||||
_b] => {} //~ NOTE attempting to move value to here
|
||||
_ => {}
|
||||
}
|
||||
let a = vec[0]; //~ ERROR cannot move out
|
||||
//~^ NOTE attempting to move value to here
|
||||
//~| can not move out of here
|
||||
}
|
||||
|
||||
fn e() {
|
||||
@ -70,13 +76,15 @@ fn e() {
|
||||
let vec: &mut [Box<isize>] = &mut vec;
|
||||
match vec {
|
||||
[_a, _b, _c] => {} //~ ERROR cannot move out
|
||||
//~^ NOTE attempting to move value to here
|
||||
//~^^ NOTE and here
|
||||
//~^^^ NOTE and here
|
||||
//~| move occurs here
|
||||
//~| NOTE attempting to move value to here
|
||||
//~| NOTE and here
|
||||
//~| NOTE and here
|
||||
_ => {}
|
||||
}
|
||||
let a = vec[0]; //~ ERROR cannot move out
|
||||
//~^ NOTE attempting to move value to here
|
||||
//~| can not move out of here
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -13,16 +13,16 @@ mod foo {
|
||||
pub const d: u8 = 2;
|
||||
}
|
||||
|
||||
use foo::b as c; //~ NOTE constant imported here
|
||||
use foo::d; //~ NOTE constant imported here
|
||||
use foo::b as c; //~ NOTE is imported here
|
||||
use foo::d; //~ NOTE is imported here
|
||||
|
||||
const a: u8 = 2; //~ NOTE constant defined here
|
||||
const a: u8 = 2; //~ NOTE is defined here
|
||||
|
||||
fn main() {
|
||||
let a = 4; //~ ERROR variable bindings cannot
|
||||
//~^ NOTE there already is a constant in scope
|
||||
let c = 4; //~ ERROR variable bindings cannot
|
||||
//~^ NOTE there already is a constant in scope
|
||||
let d = 4; //~ ERROR variable bindings cannot
|
||||
//~^ NOTE there already is a constant in scope
|
||||
let a = 4; //~ ERROR let variables cannot
|
||||
//~^ NOTE cannot be named the same as a const variable
|
||||
let c = 4; //~ ERROR let variables cannot
|
||||
//~^ NOTE cannot be named the same as a const variable
|
||||
let d = 4; //~ ERROR let variables cannot
|
||||
//~^ NOTE cannot be named the same as a const variable
|
||||
}
|
||||
|
@ -11,5 +11,5 @@
|
||||
struct hello(isize);
|
||||
|
||||
fn main() {
|
||||
let hello = 0; //~ERROR declaration of `hello` shadows
|
||||
let hello = 0; //~ERROR cannot be named the same
|
||||
}
|
||||
|
@ -11,11 +11,13 @@
|
||||
use self::A; //~ NOTE previous import of `A` here
|
||||
use self::B; //~ NOTE previous import of `B` here
|
||||
mod A {} //~ ERROR a module named `A` has already been imported in this module
|
||||
//~| `A` was already imported
|
||||
pub mod B {} //~ ERROR a module named `B` has already been imported in this module
|
||||
|
||||
//~| `B` was already imported
|
||||
mod C {
|
||||
use C::D; //~ NOTE previous import of `D` here
|
||||
mod D {} //~ ERROR a module named `D` has already been imported in this module
|
||||
//~| `D` was already imported
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -13,6 +13,7 @@ static foo: i32 = 0;
|
||||
|
||||
fn bar(foo: i32) {}
|
||||
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
||||
//~| static variable used in pattern
|
||||
|
||||
mod submod {
|
||||
pub static answer: i32 = 42;
|
||||
@ -23,6 +24,6 @@ use self::submod::answer;
|
||||
|
||||
fn question(answer: i32) {}
|
||||
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
||||
|
||||
//~| static variable used in pattern
|
||||
fn main() {
|
||||
}
|
||||
|
@ -15,9 +15,14 @@ use std::ops::Div; //~ NOTE previous import
|
||||
use std::ops::Rem; //~ NOTE previous import
|
||||
|
||||
type Add = bool; //~ ERROR a trait named `Add` has already been imported in this module
|
||||
//~| was already imported
|
||||
struct Sub { x: f32 } //~ ERROR a trait named `Sub` has already been imported in this module
|
||||
//~| was already imported
|
||||
enum Mul { A, B } //~ ERROR a trait named `Mul` has already been imported in this module
|
||||
//~| was already imported
|
||||
mod Div { } //~ ERROR a trait named `Div` has already been imported in this module
|
||||
//~| was already imported
|
||||
trait Rem { } //~ ERROR a trait named `Rem` has already been imported in this module
|
||||
//~| was already imported
|
||||
|
||||
fn main() {}
|
||||
|
@ -10,11 +10,11 @@
|
||||
|
||||
fn main() {
|
||||
match Some(1) {
|
||||
None @ _ => {} //~ ERROR declaration of `None` shadows an enum variant
|
||||
None @ _ => {} //~ ERROR cannot be named the same
|
||||
};
|
||||
const C: u8 = 1;
|
||||
match 1 {
|
||||
C @ 2 => { //~ ERROR variable bindings cannot shadow constants
|
||||
C @ 2 => { //~ ERROR cannot be named the same
|
||||
println!("{}", C);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -11,14 +11,14 @@
|
||||
// aux-build:issue_3907.rs
|
||||
extern crate issue_3907;
|
||||
|
||||
type Foo = issue_3907::Foo; //~ NOTE: type defined here
|
||||
type Foo = issue_3907::Foo; //~ NOTE: type aliases cannot be used for traits
|
||||
|
||||
struct S {
|
||||
name: isize
|
||||
}
|
||||
|
||||
impl Foo for S { //~ ERROR: `Foo` is not a trait
|
||||
//~^ NOTE: `type` aliases cannot be used for traits
|
||||
//~| `Foo` is not a trait
|
||||
fn bar() { }
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,8 @@
|
||||
// except according to those terms.
|
||||
|
||||
trait I {}
|
||||
type K = I; //~ NOTE: type defined here
|
||||
type K = I;
|
||||
//~^ NOTE: aliases cannot be used for traits
|
||||
impl K for isize {} //~ ERROR: `K` is not a trait
|
||||
//~^ NOTE: `type` aliases cannot be used for traits
|
||||
//~| is not a trait
|
||||
fn main() {}
|
||||
|
@ -32,6 +32,7 @@ fn main() {
|
||||
loop {
|
||||
f(&s, |hellothere| {
|
||||
match hellothere.x { //~ ERROR cannot move out
|
||||
//~| move occurs here
|
||||
box E::Foo(_) => {}
|
||||
box E::Bar(x) => println!("{}", x.to_string()), //~ NOTE attempting to move value to here
|
||||
box E::Baz => {}
|
||||
|
@ -17,14 +17,16 @@ impl S {
|
||||
}
|
||||
|
||||
fn func(arg: S) {
|
||||
//~^ HELP use `mut` as shown
|
||||
//~| SUGGESTION fn func(mut arg: S) {
|
||||
arg.mutate(); //~ ERROR cannot borrow immutable argument
|
||||
//~^ here to make mutable
|
||||
arg.mutate();
|
||||
//~^ ERROR cannot borrow immutable argument
|
||||
//~| cannot borrow mutably
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let local = S;
|
||||
//~^ HELP use `mut` as shown
|
||||
//~| SUGGESTION let mut local = S;
|
||||
local.mutate(); //~ ERROR cannot borrow immutable local variable
|
||||
//~^ here to make mutable
|
||||
local.mutate();
|
||||
//~^ ERROR cannot borrow immutable local variable
|
||||
//~| cannot borrow mutably
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:declaration of `None` shadows
|
||||
// error-pattern:cannot be named the same
|
||||
use std::option::*;
|
||||
|
||||
fn main() {
|
||||
|
@ -11,5 +11,5 @@
|
||||
struct foo(usize);
|
||||
|
||||
fn main() {
|
||||
let (foo, _) = (2, 3); //~ ERROR declaration of `foo` shadows
|
||||
let (foo, _) = (2, 3); //~ ERROR `foo` cannot be named the same as
|
||||
}
|
||||
|
@ -13,6 +13,6 @@ use std::mem::transmute;
|
||||
|
||||
fn transmute() {}
|
||||
//~^ ERROR a value named `transmute` has already been imported in this module
|
||||
|
||||
//~| was already imported
|
||||
fn main() {
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user