Auto merge of #25688 - nham:E0055_E0192, r=alexcrichton

- Adds explanations for E0055, E0089, E0192, E0261-E0263, E0318
 - Improves explanations for E0250, E0368, E0372.
 - Converts 15 diagnostics to have error codes (E0380-E0394). Adds an explanation for E0380.
 - The E0087-E0090 messages currently look like "expected {} parameter(s) found {} parameter(s)". This changes them to either use "parameter" or "parameters", based on the number.

This is, in part, more progress towards #24407
This commit is contained in:
bors 2015-05-26 23:10:06 +00:00
commit fe85342ef6
13 changed files with 241 additions and 96 deletions

View File

@ -396,6 +396,54 @@ enum Method { GET, POST }
```
"##,
E0261: r##"
When using a lifetime like `'a` in a type, it must be declared before being
used.
These two examples illustrate the problem:
```
// error, use of undeclared lifetime name `'a`
fn foo(x: &'a str) { }
struct Foo {
// error, use of undeclared lifetime name `'a`
x: &'a str,
}
```
These can be fixed by declaring lifetime parameters:
```
fn foo<'a>(x: &'a str) { }
struct Foo<'a> {
x: &'a str,
}
```
"##,
E0262: r##"
Declaring certain lifetime names in parameters is disallowed. For example,
because the `'static` lifetime is a special built-in lifetime name denoting
the lifetime of the entire program, this is an error:
```
// error, illegal lifetime parameter name `'static`
fn foo<'static>(x: &'static str) { }
```
"##,
E0263: r##"
A lifetime name cannot be declared more than once in the same scope. For
example:
```
// error, lifetime name `'a` declared twice in the same scope
fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { }
```
"##,
E0265: r##"
This error indicates that a static or constant references itself.
All statics and constants need to resolve to a value in an acyclic manner.
@ -814,9 +862,6 @@ register_diagnostics! {
E0136,
E0138,
E0139,
E0261, // use of undeclared lifetime name
E0262, // illegal lifetime parameter name
E0263, // lifetime name declared twice in same scope
E0264, // unknown external lang item
E0266, // expected item
E0269, // not all control paths return a value
@ -846,5 +891,7 @@ register_diagnostics! {
E0315, // cannot invoke closure outside of its lifetime
E0316, // nested quantification of lifetimes
E0370, // discriminant overflow
E0378 // method calls limited to constant inherent methods
E0378, // method calls limited to constant inherent methods
E0394 // cannot refer to other statics by value, use the address-of
// operator or a constant instead
}

View File

@ -762,9 +762,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
// statics cannot be consumed by value at any time, that would imply
// that they're an initializer (what a const is for) or kept in sync
// over time (not feasible), so deny it outright.
self.tcx.sess.span_err(consume_span,
"cannot refer to other statics by value, use the \
address-of operator or a constant instead");
span_err!(self.tcx.sess, consume_span, E0394,
"cannot refer to other statics by value, use the \
address-of operator or a constant instead");
}
break;
}

View File

@ -603,11 +603,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
let (ol, moved_lp_msg) = match the_move.kind {
move_data::Declared => {
self.tcx.sess.span_err(
use_span,
&format!("{} of possibly uninitialized variable: `{}`",
verb,
self.loan_path_to_string(lp)));
span_err!(
self.tcx.sess, use_span, E0381,
"{} of possibly uninitialized variable: `{}`",
verb,
self.loan_path_to_string(lp));
(self.loan_path_to_string(moved_lp),
String::new())
}
@ -644,12 +645,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
let msg = if !has_fork && partial { "partially " }
else if has_fork && !has_common { "collaterally "}
else { "" };
self.tcx.sess.span_err(
use_span,
&format!("{} of {}moved value: `{}`",
verb,
msg,
nl));
span_err!(
self.tcx.sess, use_span, E0382,
"{} of {}moved value: `{}`",
verb, msg, nl);
(ol, moved_lp_msg)
}
};
@ -762,12 +761,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
&self,
span: Span,
lp: &LoanPath<'tcx>) {
self.tcx
.sess
.span_err(span,
&format!("partial reinitialization of uninitialized \
structure `{}`",
self.loan_path_to_string(lp)));
span_err!(
self.tcx.sess, span, E0383,
"partial reinitialization of uninitialized structure `{}`",
self.loan_path_to_string(lp));
}
pub fn report_reassigned_immutable_variable(&self,
@ -775,10 +772,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
lp: &LoanPath<'tcx>,
assign:
&move_data::Assignment) {
self.tcx.sess.span_err(
span,
&format!("re-assignment of immutable variable `{}`",
self.loan_path_to_string(lp)));
span_err!(
self.tcx.sess, span, E0384,
"re-assignment of immutable variable `{}`",
self.loan_path_to_string(lp));
self.tcx.sess.span_note(assign.span, "prior assignment occurs here");
}
@ -896,21 +893,19 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
match cause {
mc::AliasableOther => {
self.tcx.sess.span_err(
span,
&format!("{} in an aliasable location",
prefix));
span_err!(
self.tcx.sess, span, E0385,
"{} in an aliasable location", prefix);
}
mc::AliasableReason::UnaliasableImmutable => {
self.tcx.sess.span_err(
span,
&format!("{} in an immutable container",
prefix));
span_err!(
self.tcx.sess, span, E0386,
"{} in an immutable container", prefix);
}
mc::AliasableClosure(id) => {
self.tcx.sess.span_err(span,
&format!("{} in a captured outer \
variable in an `Fn` closure", prefix));
span_err!(
self.tcx.sess, span, E0387,
"{} in a captured outer variable in an `Fn` closure", prefix);
if let BorrowViolation(euv::ClosureCapture(_)) = kind {
// The aliasability violation with closure captures can
// happen for nested closures, so we know the enclosing
@ -925,14 +920,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
mc::AliasableStatic(..) |
mc::AliasableStaticMut(..) => {
self.tcx.sess.span_err(
span,
&format!("{} in a static location", prefix));
span_err!(
self.tcx.sess, span, E0388,
"{} in a static location", prefix);
}
mc::AliasableBorrowed => {
self.tcx.sess.span_err(
span,
&format!("{} in a `&` reference", prefix));
span_err!(
self.tcx.sess, span, E0389,
"{} in a `&` reference", prefix);
}
}

View File

@ -10,6 +10,31 @@
#![allow(non_snake_case)]
register_diagnostics! {
E0373 // closure may outlive current fn, but it borrows {}, which is owned by current fn
register_long_diagnostics! {
E0381: r##"
It is not allowed to use or capture an uninitialized variable. For example:
```
fn main() {
let x: i32;
let y = x; // error, use of possibly uninitialized variable
```
To fix this, ensure that any declared variables are initialized before being
used.
"##
}
register_diagnostics! {
E0373, // closure may outlive current fn, but it borrows {}, which is owned by current fn
E0382, // use of partially/collaterally moved value
E0383, // partial reinitialization of uninitialized structure
E0384, // reassignment of immutable variable
E0385, // {} in an aliasable location
E0386, // {} in an immutable container
E0387, // {} in a captured outer variable in an `Fn` closure
E0388, // {} in a static location
E0389 // {} in a `&` reference
}

View File

@ -437,13 +437,12 @@ fn create_substs_for_ast_path<'tcx>(
// defaults. This will lead to an ICE if we are not
// careful!
if self_ty.is_none() && ty::type_has_self(default) {
tcx.sess.span_err(
span,
&format!("the type parameter `{}` must be explicitly specified \
in an object type because its default value `{}` references \
the type `Self`",
param.name.user_string(tcx),
default.user_string(tcx)));
span_err!(tcx.sess, span, E0393,
"the type parameter `{}` must be explicitly specified \
in an object type because its default value `{}` references \
the type `Self`",
param.name.user_string(tcx),
default.user_string(tcx));
substs.types.push(TypeSpace, tcx.types.err);
} else {
// This is a default type parameter.

View File

@ -4688,9 +4688,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
} else if i == type_count {
span_err!(fcx.tcx().sess, typ.span, E0087,
"too many type parameters provided: \
expected at most {} parameter(s), \
found {} parameter(s)",
type_count, data.types.len());
expected at most {} parameter{}, \
found {} parameter{}",
type_count,
if type_count == 1 {""} else {"s"},
data.types.len(),
if data.types.len() == 1 {""} else {"s"});
substs.types.truncate(space, 0);
break;
}
@ -4713,9 +4716,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
} else if i == region_count {
span_err!(fcx.tcx().sess, lifetime.span, E0088,
"too many lifetime parameters provided: \
expected {} parameter(s), found {} parameter(s)",
expected {} parameter{}, found {} parameter{}",
region_count,
data.lifetimes.len());
if region_count == 1 {""} else {"s"},
data.lifetimes.len(),
if data.lifetimes.len() == 1 {""} else {"s"});
substs.mut_regions().truncate(space, 0);
break;
}
@ -4805,9 +4810,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let qualifier =
if desired.len() != required_len { "at least " } else { "" };
span_err!(fcx.tcx().sess, span, E0089,
"too few type parameters provided: expected {}{} parameter(s) \
, found {} parameter(s)",
qualifier, required_len, provided_len);
"too few type parameters provided: expected {}{} parameter{}, \
found {} parameter{}",
qualifier, required_len,
if required_len == 1 {""} else {"s"},
provided_len,
if provided_len == 1 {""} else {"s"});
substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
return;
}
@ -4858,9 +4866,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// Otherwise, too few were provided. Report an error and then
// use inference variables.
span_err!(fcx.tcx().sess, span, E0090,
"too few lifetime parameters provided: expected {} parameter(s), \
found {} parameter(s)",
desired.len(), provided_len);
"too few lifetime parameters provided: expected {} parameter{}, \
found {} parameter{}",
desired.len(),
if desired.len() == 1 {""} else {"s"},
provided_len,
if provided_len == 1 {""} else {"s"});
substs.mut_regions().replace(
space,

View File

@ -124,10 +124,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
if ty::trait_has_default_impl(ccx.tcx, local_def(item.id)) {
if !items.is_empty() {
ccx.tcx.sess.span_err(
item.span,
"traits with default impls (`e.g. unsafe impl Trait for ..`) must \
have no methods or associated items")
span_err!(ccx.tcx.sess, item.span, E0380,
"traits with default impls (`e.g. unsafe impl \
Trait for ..`) must have no methods or associated items")
}
}
}
@ -353,10 +352,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
span: Span,
param_name: ast::Name)
{
self.tcx().sess.span_err(
span,
&format!("parameter `{}` is never used",
param_name.user_string(self.tcx())));
span_err!(self.tcx().sess, span, E0392,
"parameter `{}` is never used", param_name.user_string(self.tcx()));
let suggested_marker_id = self.tcx().lang_items.phantom_data();
match suggested_marker_id {

View File

@ -48,10 +48,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
match lang_def_id {
Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ },
_ => {
self.tcx.sess.span_err(
span,
&format!("only a single inherent implementation marked with `#[lang = \"{}\"]` \
is allowed for the `{}` primitive", lang, ty));
span_err!(self.tcx.sess, span, E0390,
"only a single inherent implementation marked with `#[lang = \"{}\"]` \
is allowed for the `{}` primitive", lang, ty);
}
}
}

View File

@ -236,9 +236,8 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
assert!(!cycle.is_empty());
let tcx = self.tcx;
tcx.sess.span_err(
span,
&format!("unsupported cyclic reference between types/traits detected"));
span_err!(tcx.sess, span, E0391,
"unsupported cyclic reference between types/traits detected");
match cycle[0] {
AstConvRequest::GetItemTypeScheme(def_id) |

View File

@ -261,6 +261,37 @@ let x_is_nonzero = x as bool;
```
"##,
E0055: r##"
During a method call, a value is automatically dereferenced as many times as
needed to make the value's type match the method's receiver. The catch is that
the compiler will only attempt to dereference a number of times up to the
recursion limit (which can be set via the `recursion_limit` attribute).
For a somewhat artificial example:
```
#![recursion_limit="2"]
struct Foo;
impl Foo {
fn foo(&self) {}
}
fn main() {
let foo = Foo;
let ref_foo = &&Foo;
// error, reached the recursion limit while auto-dereferencing &&Foo
ref_foo.foo();
}
```
One fix may be to increase the recursion limit. Note that it is possible to
create an infinite recursion of dereferencing, in which case the only fix is to
somehow break the recursion.
"##,
E0062: r##"
This error indicates that during an attempt to build a struct or struct-like
enum variant, one of the fields was specified more than once. Each field should
@ -511,6 +542,31 @@ enum Empty {}
```
"##,
E0089: r##"
Not enough type parameters were supplied for a function. For example:
```
fn foo<T, U>() {}
fn main() {
foo::<f64>(); // error, expected 2 parameters, found 1 parameter
}
```
Note that if a function takes multiple type parameters but you want the compiler
to infer some of them, you can use type placeholders:
```
fn foo<T, U>(x: T) {}
fn main() {
let x: bool = true;
foo::<f64>(x); // error, expected 2 parameters, found 1 parameter
foo::<_, f64>(x); // same as `foo::<bool, f64>(x)`
}
```
"##,
E0106: r##"
This error indicates that a lifetime is missing from a type. If it is an error
inside a function signature, the problem may be with failing to adhere to the
@ -707,6 +763,12 @@ impl Foo for Bar {
}
"##,
E0192: r##"
Negative impls are only allowed for traits with default impls. For more
information see the [opt-in builtin traits RFC](https://github.com/rust-lang/
rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
"##,
E0197: r##"
Inherent implementations (one that do not implement a trait but provide
methods associated with a type) are always safe because they are not
@ -917,10 +979,10 @@ const C: [u32; 0.0] = []; // error
"##,
E0250: r##"
This means there was an error while evaluating the expression for the length of
a fixed-size array type.
There was an error while evaluating the expression for the length of a fixed-
size array type.
Some examples of code that produces this error are:
Some examples of this error are:
```
// divide by zero in the length expression
@ -936,6 +998,12 @@ const C: [u32; u8::MAX + f64::EPSILON] = [];
```
"##,
E0318: r##"
Default impls for a trait must be located in the same crate where the trait was
defined. For more information see the [opt-in builtin traits RFC](https://github
.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
"##,
E0322: r##"
The `Sized` trait is a special trait built-in to the compiler for types with a
constant size known at compile-time. This trait is automatically implemented
@ -964,9 +1032,7 @@ impl Foo for Bar {
E0368: r##"
This error indicates that a binary assignment operator like `+=` or `^=` was
applied to the wrong types.
A couple examples of this are as follows:
applied to the wrong types. For example:
```
let mut x: u16 = 5;
@ -1029,8 +1095,13 @@ Trying to implement a trait for a trait object (as in `impl Trait1 for
Trait2 { ... }`) does not work if the trait is not object-safe. Please see the
[RFC 255] for more details on object safety rules.
[RFC 255]:https://github.com/rust-lang/rfcs/blob/master/text/0255-object-\
safety.md
[RFC 255]: https://github.com/rust-lang/rfcs/pull/255
"##,
E0380: r##"
Default impls are only allowed for traits with no methods or associated items.
For more information see the [opt-in builtin traits RFC](https://github.com/rust
-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
"##
}
@ -1045,7 +1116,6 @@ register_diagnostics! {
E0040, // explicit use of destructor method
E0044, // foreign items may not have type parameters
E0045, // variadic function must have C calling convention
E0055, // method has an incompatible type for trait
E0057, // method has an incompatible type for trait
E0059,
E0060,
@ -1060,7 +1130,6 @@ register_diagnostics! {
E0086,
E0087,
E0088,
E0089,
E0090,
E0091,
E0092,
@ -1098,7 +1167,6 @@ register_diagnostics! {
E0189, // deprecated: can only cast a boxed pointer to a boxed object
E0190, // deprecated: can only cast a &-pointer to an &-object
E0191, // value of the associated type must be specified
E0192, // negative impls are allowed just for `Send` and `Sync`
E0193, // cannot bound type where clause bounds may only be attached to types
// involving type parameters
E0194,
@ -1146,7 +1214,6 @@ register_diagnostics! {
E0246, // illegal recursive type
E0247, // found module name used as a type
E0248, // found value name used as a type
E0318, // can't create default impls for traits outside their crates
E0319, // trait impls for defaulted traits allowed just for structs/enums
E0320, // recursive overflow during dropck
E0321, // extended coherence rules for defaulted traits violated
@ -1168,5 +1235,11 @@ register_diagnostics! {
// between structures
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with the same definition
E0379 // trait fns cannot be const
E0379, // trait fns cannot be const
E0390, // only a single inherent implementation marked with
// `#[lang = \"{}\"]` is allowed for the `{}` primitive
E0391, // unsupported cyclic reference between types/traits detected
E0392, // parameter `{}` is never used
E0393 // the type parameter `{}` must be explicitly specified in an object
// type because its default value `{}` references the type `Self`"
}

View File

@ -4564,7 +4564,7 @@ impl<'a> Parser<'a> {
if try!(self.eat(&token::DotDot) ){
if generics.is_parameterized() {
self.span_err(impl_span, "default trait implementations are not \
allowed to have genercis");
allowed to have generics");
}
try!(self.expect(&token::OpenDelim(token::Brace)));

View File

@ -13,6 +13,6 @@
trait MyDefaultImpl {}
impl<T> MyDefaultImpl for .. {}
//~^ ERROR default trait implementations are not allowed to have genercis
//~^ ERROR default trait implementations are not allowed to have generics
fn main() {}

View File

@ -12,5 +12,5 @@ use std::borrow::IntoCow;
fn main() {
<String as IntoCow>::into_cow("foo".to_string());
//~^ ERROR too few type parameters provided: expected 1 parameter(s)
//~^ ERROR too few type parameters provided: expected 1 parameter
}