rollup merge of #21289: brson/errorcodes

This does the bare minimum to make registration of error codes work again. After this patch, every call to `span_err!` with an error code gets that error code validated against a list in that crate and a new tidy script `errorck.py` validates that no error codes are duplicated globally.

There are further improvements to be made yet, detailed in #19624.

r? @nikomatsakis
This commit is contained in:
Alex Crichton 2015-01-21 09:13:46 -08:00
commit b250d9a3c8
38 changed files with 618 additions and 476 deletions

View File

@ -300,6 +300,7 @@ tidy:
| grep '^$(S)src/libbacktrace' -v \
| grep '^$(S)src/rust-installer' -v \
| xargs $(CFG_PYTHON) $(S)src/etc/check-binaries.py
$(Q) $(CFG_PYTHON) $(S)src/etc/errorck.py $(S)src/
endif

70
src/etc/errorck.py Normal file
View File

@ -0,0 +1,70 @@
# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# Digs error codes out of files named 'diagnostics.rs' across
# the tree, and ensures thare are no duplicates.
import sys, os, re
src_dir = sys.argv[1]
errcode_map = { }
for (dirpath, dirnames, filenames) in os.walk(src_dir):
if "src/test" in dirpath or "src/llvm" in dirpath:
# Short circuit for fast
continue
for filename in filenames:
if filename != "diagnostics.rs":
continue
path = os.path.join(dirpath, filename)
line_num = 1
with open(path, 'r') as f:
for line in f:
p = re.compile("(E\d\d\d\d)")
m = p.search(line)
if not m is None:
errcode = m.group(1)
new_record = [(errcode, path, line_num, line)]
existing = errcode_map.get(errcode)
if existing is not None:
# This is a dupe
errcode_map[errcode] = existing + new_record
else:
errcode_map[errcode] = new_record
line_num += 1
errors = False
all_errors = []
for errcode in errcode_map:
entries = errcode_map[errcode]
all_errors += [entries[0][0]]
if len(entries) > 1:
print "error: duplicate error code " + errcode
for entry in entries:
print entry[1] + ": " + str(entry[2])
print entry[3]
errors = True
print str(len(errcode_map)) + " error codes"
all_errors.sort()
all_errors.reverse()
print "highest error code: " + all_errors[0]
if errors:
sys.exit(1)

View File

@ -10,28 +10,55 @@
#![allow(non_snake_case)]
register_diagnostic! { E0001, r##"
register_long_diagnostics! {
E0001: r##"
This error suggests that the expression arm corresponding to the noted pattern
will never be reached as for all possible values of the expression being matched,
one of the preceeding patterns will match.
This means that perhaps some of the preceeding patterns are too general, this
one is too specific or the ordering is incorrect.
"## }
"##,
E0003: r##"
Not-a-Number (NaN) values can not be compared for equality and hence can never match
the input to a match expression. To match against NaN values, you should instead use
the `is_nan` method in a guard, as in: x if x.is_nan() => ...
"##,
E0004: r##"
This error indicates that the compiler can not guarantee a matching pattern for one
or more possible inputs to a match expression. Guaranteed matches are required in order
to assign values to match expressions, or alternatively, determine the flow of execution.
If you encounter this error you must alter your patterns so that every possible value of
the input type is matched. For types with a small number of variants (like enums) you
should probably cover all cases explicitly. Alternatively, the underscore `_` wildcard
pattern can be added after all other patterns to match "anything else".
"##,
// FIXME: Remove duplication here?
E0005: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
"##,
E0006: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
"##
}
register_diagnostics! {
E0002,
E0003,
E0004,
E0005,
E0006,
E0007,
E0008,
E0009,
E0010,
E0011,
E0012,
E0013,
E0014,
E0015,
E0016,
@ -49,24 +76,58 @@ register_diagnostics! {
E0137,
E0138,
E0139,
E0140,
E0152,
E0153,
E0157,
E0158,
E0161,
E0162,
E0165,
E0166,
E0167,
E0168,
E0169,
E0170,
E0171,
E0172,
E0173,
E0174,
E0177,
E0178,
E0179
E0261, // use of undeclared lifetime name
E0262, // illegal lifetime parameter name
E0263, // lifetime name declared twice in same scope
E0264, // unknown external lang item
E0265, // recursive constant
E0266, // expected item
E0267, // thing inside of a closure
E0268, // thing outside of a loop
E0269, // not all control paths return a value
E0270, // computation may converge in a function marked as diverging
E0271, // type mismatch resolving
E0272, // rustc_on_unimplemented attribute refers to non-existent type parameter
E0273, // rustc_on_unimplemented must have named format arguments
E0274, // rustc_on_unimplemented must have a value
E0275, // overflow evaluating requirement
E0276, // requirement appears on impl method but not on corresponding trait method
E0277, // trait is not implemented for type
E0278, // requirement is not satisfied
E0279, // requirement is not satisfied
E0280, // requirement is not satisfied
E0281, // type implements trait but other trait is required
E0282, // unable to infer enough type information about
E0283, // cannot resolve type
E0284, // cannot resolve type
E0285, // overflow evaluation builtin bounds
E0296, // malformed recursion limit attribute
E0297, // refutable pattern in for loop binding
E0298, // mismatched types between arms
E0299, // mismatched types between arms
E0300, // unexpanded macro
E0301, // cannot mutable borrow in a pattern guard
E0302, // cannot assign in a pattern guard
E0303, // pattern bindings are not allowed after an `@`
E0304, // expected signed integer constant
E0305, // expected constant
E0306, // expected positive integer for repeat count
E0307, // expected constant integer for repeat count
E0308,
E0309, // thing may not live long enough
E0310, // thing may not live long enough
E0311, // thing may not live long enough
E0312, // lifetime of reference outlives lifetime of borrowed content
E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
E0314, // closure outlives stack frame
E0315 // cannot invoke closure outside of its lifetime
}
__build_diagnostic_array! { DIAGNOSTICS }

View File

@ -54,7 +54,9 @@ extern crate test;
pub use rustc_llvm as llvm;
mod diagnostics;
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;
pub mod back {
pub use rustc_back::abi;
@ -132,8 +134,6 @@ pub mod lib {
pub use llvm;
}
__build_diagnostic_array! { DIAGNOSTICS }
// A private module so that macro-expanded idents like
// `::rustc::lint::Lint` will also work in `rustc` itself.
//

View File

@ -73,12 +73,12 @@ impl<'a> CheckLoopVisitor<'a> {
match self.cx {
Loop => {}
Closure => {
self.sess.span_err(span,
&format!("`{}` inside of a closure", name)[]);
span_err!(self.sess, span, E0267,
"`{}` inside of a closure", name);
}
Normal => {
self.sess.span_err(span,
&format!("`{}` outside of loop", name)[]);
span_err!(self.sess, span, E0268,
"`{}` outside of loop", name);
}
}
}

View File

@ -226,11 +226,10 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
ast::ExprForLoop(ref pat, _, _, _) => {
let mut static_inliner = StaticInliner::new(cx.tcx);
is_refutable(cx, &*static_inliner.fold_pat((*pat).clone()), |uncovered_pat| {
cx.tcx.sess.span_err(
pat.span,
&format!("refutable pattern in `for` loop binding: \
span_err!(cx.tcx.sess, pat.span, E0297,
"refutable pattern in `for` loop binding: \
`{}` not covered",
pat_to_string(uncovered_pat))[]);
pat_to_string(uncovered_pat));
});
// Check legality of move bindings.
@ -869,7 +868,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
Some(true) => Some(vec![]),
Some(false) => None,
None => {
cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
span_err!(cx.tcx.sess, pat_span, E0298, "mismatched types between arms");
None
}
}
@ -882,7 +881,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
Some(true) => Some(vec![]),
Some(false) => None,
None => {
cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
span_err!(cx.tcx.sess, pat_span, E0299, "mismatched types between arms");
None
}
}
@ -921,7 +920,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
}
ast::PatMac(_) => {
cx.tcx.sess.span_err(pat_span, "unexpanded macro");
span_err!(cx.tcx.sess, pat_span, E0300, "unexpanded macro");
None
}
};
@ -1082,11 +1081,8 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
_: LoanCause) {
match kind {
MutBorrow => {
self.cx
.tcx
.sess
.span_err(span,
"cannot mutably borrow in a pattern guard")
span_err!(self.cx.tcx.sess, span, E0301,
"cannot mutably borrow in a pattern guard")
}
ImmBorrow | UniqueImmBorrow => {}
}
@ -1095,10 +1091,7 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
fn mutate(&mut self, _: NodeId, span: Span, _: cmt, mode: MutateMode) {
match mode {
JustWrite | WriteAndRead => {
self.cx
.tcx
.sess
.span_err(span, "cannot assign in a pattern guard")
span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")
}
Init => {}
}
@ -1120,7 +1113,7 @@ struct AtBindingPatternVisitor<'a, 'b:'a, 'tcx:'b> {
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> {
fn visit_pat(&mut self, pat: &Pat) {
if !self.bindings_allowed && pat_is_binding(&self.cx.tcx.def_map, pat) {
self.cx.tcx.sess.span_err(pat.span,
span_err!(self.cx.tcx.sess, pat.span, E0303,
"pattern bindings are not allowed \
after an `@`");
}

View File

@ -83,7 +83,7 @@ pub fn check_item_recursion<'a>(sess: &'a Session,
impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
fn visit_item(&mut self, it: &ast::Item) {
if self.idstack.iter().any(|x| x == &(it.id)) {
self.sess.span_err(self.root_it.span, "recursive constant");
span_err!(self.sess, self.root_it.span, E0265, "recursive constant");
return;
}
self.idstack.push(it.id);
@ -103,9 +103,9 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
self.visit_item(item),
ast_map::NodeForeignItem(_) => {},
_ => {
self.sess.span_err(e.span,
&format!("expected item, found {}",
self.ast_map.node_to_string(def_id.node))[]);
span_err!(self.sess, e.span, E0266,
"expected item, found {}",
self.ast_map.node_to_string(def_id.node));
return;
},
}

View File

@ -371,12 +371,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
infer::EquatePredicate(_) => "equality predicate not satisfied",
};
self.tcx.sess.span_err(
trace.origin.span(),
&format!("{}: {} ({})",
span_err!(self.tcx.sess, trace.origin.span(), E0308,
"{}: {} ({})",
message_root_str,
expected_found_str,
ty::type_err_to_str(self.tcx, terr))[]);
ty::type_err_to_str(self.tcx, terr));
match trace.origin {
infer::MatchExpressionArm(_, arm_span) =>
@ -443,9 +442,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
match sub {
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
self.tcx.sess.span_err(
origin.span(),
&format!("{} may not live long enough", labeled_user_string)[]);
span_err!(self.tcx.sess, origin.span(), E0309,
"{} may not live long enough", labeled_user_string);
self.tcx.sess.span_help(
origin.span(),
&format!(
@ -456,9 +454,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
ty::ReStatic => {
// Does the required lifetime have a nice name we can print?
self.tcx.sess.span_err(
origin.span(),
&format!("{} may not live long enough", labeled_user_string)[]);
span_err!(self.tcx.sess, origin.span(), E0310,
"{} may not live long enough", labeled_user_string);
self.tcx.sess.span_help(
origin.span(),
&format!(
@ -468,11 +465,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
_ => {
// If not, be less specific.
self.tcx.sess.span_err(
origin.span(),
&format!(
span_err!(self.tcx.sess, origin.span(), E0311,
"{} may not live long enough",
labeled_user_string)[]);
labeled_user_string);
self.tcx.sess.span_help(
origin.span(),
&format!(
@ -499,8 +494,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
self.report_and_explain_type_error(trace, &terr);
}
infer::Reborrow(span) => {
self.tcx.sess.span_err(
span,
span_err!(self.tcx.sess, span, E0312,
"lifetime of reference outlines \
lifetime of borrowed content...");
note_and_explain_region(
@ -515,14 +509,13 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
"");
}
infer::ReborrowUpvar(span, ref upvar_id) => {
self.tcx.sess.span_err(
span,
&format!("lifetime of borrowed pointer outlives \
span_err!(self.tcx.sess, span, E0313,
"lifetime of borrowed pointer outlives \
lifetime of captured variable `{}`...",
ty::local_var_name_str(self.tcx,
upvar_id.var_id)
.get()
.to_string())[]);
.to_string());
note_and_explain_region(
self.tcx,
"...the borrowed pointer is valid for ",
@ -539,8 +532,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
"");
}
infer::InfStackClosure(span) => {
self.tcx.sess.span_err(
span,
span_err!(self.tcx.sess, span, E0314,
"closure outlives stack frame");
note_and_explain_region(
self.tcx,
@ -554,8 +546,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
"");
}
infer::InvokeClosure(span) => {
self.tcx.sess.span_err(
span,
span_err!(self.tcx.sess, span, E0315,
"cannot invoke closure outside of its lifetime");
note_and_explain_region(
self.tcx,

View File

@ -1557,8 +1557,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
},
_ => false
};
self.ir.tcx.sess.span_err(
sp, "not all control paths return a value");
span_err!(self.ir.tcx.sess, sp, E0269, "not all control paths return a value");
if ends_with_stmt {
let last_stmt = body.stmts.first().unwrap();
let original_span = original_sp(self.ir.tcx.sess.codemap(),
@ -1575,7 +1574,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
ty::FnDiverging
if self.live_on_entry(entry_ln, self.s.clean_exit_var).is_some() => {
self.ir.tcx.sess.span_err(sp,
span_err!(self.ir.tcx.sess, sp, E0270,
"computation may converge in a function marked as diverging");
}

View File

@ -33,7 +33,7 @@ pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
}
}
sess.span_err(attr.span, "malformed recursion limit attribute, \
span_err!(sess, attr.span, E0296, "malformed recursion limit attribute, \
expected #![recursion_limit=\"N\"]");
}
}

View File

@ -396,10 +396,9 @@ impl<'a> LifetimeContext<'a> {
}
fn unresolved_lifetime_ref(&self, lifetime_ref: &ast::Lifetime) {
self.sess.span_err(
lifetime_ref.span,
&format!("use of undeclared lifetime name `{}`",
token::get_name(lifetime_ref.name))[]);
span_err!(self.sess, lifetime_ref.span, E0261,
"use of undeclared lifetime name `{}`",
token::get_name(lifetime_ref.name));
}
fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &Vec<ast::LifetimeDef>) {
@ -409,11 +408,9 @@ impl<'a> LifetimeContext<'a> {
let special_idents = [special_idents::static_lifetime];
for lifetime in lifetimes.iter() {
if special_idents.iter().any(|&i| i.name == lifetime.lifetime.name) {
self.sess.span_err(
lifetime.lifetime.span,
&format!("illegal lifetime parameter name: `{}`",
token::get_name(lifetime.lifetime.name))
[]);
span_err!(self.sess, lifetime.lifetime.span, E0262,
"illegal lifetime parameter name: `{}`",
token::get_name(lifetime.lifetime.name));
}
}
@ -422,12 +419,10 @@ impl<'a> LifetimeContext<'a> {
let lifetime_j = &lifetimes[j];
if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
self.sess.span_err(
lifetime_j.lifetime.span,
&format!("lifetime name `{}` declared twice in \
span_err!(self.sess, lifetime_j.lifetime.span, E0263,
"lifetime name `{}` declared twice in \
the same scope",
token::get_name(lifetime_j.lifetime.name))
[]);
token::get_name(lifetime_j.lifetime.name));
}
}

View File

@ -55,12 +55,10 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
if !predicate.references_error() {
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0271,
"type mismatch resolving `{}`: {}",
predicate.user_string(infcx.tcx),
ty::type_err_to_str(infcx.tcx, &error.err)).as_slice());
ty::type_err_to_str(infcx.tcx, &error.err));
note_obligation_cause(infcx, obligation);
}
}
@ -97,28 +95,25 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
Position::ArgumentNamed(s) => match generic_map.get(s) {
Some(val) => Some(val.as_slice()),
None => {
infcx.tcx.sess
.span_err(err_sp,
format!("the #[rustc_on_unimplemented] \
span_err!(infcx.tcx.sess, err_sp, E0272,
"the #[rustc_on_unimplemented] \
attribute on \
trait definition for {} refers to \
non-existent type parameter {}",
trait_str, s)
.as_slice());
trait_str, s);
errored = true;
None
}
},
_ => {
infcx.tcx.sess
.span_err(err_sp,
format!("the #[rustc_on_unimplemented] \
span_err!(infcx.tcx.sess, err_sp, E0273,
"the #[rustc_on_unimplemented] \
attribute on \
trait definition for {} must have named \
format arguments, \
eg `#[rustc_on_unimplemented = \
\"foo {{T}}\"]`",
trait_str).as_slice());
trait_str);
errored = true;
None
}
@ -130,11 +125,11 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
report = Some(err);
}
} else {
infcx.tcx.sess.span_err(err_sp,
format!("the #[rustc_on_unimplemented] attribute on \
span_err!(infcx.tcx.sess, err_sp, E0274,
"the #[rustc_on_unimplemented] attribute on \
trait definition for {} must have a value, \
eg `#[rustc_on_unimplemented = \"foo\"]`",
trait_str).as_slice());
trait_str);
}
break;
}
@ -151,11 +146,9 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
// We could track the stack here more precisely if we wanted, I imagine.
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
"overflow evaluating the requirement `{}`",
predicate.user_string(infcx.tcx)).as_slice());
predicate.user_string(infcx.tcx));
suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
@ -165,12 +158,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
SelectionError::Unimplemented => {
match &obligation.cause.code {
&ObligationCauseCode::CompareImplMethodObligation => {
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0276,
"the requirement `{}` appears on the impl \
method but not on the corresponding trait method",
obligation.predicate.user_string(infcx.tcx)).as_slice());
obligation.predicate.user_string(infcx.tcx));;
}
_ => {
match obligation.predicate {
@ -180,12 +171,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
if !trait_predicate.references_error() {
let trait_ref = trait_predicate.to_poly_trait_ref();
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0277,
"the trait `{}` is not implemented for the type `{}`",
trait_ref.user_string(infcx.tcx),
trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
trait_ref.self_ty().user_string(infcx.tcx));
// Check if it has a custom "#[rustc_on_unimplemented]"
// error message, report with that message if it does
let custom_note = report_on_unimplemented(infcx, &*trait_ref.0,
@ -201,34 +190,28 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.equality_predicate(obligation.cause.span,
&predicate).unwrap_err();
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0278,
"the requirement `{}` is not satisfied (`{}`)",
predicate.user_string(infcx.tcx),
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
ty::type_err_to_str(infcx.tcx, &err));
}
ty::Predicate::RegionOutlives(ref predicate) => {
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.region_outlives_predicate(obligation.cause.span,
&predicate).unwrap_err();
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate.user_string(infcx.tcx),
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
ty::type_err_to_str(infcx.tcx, &err));
}
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0280,
"the requirement `{}` is not satisfied",
predicate.user_string(infcx.tcx)).as_slice());
predicate.user_string(infcx.tcx));
}
}
}
@ -239,15 +222,13 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
if !ty::type_is_error(actual_trait_ref.self_ty()) {
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0281,
"type mismatch: the type `{}` implements the trait `{}`, \
but the trait `{}` is required ({})",
expected_trait_ref.self_ty().user_string(infcx.tcx),
expected_trait_ref.user_string(infcx.tcx),
actual_trait_ref.user_string(infcx.tcx),
ty::type_err_to_str(infcx.tcx, e)).as_slice());
ty::type_err_to_str(infcx.tcx, e));
note_obligation_cause(infcx, obligation);
}
}
@ -293,18 +274,14 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
infcx.tcx.lang_items.sized_trait()
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
{
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0282,
"unable to infer enough type information about `{}`; \
type annotations required",
self_ty.user_string(infcx.tcx)).as_slice());
self_ty.user_string(infcx.tcx));
} else {
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
"type annotations required: cannot resolve `{}`",
predicate.user_string(infcx.tcx)).as_slice());
predicate.user_string(infcx.tcx));;
note_obligation_cause(infcx, obligation);
}
}
@ -323,11 +300,9 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
_ => {
if !infcx.tcx.sess.has_errors() {
infcx.tcx.sess.span_err(
obligation.cause.span,
format!(
span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
"type annotations required: cannot resolve `{}`",
predicate.user_string(infcx.tcx)).as_slice());
predicate.user_string(infcx.tcx));;
note_obligation_cause(infcx, obligation);
}
}

View File

@ -379,11 +379,10 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
false
}
Err(Overflow) => {
infcx.tcx.sess.span_err(
span,
format!("overflow evaluating whether `{}` is `{}`",
ty.user_string(infcx.tcx),
bound.user_string(infcx.tcx)).as_slice());
span_err!(infcx.tcx.sess, span, E0285,
"overflow evaluating whether `{}` is `{}`",
ty.user_string(infcx.tcx),
bound.user_string(infcx.tcx));
suggest_new_overflow_limit(infcx.tcx, span);
false
}

View File

@ -5369,15 +5369,13 @@ pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
discriminant = val as Disr
}
Ok(_) => {
cx.sess
.span_err(e.span,
span_err!(cx.sess, e.span, E0304,
"expected signed integer constant");
}
Err(ref err) => {
cx.sess
.span_err(e.span,
&format!("expected constant: {}",
*err)[]);
span_err!(cx.sess, e.span, E0305,
"expected constant: {}",
*err);
}
},
None => {}
@ -5851,9 +5849,9 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
const_eval::const_binary(_) =>
"binary array"
};
tcx.sess.span_err(count_expr.span, &format!(
span_err!(tcx.sess, count_expr.span, E0306,
"expected positive integer for repeat count, found {}",
found)[]);
found);
}
Err(_) => {
let found = match count_expr.node {
@ -5866,9 +5864,9 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
_ =>
"non-constant expression"
};
tcx.sess.span_err(count_expr.span, &format!(
span_err!(tcx.sess, count_expr.span, E0307,
"expected constant integer for repeat count, found {}",
found)[]);
found);
}
}
0

View File

@ -99,9 +99,9 @@ impl<'a> Context<'a> {
self.items.missing.push(lang_items::$item);
}
} else)* {
self.sess.span_err(span,
format!("unknown external lang item: `{}`",
name).as_slice());
span_err!(self.sess, span, E0264,
"unknown external lang item: `{}`",
name);
}
}
}

View File

@ -69,65 +69,23 @@ impl Session {
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
self.diagnostic().span_fatal(sp, msg)
}
pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! {
self.diagnostic().span_fatal_with_code(sp, msg, code)
}
pub fn fatal(&self, msg: &str) -> ! {
self.diagnostic().handler().fatal(msg)
}
pub fn span_err(&self, sp: Span, msg: &str) {
// Conditions for enabling multi-line errors:
if !msg.contains("mismatched types") &&
!msg.contains("type mismatch resolving") &&
!msg.contains("if and else have incompatible types") &&
!msg.contains("if may be missing an else clause") &&
!msg.contains("match arms have incompatible types") &&
!msg.contains("structure constructor specifies a structure of type") {
return self.diagnostic().span_err(sp, msg);
match split_msg_into_multilines(msg) {
Some(msg) => self.diagnostic().span_err(sp, &msg[]),
None => self.diagnostic().span_err(sp, msg)
}
let first = Regex::new(r"[( ]expected").unwrap();
let second = Regex::new(r" found").unwrap();
let third = Regex::new(
r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
let mut new_msg = String::new();
let mut head = 0u;
// Insert `\n` before expected and found.
for (pos1, pos2) in first.find_iter(msg).zip(
second.find_iter(msg)) {
new_msg = new_msg +
// A `(` may be preceded by a space and it should be trimmed
msg[head..pos1.0].trim_right() + // prefix
"\n" + // insert before first
&msg[pos1.0..pos1.1] + // insert what first matched
&msg[pos1.1..pos2.0] + // between matches
"\n " + // insert before second
// 123
// `expected` is 3 char longer than `found`. To align the types, `found` gets
// 3 spaces prepended.
&msg[pos2.0..pos2.1]; // insert what second matched
head = pos2.1;
}
let mut tail = &msg[head..];
// Insert `\n` before any remaining messages which match.
for pos in third.find_iter(tail).take(1) {
// The end of the message may just be wrapped in `()` without `expected`/`found`.
// Push this also to a new line and add the final tail after.
new_msg = new_msg +
// `(` is usually preceded by a space and should be trimmed.
tail[..pos.0].trim_right() + // prefix
"\n" + // insert before paren
&tail[pos.0..]; // append the tail
tail = "";
}
new_msg.push_str(tail);
self.diagnostic().span_err(sp, &new_msg[])
}
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
self.diagnostic().span_err_with_code(sp, msg, code)
match split_msg_into_multilines(msg) {
Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[], code),
None => self.diagnostic().span_err_with_code(sp, msg, code)
}
}
pub fn err(&self, msg: &str) {
self.diagnostic().handler().err(msg)
@ -285,6 +243,62 @@ impl Session {
}
}
fn split_msg_into_multilines(msg: &str) -> Option<String> {
// Conditions for enabling multi-line errors:
if !msg.contains("mismatched types") &&
!msg.contains("type mismatch resolving") &&
!msg.contains("if and else have incompatible types") &&
!msg.contains("if may be missing an else clause") &&
!msg.contains("match arms have incompatible types") &&
!msg.contains("structure constructor specifies a structure of type") {
return None
}
let first = Regex::new(r"[( ]expected").unwrap();
let second = Regex::new(r" found").unwrap();
let third = Regex::new(
r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
let mut new_msg = String::new();
let mut head = 0u;
// Insert `\n` before expected and found.
for (pos1, pos2) in first.find_iter(msg).zip(
second.find_iter(msg)) {
new_msg = new_msg +
// A `(` may be preceded by a space and it should be trimmed
msg[head..pos1.0].trim_right() + // prefix
"\n" + // insert before first
&msg[pos1.0..pos1.1] + // insert what first matched
&msg[pos1.1..pos2.0] + // between matches
"\n " + // insert before second
// 123
// `expected` is 3 char longer than `found`. To align the types, `found` gets
// 3 spaces prepended.
&msg[pos2.0..pos2.1]; // insert what second matched
head = pos2.1;
}
let mut tail = &msg[head..];
// Insert `\n` before any remaining messages which match.
for pos in third.find_iter(tail).take(1) {
// The end of the message may just be wrapped in `()` without `expected`/`found`.
// Push this also to a new line and add the final tail after.
new_msg = new_msg +
// `(` is usually preceded by a space and should be trimmed.
tail[..pos.0].trim_right() + // prefix
"\n" + // insert before paren
&tail[pos.0..]; // append the tail
tail = "";
}
new_msg.push_str(tail);
return Some(new_msg)
}
pub fn build_session(sopts: config::Options,
local_crate_source_file: Option<Path>,
registry: diagnostics::registry::Registry)

View File

@ -61,7 +61,6 @@ use rustc::lint::Lint;
use rustc::lint;
use rustc::metadata;
use rustc::metadata::creader::CrateOrString::Str;
use rustc::DIAGNOSTICS;
use rustc::util::common::time;
use std::cmp::Ordering::Equal;
@ -98,7 +97,7 @@ fn run_compiler(args: &[String]) {
None => return
};
let descriptions = diagnostics::registry::Registry::new(&DIAGNOSTICS);
let descriptions = diagnostics_registry();
match matches.opt_str("explain") {
Some(ref code) => {
match descriptions.find_description(&code[]) {
@ -659,8 +658,20 @@ pub fn monitor<F:FnOnce()+Send>(f: F) {
}
}
pub fn diagnostics_registry() -> diagnostics::registry::Registry {
use syntax::diagnostics::registry::Registry;
let all_errors = Vec::new() +
rustc::diagnostics::DIAGNOSTICS.as_slice() +
rustc_typeck::diagnostics::DIAGNOSTICS.as_slice() +
rustc_resolve::diagnostics::DIAGNOSTICS.as_slice();
Registry::new(&*all_errors)
}
pub fn main() {
let args = std::os::args();
let result = run(args);
std::os::set_exit_status(result);
}

View File

@ -0,0 +1,28 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(non_snake_case)]
register_diagnostics! {
E0157,
E0153,
E0251, // a named type or value has already been imported in this module
E0252, // a named type or value has already been imported in this module
E0253, // not directly importable
E0254, // import conflicts with imported crate in this module
E0255, // import conflicts with value in this module
E0256, // import conflicts with type in this module
E0257, // inherent implementations are only allowen on types defined in the current module
E0258, // import conflicts with existing submodule
E0259, // an extern crate has already been imported into this module
E0260 // name conflicts with an external crate that has been imported into this module
}
__build_diagnostic_array! { DIAGNOSTICS }

View File

@ -97,6 +97,10 @@ use std::mem::replace;
use std::rc::{Rc, Weak};
use std::uint;
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;
mod check_unused;
mod record_exports;
mod build_reduced_graph;
@ -1718,7 +1722,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
in this module",
namespace_name,
token::get_name(name).get());
self.session.span_err(import_directive.span, msg.as_slice());
span_err!(self.session, import_directive.span, E0251, "{}", msg.as_slice());
} else {
let target = Target::new(containing_module.clone(),
name_bindings.clone(),
@ -1765,7 +1769,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ValueNS => "value",
},
token::get_name(name).get());
self.session.span_err(import_span, &msg[]);
span_err!(self.session, import_span, E0252, "{}", &msg[]);
}
Some(_) | None => {}
}
@ -1780,7 +1784,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) {
let msg = format!("`{}` is not directly importable",
token::get_name(name));
self.session.span_err(import_span, &msg[]);
span_err!(self.session, import_span, E0253, "{}", &msg[]);
}
}
@ -1805,7 +1809,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
crate in this module \
(maybe you meant `use {0}::*`?)",
token::get_name(name).get());
self.session.span_err(import_span, &msg[]);
span_err!(self.session, import_span, E0254, "{}", &msg[]);
}
Some(_) | None => {}
}
@ -1827,7 +1831,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let msg = format!("import `{}` conflicts with value \
in this module",
token::get_name(name).get());
self.session.span_err(import_span, &msg[]);
span_err!(self.session, import_span, E0255, "{}", &msg[]);
if let Some(span) = value.value_span {
self.session.span_note(span,
"conflicting value here");
@ -1845,7 +1849,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let msg = format!("import `{}` conflicts with type in \
this module",
token::get_name(name).get());
self.session.span_err(import_span, &msg[]);
span_err!(self.session, import_span, E0256, "{}", &msg[]);
if let Some(span) = ty.type_span {
self.session.span_note(span,
"note conflicting type here")
@ -1858,7 +1862,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let msg = format!("inherent implementations \
are only allowed on types \
defined in the current module");
self.session.span_err(span, &msg[]);
span_err!(self.session, span, E0257, "{}", &msg[]);
self.session.span_note(import_span,
"import from other module here")
}
@ -1867,7 +1871,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let msg = format!("import `{}` conflicts with existing \
submodule",
token::get_name(name).get());
self.session.span_err(import_span, &msg[]);
span_err!(self.session, import_span, E0258, "{}", &msg[]);
if let Some(span) = ty.type_span {
self.session.span_note(span,
"note conflicting module here")
@ -1893,11 +1897,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if module.external_module_children.borrow().contains_key(&name) {
self.session
.span_err(span,
&format!("an external crate named `{}` has already \
span_err!(self.session, span, E0259,
"an external crate named `{}` has already \
been imported into this module",
token::get_name(name).get())[]);
token::get_name(name).get());
}
}
@ -1911,12 +1914,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if module.external_module_children.borrow().contains_key(&name) {
self.session
.span_err(span,
&format!("the name `{}` conflicts with an external \
span_err!(self.session, span, E0260,
"the name `{}` conflicts with an external \
crate that has been imported into this \
module",
token::get_name(name).get())[]);
token::get_name(name).get());
}
}

View File

@ -100,8 +100,7 @@ pub trait AstConv<'tcx> {
-> Ty<'tcx>
{
if ty::binds_late_bound_regions(self.tcx(), &poly_trait_ref) {
self.tcx().sess.span_err(
span,
span_err!(self.tcx().sess, span, E0212,
"cannot extract an associated type from a higher-ranked trait bound \
in this context");
self.tcx().types.err
@ -119,8 +118,7 @@ pub trait AstConv<'tcx> {
_item_name: ast::Name)
-> Ty<'tcx>
{
self.tcx().sess.span_err(
span,
span_err!(self.tcx().sess, span, E0213,
"associated types are not accepted in this context");
self.tcx().types.err
@ -268,8 +266,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
convert_angle_bracketed_parameters(this, rscope, data)
}
ast::ParenthesizedParameters(ref data) => {
tcx.sess.span_err(
path.span,
span_err!(tcx.sess, path.span, E0214,
"parenthesized parameters may only be used with a trait");
(Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
}
@ -342,22 +339,22 @@ fn create_substs_for_ast_path<'tcx>(
} else {
"expected"
};
this.tcx().sess.span_fatal(span,
&format!("wrong number of type arguments: {} {}, found {}",
span_fatal!(this.tcx().sess, span, E0243,
"wrong number of type arguments: {} {}, found {}",
expected,
required_ty_param_count,
supplied_ty_param_count)[]);
supplied_ty_param_count);
} else if supplied_ty_param_count > formal_ty_param_count {
let expected = if required_ty_param_count < formal_ty_param_count {
"expected at most"
} else {
"expected"
};
this.tcx().sess.span_fatal(span,
&format!("wrong number of type arguments: {} {}, found {}",
span_fatal!(this.tcx().sess, span, E0244,
"wrong number of type arguments: {} {}, found {}",
expected,
formal_ty_param_count,
supplied_ty_param_count)[]);
supplied_ty_param_count);
}
let mut substs = Substs::new_type(types, regions);
@ -560,10 +557,9 @@ pub fn instantiate_trait_ref<'tcx>(
trait_ref
}
_ => {
this.tcx().sess.span_fatal(
ast_trait_ref.path.span,
&format!("`{}` is not a trait",
ast_trait_ref.path.user_string(this.tcx()))[]);
span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245,
"`{}` is not a trait",
ast_trait_ref.path.user_string(this.tcx()));
}
}
}
@ -610,7 +606,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
if !this.tcx().sess.features.borrow().unboxed_closures &&
this.tcx().lang_items.fn_trait_kind(trait_def_id).is_some()
{
this.tcx().sess.span_err(path.span,
span_err!(this.tcx().sess, path.span, E0215,
"angle-bracket notation is not stable when \
used with the `Fn` family of traits, use parentheses");
span_help!(this.tcx().sess, path.span,
@ -626,7 +622,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
if !this.tcx().sess.features.borrow().unboxed_closures &&
this.tcx().lang_items.fn_trait_kind(trait_def_id).is_none()
{
this.tcx().sess.span_err(path.span,
span_err!(this.tcx().sess, path.span, E0216,
"parenthetical notation is only stable when \
used with the `Fn` family of traits");
span_help!(this.tcx().sess, path.span,
@ -738,32 +734,29 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
}
if candidates.len() > 1 {
tcx.sess.span_err(
binding.span,
format!("ambiguous associated type: `{}` defined in multiple supertraits `{}`",
span_err!(tcx.sess, binding.span, E0217,
"ambiguous associated type: `{}` defined in multiple supertraits `{}`",
token::get_name(binding.item_name),
candidates.user_string(tcx)).as_slice());
candidates.user_string(tcx));
return Err(ErrorReported);
}
let candidate = match candidates.pop() {
Some(c) => c,
None => {
tcx.sess.span_err(
binding.span,
format!("no associated type `{}` defined in `{}`",
span_err!(tcx.sess, binding.span, E0218,
"no associated type `{}` defined in `{}`",
token::get_name(binding.item_name),
trait_ref.user_string(tcx)).as_slice());
trait_ref.user_string(tcx));
return Err(ErrorReported);
}
};
if ty::binds_late_bound_regions(tcx, &candidate) {
tcx.sess.span_err(
binding.span,
format!("associated type `{}` defined in higher-ranked supertrait `{}`",
span_err!(tcx.sess, binding.span, E0219,
"associated type `{}` defined in higher-ranked supertrait `{}`",
token::get_name(binding.item_name),
candidate.user_string(tcx)).as_slice());
candidate.user_string(tcx));
return Err(ErrorReported);
}
@ -964,18 +957,18 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
}
if suitable_bounds.len() == 0 {
tcx.sess.span_err(ast_ty.span,
format!("associated type `{}` not found for type parameter `{}`",
span_err!(tcx.sess, ast_ty.span, E0220,
"associated type `{}` not found for type parameter `{}`",
token::get_name(assoc_name),
token::get_name(ty_param_name)).as_slice());
token::get_name(ty_param_name));
return this.tcx().types.err;
}
if suitable_bounds.len() > 1 {
tcx.sess.span_err(ast_ty.span,
format!("ambiguous associated type `{}` in bounds of `{}`",
span_err!(tcx.sess, ast_ty.span, E0221,
"ambiguous associated type `{}` in bounds of `{}`",
token::get_name(assoc_name),
token::get_name(ty_param_name)).as_slice());
token::get_name(ty_param_name));
for suitable_bound in suitable_bounds.iter() {
span_note!(this.tcx().sess, ast_ty.span,
@ -1042,7 +1035,7 @@ pub fn ast_ty_to_ty<'tcx>(
match ast_ty_to_ty_cache.get(&ast_ty.id) {
Some(&ty::atttce_resolved(ty)) => return ty,
Some(&ty::atttce_unresolved) => {
tcx.sess.span_fatal(ast_ty.span,
span_fatal!(tcx.sess, ast_ty.span, E0246,
"illegal recursive type; insert an enum \
or struct in the cycle, if this is \
desired");
@ -1093,7 +1086,7 @@ pub fn ast_ty_to_ty<'tcx>(
ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
ast::TyBareFn(ref bf) => {
if bf.decl.variadic && bf.abi != abi::C {
tcx.sess.span_err(ast_ty.span,
span_err!(tcx.sess, ast_ty.span, E0222,
"variadic function must have C calling convention");
}
let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
@ -1142,9 +1135,9 @@ pub fn ast_ty_to_ty<'tcx>(
ty::mk_self_type(tcx)
}
def::DefMod(id) => {
tcx.sess.span_fatal(ast_ty.span,
&format!("found module name used as a type: {}",
tcx.map.node_to_string(id.node))[]);
span_fatal!(tcx.sess, ast_ty.span, E0247,
"found module name used as a type: {}",
tcx.map.node_to_string(id.node));
}
def::DefPrimTy(_) => {
panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
@ -1152,8 +1145,8 @@ pub fn ast_ty_to_ty<'tcx>(
def::DefAssociatedTy(trait_type_id) => {
let path_str = tcx.map.path_to_string(
tcx.map.get_parent(trait_type_id.node));
tcx.sess.span_err(ast_ty.span,
&format!("ambiguous associated \
span_err!(tcx.sess, ast_ty.span, E0223,
"ambiguous associated \
type; specify the type \
using the syntax `<Type \
as {}>::{}`",
@ -1163,17 +1156,17 @@ pub fn ast_ty_to_ty<'tcx>(
.last()
.unwrap()
.identifier)
.get())[]);
.get());
this.tcx().types.err
}
def::DefAssociatedPath(provenance, assoc_ident) => {
associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name)
}
_ => {
tcx.sess.span_fatal(ast_ty.span,
&format!("found value name used \
span_fatal!(tcx.sess, ast_ty.span, E0248,
"found value name used \
as a type: {:?}",
a_def)[]);
a_def);
}
}
}
@ -1191,17 +1184,16 @@ pub fn ast_ty_to_ty<'tcx>(
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
Some(i as uint)),
_ => {
tcx.sess.span_fatal(
ast_ty.span, "expected constant expr for array length");
span_fatal!(tcx.sess, ast_ty.span, E0249,
"expected constant expr for array length");
}
}
}
Err(ref r) => {
tcx.sess.span_fatal(
ast_ty.span,
&format!("expected constant expr for array \
span_fatal!(tcx.sess, ast_ty.span, E0250,
"expected constant expr for array \
length: {}",
*r)[]);
*r);
}
}
}
@ -1557,8 +1549,7 @@ fn conv_ty_poly_trait_ref<'tcx>(
None,
&mut projection_bounds))
} else {
this.tcx().sess.span_err(
span,
span_err!(this.tcx().sess, span, E0224,
"at least one non-builtin trait is required for an object type");
None
};
@ -1593,10 +1584,9 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
if !trait_bounds.is_empty() {
let b = &trait_bounds[0];
this.tcx().sess.span_err(
b.trait_ref.path.span,
&format!("only the builtin traits can be used \
as closure or object bounds")[]);
span_err!(this.tcx().sess, b.trait_ref.path.span, E0225,
"only the builtin traits can be used \
as closure or object bounds");
}
let region_bound = compute_region_bound(this,
@ -1633,9 +1623,8 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
builtin_bounds.repr(tcx));
if explicit_region_bounds.len() > 1 {
tcx.sess.span_err(
explicit_region_bounds[1].span,
format!("only a single explicit lifetime bound is permitted").as_slice());
span_err!(tcx.sess, explicit_region_bounds[1].span, E0226,
"only a single explicit lifetime bound is permitted");
}
if explicit_region_bounds.len() != 0 {
@ -1666,10 +1655,9 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
// error.
let r = derived_region_bounds[0];
if derived_region_bounds.slice_from(1).iter().any(|r1| r != *r1) {
tcx.sess.span_err(
span,
&format!("ambiguous lifetime bound, \
explicit lifetime bound required")[]);
span_err!(tcx.sess, span, E0227,
"ambiguous lifetime bound, \
explicit lifetime bound required");
}
return Some(r);
}
@ -1693,9 +1681,8 @@ fn compute_region_bound<'tcx>(
match rscope.default_region_bound(span) {
Some(r) => { r }
None => {
this.tcx().sess.span_err(
span,
&format!("explicit lifetime bound required")[]);
span_err!(this.tcx().sess, span, E0228,
"explicit lifetime bound required");
ty::ReStatic
}
}
@ -1779,8 +1766,7 @@ fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>,
bindings: &[ConvertedBinding<'tcx>])
{
for binding in bindings.iter().take(1) {
tcx.sess.span_err(
binding.span,
span_err!(tcx.sess, binding.span, E0229,
"associated type bindings are not allowed here");
}
}

View File

@ -50,10 +50,9 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
check_unboxed_closure(fcx, expr, kind, decl, body, None);
fcx.ccx.tcx.sess.span_err(
expr.span,
span_err!(fcx.ccx.tcx.sess, expr.span, E0187,
"can't infer the \"kind\" of the closure, explicitly annotate it. e.g. \
`|&:| {}`");
`|&:| {{}}`");
},
Some((sig, kind)) => {
check_unboxed_closure(fcx, expr, kind, decl, body, Some(sig));

View File

@ -59,23 +59,21 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
(&ty::StaticExplicitSelfCategory,
&ty::StaticExplicitSelfCategory) => {}
(&ty::StaticExplicitSelfCategory, _) => {
tcx.sess.span_err(
impl_m_span,
format!("method `{}` has a `{}` declaration in the impl, \
span_err!(tcx.sess, impl_m_span, E0185,
"method `{}` has a `{}` declaration in the impl, \
but not in the trait",
token::get_name(trait_m.name),
ppaux::explicit_self_category_to_str(
&impl_m.explicit_self)).as_slice());
&impl_m.explicit_self));
return;
}
(_, &ty::StaticExplicitSelfCategory) => {
tcx.sess.span_err(
impl_m_span,
format!("method `{}` has a `{}` declaration in the trait, \
span_err!(tcx.sess, impl_m_span, E0186,
"method `{}` has a `{}` declaration in the trait, \
but not in the impl",
token::get_name(trait_m.name),
ppaux::explicit_self_category_to_str(
&trait_m.explicit_self)).as_slice());
&trait_m.explicit_self));
return;
}
_ => {
@ -400,11 +398,10 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
// are zero. Since I don't quite know how to phrase things at
// the moment, give a kind of vague error message.
if trait_params.len() != impl_params.len() {
tcx.sess.span_err(
span,
&format!("lifetime parameters or bounds on method `{}` do \
span_err!(tcx.sess, span, E0195,
"lifetime parameters or bounds on method `{}` do \
not match the trait declaration",
token::get_name(impl_m.name))[]);
token::get_name(impl_m.name));
return false;
}

View File

@ -801,16 +801,15 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}) {
Some(_) => (),
None => {
ccx.tcx.sess.span_err(attr.span,
format!("there is no type parameter \
span_err!(ccx.tcx.sess, attr.span, E0230,
"there is no type parameter \
{} on trait {}",
s, item.ident.as_str())
.as_slice());
s, item.ident.as_str());
}
},
// `{:1}` and `{}` are not to be used
Position::ArgumentIs(_) | Position::ArgumentNext => {
ccx.tcx.sess.span_err(attr.span,
span_err!(ccx.tcx.sess, attr.span, E0231,
"only named substitution \
parameters are allowed");
}
@ -818,7 +817,7 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}
}
} else {
ccx.tcx.sess.span_err(attr.span,
span_err!(ccx.tcx.sess, attr.span, E0232,
"this attribute must have a value, \
eg `#[rustc_on_unimplemented = \"foo\"]`")
}
@ -2099,8 +2098,8 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
Ok(trait_did) => trait_did,
Err(ref err_string) => {
fcx.tcx().sess.span_err(iterator_expr.span,
&err_string[]);
span_err!(fcx.tcx().sess, iterator_expr.span, E0233,
"{}", &err_string[]);
return fcx.tcx().types.err
}
};
@ -2123,11 +2122,10 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
if !ty::type_is_error(true_expr_type) {
let ty_string = fcx.infcx().ty_to_string(true_expr_type);
fcx.tcx().sess.span_err(iterator_expr.span,
&format!("`for` loop expression has type `{}` which does \
span_err!(fcx.tcx().sess, iterator_expr.span, E0234,
"`for` loop expression has type `{}` which does \
not implement the `Iterator` trait; \
maybe try .iter()",
ty_string)[]);
maybe try .iter()", ty_string);
}
fcx.tcx().types.err
}
@ -2162,11 +2160,10 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
fcx.tcx().types.err
}
_ => {
fcx.tcx().sess.span_err(iterator_expr.span,
&format!("`next` method of the `Iterator` \
span_err!(fcx.tcx().sess, iterator_expr.span, E0239,
"`next` method of the `Iterator` \
trait has an unexpected type `{}`",
fcx.infcx().ty_to_string(return_type))
[]);
fcx.infcx().ty_to_string(return_type));
fcx.tcx().types.err
}
}
@ -3880,10 +3877,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
Err(type_error) => {
let type_error_description =
ty::type_err_to_str(tcx, &type_error);
fcx.tcx()
.sess
.span_err(path.span,
&format!("structure constructor specifies a \
span_err!(fcx.tcx().sess, path.span, E0235,
"structure constructor specifies a \
structure of type `{}`, but this \
structure has type `{}`: {}",
fcx.infcx()
@ -3891,7 +3886,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
fcx.infcx()
.ty_to_string(
actual_structure_type),
type_error_description)[]);
type_error_description);
ty::note_and_explain_type_err(tcx, &type_error);
}
}
@ -4012,7 +4007,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
ty::mk_struct(tcx, did, tcx.mk_substs(substs))
} else {
tcx.sess.span_err(expr.span, "No lang item for range syntax");
span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
fcx.tcx().types.err
}
}
@ -4022,7 +4017,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
let substs = Substs::new_type(vec![], vec![]);
ty::mk_struct(tcx, did, tcx.mk_substs(substs))
} else {
tcx.sess.span_err(expr.span, "No lang item for range syntax");
span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
fcx.tcx().types.err
}
}
@ -4872,8 +4867,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
ast::ParenthesizedParameters(ref data) => {
fcx.tcx().sess.span_err(
span,
span_err!(fcx.tcx().sess, span, E0238,
"parenthesized parameters may only be used with a trait");
push_explicit_parenthesized_parameters_from_segment_to_substs(
fcx, space, span, type_defs, data, substs);
@ -5230,7 +5224,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
"get_tydesc" => {
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
Ok(t) => t,
Err(s) => { tcx.sess.span_fatal(it.span, &s[]); }
Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[]); }
};
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
ty: tydesc_ty,

View File

@ -51,7 +51,7 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
{
let object_trait = object_trait(&object_trait_ty);
if !mutability_allowed(referent_mutbl, target_mutbl) {
fcx.tcx().sess.span_err(source_expr.span,
span_err!(fcx.tcx().sess, source_expr.span, E0188,
"types differ in mutability");
} else {
// Ensure that if &'a T is cast to &'b Trait, then T : Trait
@ -70,19 +70,17 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
(_, &ty::ty_uniq(..)) => {
fcx.ccx.tcx.sess.span_err(
source_expr.span,
&format!("can only cast an boxed pointer \
span_err!(fcx.ccx.tcx.sess, source_expr.span, E0189,
"can only cast a boxed pointer \
to a boxed object, not a {}",
ty::ty_sort_string(fcx.tcx(), source_ty))[]);
ty::ty_sort_string(fcx.tcx(), source_ty));
}
(_, &ty::ty_rptr(..)) => {
fcx.ccx.tcx.sess.span_err(
source_expr.span,
&format!("can only cast a &-pointer \
span_err!(fcx.ccx.tcx.sess, source_expr.span, E0190,
"can only cast a &-pointer \
to an &-object, not a {}",
ty::ty_sort_string(fcx.tcx(), source_ty))[]);
ty::ty_sort_string(fcx.tcx(), source_ty));
}
_ => {
@ -272,11 +270,10 @@ fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>,
}
for (trait_def_id, name) in associated_types.into_iter() {
tcx.sess.span_err(
span,
format!("the value of the associated type `{}` (from the trait `{}`) must be specified",
span_err!(tcx.sess, span, E0191,
"the value of the associated type `{}` (from the trait `{}`) must be specified",
name.user_string(tcx),
ty::item_path_str(tcx, trait_def_id)).as_slice());
ty::item_path_str(tcx, trait_def_id));
}
}

View File

@ -81,10 +81,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
Some(ty::BoundSend) | Some(ty::BoundSync) => {}
Some(_) | None => {
ccx.tcx.sess.span_err(
item.span,
format!("negative impls are currently \
allowed just for `Send` and `Sync`").as_slice())
span_err!(ccx.tcx.sess, item.span, E0192,
"negative impls are currently \
allowed just for `Send` and `Sync`")
}
}
}
@ -302,12 +301,11 @@ fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
fn report_bound_error<'t>(tcx: &ty::ctxt<'t>,
span: Span,
bounded_ty: ty::Ty<'t>) {
tcx.sess.span_err(
span,
format!("cannot bound type `{}`, where clause \
span_err!(tcx.sess, span, E0193,
"cannot bound type `{}`, where clause \
bounds may only be attached to types involving \
type parameters",
bounded_ty.repr(tcx)).as_slice())
bounded_ty.repr(tcx))
}
fn is_ty_param(ty: ty::Ty) -> bool {
@ -326,10 +324,9 @@ fn reject_shadowing_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>,
for method_param in generics.types.get_slice(subst::FnSpace).iter() {
if impl_params.contains(&method_param.name) {
tcx.sess.span_err(
span,
&*format!("type parameter `{}` shadows another type parameter of the same name",
token::get_name(method_param.name)));
span_err!(tcx.sess, span, E0194,
"type parameter `{}` shadows another type parameter of the same name",
token::get_name(method_param.name));
}
}
}

View File

@ -416,7 +416,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
ResolvingUnboxedClosure(_) => {
let span = self.reason.span(self.tcx);
self.tcx.sess.span_err(span,
span_err!(self.tcx.sess, span, E0196,
"cannot determine a type for this \
unboxed closure")
}

View File

@ -34,10 +34,9 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> {
match trait_ref.self_ty().sty {
ty::ty_struct(..) | ty::ty_enum(..) => {}
_ => {
self.tcx.sess.span_err(
item.span,
&format!("builtin traits can only be \
implemented on structs or enums")[]);
span_err!(self.tcx.sess, item.span, E0209,
"builtin traits can only be \
implemented on structs or enums");
}
}
}

View File

@ -490,24 +490,21 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
match ty::can_type_implement_copy(&param_env, span, self_type) {
Ok(()) => {}
Err(ty::FieldDoesNotImplementCopy(name)) => {
tcx.sess
.span_err(span,
&format!("the trait `Copy` may not be \
span_err!(tcx.sess, span, E0204,
"the trait `Copy` may not be \
implemented for this type; field \
`{}` does not implement `Copy`",
token::get_name(name))[])
token::get_name(name))
}
Err(ty::VariantDoesNotImplementCopy(name)) => {
tcx.sess
.span_err(span,
&format!("the trait `Copy` may not be \
span_err!(tcx.sess, span, E0205,
"the trait `Copy` may not be \
implemented for this type; variant \
`{}` does not implement `Copy`",
token::get_name(name))[])
token::get_name(name))
}
Err(ty::TypeIsStructural) => {
tcx.sess
.span_err(span,
span_err!(tcx.sess, span, E0206,
"the trait `Copy` may not be implemented \
for this type; type is not a structure or \
enumeration")

View File

@ -89,13 +89,11 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
}
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
self.tcx.sess.span_err(
item.span,
format!(
span_err!(self.tcx.sess, item.span, E0210,
"type parameter `{}` is not constrained by any local type; \
only traits defined in the current crate can be implemented \
for a type parameter",
param_ty.user_string(self.tcx)).as_slice());
param_ty.user_string(self.tcx));
self.tcx.sess.span_note(
item.span,
format!("for a limited time, you can add \

View File

@ -37,8 +37,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
match unsafety {
ast::Unsafety::Normal => { /* OK */ }
ast::Unsafety::Unsafe => {
self.tcx.sess.span_err(
item.span,
span_err!(self.tcx.sess, item.span, E0197,
"inherent impls cannot be declared as unsafe");
}
}
@ -49,24 +48,21 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
match (trait_def.unsafety, unsafety, polarity) {
(ast::Unsafety::Unsafe,
ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
self.tcx.sess.span_err(
item.span,
format!("negative implementations are not unsafe").as_slice());
span_err!(self.tcx.sess, item.span, E0198,
"negative implementations are not unsafe");
}
(ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
self.tcx.sess.span_err(
item.span,
format!("implementing the trait `{}` is not unsafe",
trait_ref.user_string(self.tcx)).as_slice());
span_err!(self.tcx.sess, item.span, E0199,
"implementing the trait `{}` is not unsafe",
trait_ref.user_string(self.tcx));
}
(ast::Unsafety::Unsafe,
ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
self.tcx.sess.span_err(
item.span,
format!("the trait `{}` requires an `unsafe impl` declaration",
trait_ref.user_string(self.tcx)).as_slice());
span_err!(self.tcx.sess, item.span, E0200,
"the trait `{}` requires an `unsafe impl` declaration",
trait_ref.user_string(self.tcx));
}
(ast::Unsafety::Unsafe,

View File

@ -452,7 +452,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
let mut seen_methods = FnvHashSet();
for m in ms {
if !seen_methods.insert(m.pe_ident().repr(tcx)) {
tcx.sess.span_err(m.span, "duplicate method in trait impl");
span_err!(tcx.sess, m.span, E0201, "duplicate method in trait impl");
}
let m_def_id = local_def(m.id);
@ -608,7 +608,7 @@ fn convert(ccx: &CollectCtxt, it: &ast::Item) {
}
ast::TypeImplItem(ref typedef) => {
if opt_trait_ref.is_none() {
tcx.sess.span_err(typedef.span,
span_err!(tcx.sess, typedef.span, E0202,
"associated items are not allowed in inherent impls");
}
@ -1160,7 +1160,8 @@ fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
assert!(ptr.bound_lifetimes.is_empty());
unbound = Some(ptr.trait_ref.clone());
} else {
ccx.tcx.sess.span_err(span, "type parameter has more than one relaxed default \
span_err!(ccx.tcx.sess, span, E0203,
"type parameter has more than one relaxed default \
bound, only one is supported");
}
}
@ -1690,11 +1691,10 @@ fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
impl trait, self type, or predicates",
param_ty.user_string(tcx)).as_slice());
} else {
tcx.sess.span_err(
ty_param.span,
format!("the type parameter `{}` is not constrained by the \
span_err!(tcx.sess, ty_param.span, E0207,
"the type parameter `{}` is not constrained by the \
impl trait, self type, or predicates",
param_ty.user_string(tcx)).as_slice());
param_ty.user_string(tcx));
tcx.sess.span_help(
ty_param.span,
format!("you can temporarily opt out of this rule by placing \

View File

@ -10,38 +10,7 @@
#![allow(non_snake_case)]
register_diagnostic! {
E0001,
r##"
This error suggests that the expression arm corresponding to the noted pattern
will never be reached as for all possible values of the expression being matched,
one of the preceeding patterns will match.
This means that perhaps some of the preceeding patterns are too general, this
one is too specific or the ordering is incorrect.
"## }
register_diagnostics! {
E0002,
E0003,
E0004,
E0005,
E0006,
E0007,
E0008,
E0009,
E0010,
E0011,
E0012,
E0013,
E0014,
E0015,
E0016,
E0017,
E0018,
E0019,
E0020,
E0022,
E0023,
E0024,
E0025,
@ -61,12 +30,9 @@ register_diagnostics! {
E0046,
E0049,
E0050,
E0051,
E0052,
E0053,
E0054,
E0055,
E0056,
E0057,
E0059,
E0060,
@ -101,16 +67,12 @@ register_diagnostics! {
E0092,
E0093,
E0094,
E0100,
E0101,
E0102,
E0103,
E0104,
E0106,
E0107,
E0108,
E0109,
E0110,
E0116,
E0117,
E0118,
@ -125,38 +87,92 @@ register_diagnostics! {
E0130,
E0131,
E0132,
E0133,
E0134,
E0135,
E0136,
E0137,
E0138,
E0139,
E0140,
E0141,
E0152,
E0153,
E0157,
E0158,
E0159,
E0161,
E0162,
E0163,
E0164,
E0165,
E0166,
E0167,
E0168,
E0169,
E0171,
E0172,
E0173, // manual implementations of unboxed closure traits are experimental
E0174, // explicit use of unboxed closure methods are experimental
E0177,
E0178,
E0180,
E0181,
E0182,
E0183,
E0184
E0184,
E0185,
E0186,
E0187, // can't infer the kind of the closure
E0188, // types differ in mutability
E0189, // can only cast a boxed pointer to a boxed object
E0190, // can only cast a &-pointer to an &-object
E0191, // value of the associated type must be specified
E0192, // negative imples are allowed just fo `Send` and `Sync`
E0193, // cannot bound type where clause bounds may only be attached to types
// involving type parameters
E0194,
E0195, // lifetime parameters or bounds on method do not match the trait declaration
E0196, // cannot determine a type for this unboxed closure
E0197, // inherent impls cannot be declared as unsafe
E0198, // negative implementations are not unsafe
E0199, // implementing trait is not unsafe
E0200, // trait requires an `unsafe impl` declaration
E0201, // duplicate method in trait impl
E0202, // associated items are not allowed in inherint impls
E0203, // type parameter has more than one relaxed default bound,
// and only one is supported
E0204, // trait `Copy` may not be implemented for this type; field
// does not implement `Copy`
E0205, // trait `Copy` may not be implemented for this type; variant
// does not implement `copy`
E0206, // trait `Copy` may not be implemented for this type; type is
// not a structure or enumeration
E0207, // type parameter is not constrained by the impl trait, self type, or predicate
E0208,
E0209, // builtin traits can only be implemented on structs or enums
E0210, // type parameter is not constrained by any local type
E0211,
E0212, // cannot extract an associated type from a higher-ranked trait bound
E0213, // associated types are not accepted in this context
E0214, // parenthesized parameters may only be used with a trait
E0215, // angle-bracket notation is not stable with `Fn`
E0216, // parenthetical notation is only stable with `Fn`
E0217, // ambiguous associated type, defined in multiple supertraits
E0218, // no associated type defined
E0219, // associated type defined in higher-ranked supertrait
E0220, // associated type not found for type parameter
E0221, // ambiguous associated type in bounds
E0222, // variadic function must have C calling convention
E0223, // ambiguous associated type
E0224, // at least one non-builtin train is required for an object type
E0225, // only the builtin traits can be used as closure or object bounds
E0226, // only a single explicit lifetime bound is permitted
E0227, // ambiguous lifetime bound, explicit lifetime bound required
E0228, // explicit lifetime bound required
E0229, // associated type bindings are not allowed here
E0230, // there is no type parameter on trait
E0231, // only named substitution parameters are allowed
E0232, // this attribute must have a value
E0233,
E0234, // `for` loop expression has type which does not implement the `Iterator` trait
E0235, // structure constructor specifies a structure of type but
E0236, // no lang item for range syntax
E0237, // no lang item for range syntax
E0238, // parenthesized parameters may only be used with a trait
E0239, // `next` method of `Iterator` trait has unexpected type
E0240,
E0241,
E0242, // internal error looking up a definition
E0243, // wrong number of type arguments
E0244, // wrong number of type arguments
E0245, // not a trait
E0246, // illegal recursive type
E0247, // found module name used as a type
E0248, // found value name used as a type
E0249, // expected constant expr for array length
E0250 // expected constant expr for array length
}
__build_diagnostic_array! { DIAGNOSTICS }

View File

@ -111,6 +111,10 @@ use syntax::ast_util::local_def;
use std::cell::RefCell;
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;
mod check;
mod rscope;
mod astconv;
@ -158,7 +162,7 @@ fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
match tcx.def_map.borrow().get(&id) {
Some(x) => x.clone(),
_ => {
tcx.sess.span_fatal(sp, "internal error looking up a definition")
span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
}
}
}
@ -202,11 +206,11 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
match result {
Ok(_) => true,
Err(ref terr) => {
tcx.sess.span_err(span,
&format!("{}: {}",
span_err!(tcx.sess, span, E0211,
"{}: {}",
msg(),
ty::type_err_to_str(tcx,
terr))[]);
terr));
ty::note_and_explain_type_err(tcx, terr);
false
}

View File

@ -1055,7 +1055,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
// attribute and report an error with various results if found.
if ty::has_attr(tcx, item_def_id, "rustc_variance") {
let found = item_variances.repr(tcx);
tcx.sess.span_err(tcx.map.span(item_id), &found[]);
span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{}", &found[]);
}
let newly_added = tcx.item_variance_map.borrow_mut()

View File

@ -92,6 +92,10 @@ impl SpanHandler {
self.handler.emit(Some((&self.cm, sp)), msg, Fatal);
panic!(FatalError);
}
pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! {
self.handler.emit_with_code(Some((&self.cm, sp)), msg, code, Fatal);
panic!(FatalError);
}
pub fn span_err(&self, sp: Span, msg: &str) {
self.handler.emit(Some((&self.cm, sp)), msg, Error);
self.handler.bump_err_count();

View File

@ -14,6 +14,14 @@ macro_rules! register_diagnostic {
($code:tt) => (__register_diagnostic! { $code })
}
#[macro_export]
macro_rules! span_fatal {
($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
__diagnostic_used!($code);
$session.span_fatal_with_code($span, format!($($message)*).as_slice(), stringify!($code))
})
}
#[macro_export]
macro_rules! span_err {
($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
@ -51,3 +59,9 @@ macro_rules! register_diagnostics {
)
}
#[macro_export]
macro_rules! register_long_diagnostics {
($($code:tt: $description:tt),*) => (
$(register_diagnostic! { $code, $description })*
)
}

View File

@ -65,6 +65,13 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt,
}
()
});
with_registered_diagnostics(|diagnostics| {
if !diagnostics.contains_key(&code.name) {
ecx.span_err(span, &format!(
"used diagnostic code {} not registered", token::get_ident(code).get()
)[]);
}
});
MacExpr::new(quote_expr!(ecx, ()))
}

View File

@ -44,7 +44,7 @@ fn basic_sess(sysroot: Path) -> Session {
opts.output_types = vec![OutputTypeExe];
opts.maybe_sysroot = Some(sysroot);
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
let descriptions = Registry::new(&rustc::diagnostics::DIAGNOSTICS);
let sess = build_session(opts, None, descriptions);
sess
}