From dd5eed4b8136849537d1b2c8655bd29dc976d89a Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Sat, 11 Apr 2015 08:14:38 +1000 Subject: [PATCH 1/6] Validate format of extended error descriptions. --- src/libsyntax/diagnostics/plugin.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 59fe3658437bd..de7964c92303b 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -92,6 +92,18 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, } _ => unreachable!() }; + // Check that the description starts and ends with a newline. + description.map(|raw_msg| { + let msg = raw_msg.as_str(); + let last = msg.len() - 1; + if &msg[0..1] != "\n" || &msg[last..] != "\n" { + ecx.span_err(span, &format!( + "description for error code {} doesn't start and end with a newline", + token::get_ident(*code) + )); + } + raw_msg + }); with_registered_diagnostics(|diagnostics| { if diagnostics.insert(code.name, description).is_some() { ecx.span_err(span, &format!( From c54f43a5d18c89f65f22a179e8e6d05ce9c1d36c Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 15 Apr 2015 18:12:28 +1000 Subject: [PATCH 2/6] Update/add messages for E0{267,268,296,303}. --- src/librustc/diagnostics.rs | 39 +++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index e1eb8d7418695..fedcd582cd990 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -217,6 +217,26 @@ use Method::*; enum Method { GET, POST } "##, +E0267: r##" +This error indicates the use of loop keyword (break or continue) inside a +closure but outside of any loop. Break and continue can be used as normal +inside closures as long as they are also contained within a loop. To halt the +execution of a closure you should instead use a return statement. +"##, + +E0268: r##" +This error indicates the use of loop keyword (break or continue) outside of a +loop. Without a loop to break out of or continue in, no sensible action can be +taken. +"##, + +E0296: r##" +This error indicates that the given recursion limit could not be parsed. Ensure +that the value provided is a positive integer between quotes, like so: + +#![recursion_limit="1000"] +"##, + E0297: r##" Patterns used to bind names must be irrefutable. That is, they must guarantee that a name will be extracted in all cases. Instead of pattern matching the @@ -277,21 +297,23 @@ In certain cases it is possible for sub-bindings to violate memory safety. Updates to the borrow checker in a future version of Rust may remove this restriction, but for now patterns must be rewritten without sub-bindings. -// Code like this... -match Some(5) { - ref op_num @ Some(num) => ... +// Before. +match Some("hi".to_string()) { + ref op_string_ref @ Some(ref s) => ... None => ... } -// ... should be updated to code like this. -match Some(5) { - Some(num) => { - let op_num = &Some(num); +// After. +match Some("hi".to_string()) { + Some(ref s) => { + let op_string_ref = &Some(&s); ... } None => ... } +The `op_string_ref` binding has type &Option<&String> in both cases. + See also https://github.com/rust-lang/rust/issues/14587 "##, @@ -338,8 +360,6 @@ register_diagnostics! { 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 @@ -357,7 +377,6 @@ register_diagnostics! { E0283, // cannot resolve type E0284, // cannot resolve type E0285, // overflow evaluation builtin bounds - E0296, // malformed recursion limit attribute E0298, // mismatched types between arms E0299, // mismatched types between arms E0300, // unexpanded macro From 6d2b6d5a19224eee279c44e8ff2bb37ba331d1df Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 15 Apr 2015 21:54:01 +1000 Subject: [PATCH 3/6] Enforce 80 char lines in extended errors. --- src/librustc/diagnostics.rs | 14 ++++++++------ src/libsyntax/diagnostics/plugin.rs | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index fedcd582cd990..092d0cc442402 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -55,15 +55,17 @@ underscore `_` wildcard pattern can be added after all other patterns to match // 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. +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. +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. "##, E0007: r##" diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index de7964c92303b..6fcf39f0b174b 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -20,6 +20,9 @@ use parse::token; use ptr::P; use util::small_vector::SmallVector; +// Maximum width of any line in an extended error description (inclusive). +const MAX_DESCRIPTION_WIDTH: usize = 80; + thread_local! { static REGISTERED_DIAGNOSTICS: RefCell>> = { RefCell::new(BTreeMap::new()) @@ -92,16 +95,22 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, } _ => unreachable!() }; - // Check that the description starts and ends with a newline. + // Check that the description starts and ends with a newline and doesn't + // overflow the maximum line width. description.map(|raw_msg| { let msg = raw_msg.as_str(); - let last = msg.len() - 1; - if &msg[0..1] != "\n" || &msg[last..] != "\n" { + if !msg.starts_with("\n") || !msg.ends_with("\n") { ecx.span_err(span, &format!( "description for error code {} doesn't start and end with a newline", token::get_ident(*code) )); } + if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH) { + ecx.span_err(span, &format!( + "description for error code {} contains a line longer than {} characters", + token::get_ident(*code), MAX_DESCRIPTION_WIDTH + )); + } raw_msg }); with_registered_diagnostics(|diagnostics| { From 22ce069c7e4e008d4835a669b85bee3d93a84172 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Thu, 16 Apr 2015 00:46:41 -0500 Subject: [PATCH 4/6] Add long diagnostics for E0020 --- src/librustc/diagnostics.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 092d0cc442402..4f1fc4150fd47 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -114,6 +114,11 @@ reference when using guards or refactor the entire expression, perhaps by putting the condition inside the body of the arm. "##, +E0020: r##" +This error indicates that an attempt was made to divide by zero (or take the +remainder of a zero divisor) in a static or constant expression. +"##, + E0152: r##" Lang items are already implemented in the standard library. Unless you are writing a free-standing application (e.g. a kernel), you do not need to provide @@ -343,7 +348,6 @@ register_diagnostics! { E0017, E0018, E0019, - E0020, E0022, E0079, // enum variant: expected signed integer constant E0080, // enum variant: constant evaluation error From 017bc44712b94d22165672fd546b7e084fc3b404 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Thu, 16 Apr 2015 00:47:31 -0500 Subject: [PATCH 5/6] Add long diagnostics for E0015 --- src/librustc/diagnostics.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 4f1fc4150fd47..24d920077d628 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -114,6 +114,12 @@ reference when using guards or refactor the entire expression, perhaps by putting the condition inside the body of the arm. "##, +E0015: r##" +The only function calls allowed in static or constant expressions are enum +variant constructors or struct constructors (for unit or tuple structs). This +is because Rust currently does not support compile-time function execution. +"##, + E0020: r##" This error indicates that an attempt was made to divide by zero (or take the remainder of a zero divisor) in a static or constant expression. @@ -343,7 +349,6 @@ register_diagnostics! { E0012, E0013, E0014, - E0015, E0016, E0017, E0018, From 50f75f3e2a4b8cb5451acb15f8d469a222dafbf4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Apr 2015 12:31:56 +0200 Subject: [PATCH 6/6] Add long diagnostics for "bind by-ref and by-move" --- src/librustc/diagnostics.rs | 49 ++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 24d920077d628..306d2cd102fdb 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -114,6 +114,54 @@ reference when using guards or refactor the entire expression, perhaps by putting the condition inside the body of the arm. "##, +E0009: r##" +In a pattern, all values that don't implement the `Copy` trait have to be bound +the same way. The goal here is to avoid binding simultaneously by-move and +by-ref. + +This limitation may be removed in a future version of Rust. + +Wrong example: + +``` +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((y, ref z)) => {}, + None => panic!() +} +``` + +You have two solutions: +1. Bind the pattern's values the same way: + +``` +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((ref y, ref z)) => {}, + // or Some((y, z)) => {} + None => panic!() +} +``` + +2. Implement the `Copy` trait for the X structure (however, please +keep in mind that the first solution should be preferred!): + +``` +#[derive(Clone, Copy)] +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((y, ref z)) => {}, + None => panic!() +} +``` +"##, + E0015: r##" The only function calls allowed in static or constant expressions are enum variant constructors or struct constructors (for unit or tuple structs). This @@ -343,7 +391,6 @@ a compile-time constant. } register_diagnostics! { - E0009, E0010, E0011, E0012,