about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Sproul <micsproul@gmail.com>2015-04-30 17:32:20 +1000
committerMichael Sproul <micsproul@gmail.com>2015-04-30 20:24:30 +1000
commit63e63218a123bbda1ed47cbe5e8bac62b7e48e97 (patch)
treeedf966010605114bfa793ca126d91f12d9b601cd
parentf0bd14f7b15b978f8bf32bb368f63faa0f26c02e (diff)
downloadrust-63e63218a123bbda1ed47cbe5e8bac62b7e48e97.tar.gz
rust-63e63218a123bbda1ed47cbe5e8bac62b7e48e97.zip
Add long diagnostics for enum repr errors.
-rw-r--r--src/librustc/diagnostics.rs27
-rw-r--r--src/librustc/middle/ty.rs4
-rw-r--r--src/librustc_typeck/diagnostics.rs83
3 files changed, 107 insertions, 7 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 7fbe89648d5..7e4f97ca698 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -221,6 +221,31 @@ 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.
 "##,
 
+E0079: r##"
+Enum variants which contain no data can be given a custom integer
+representation. This error indicates that the value provided is not an
+integer literal and is therefore invalid.
+"##,
+
+E0080: r##"
+This error indicates that the compiler was unable to sensibly evaluate an
+integer expression provided as an enum discriminant. Attempting to divide by 0
+or causing integer overflow are two ways to induce this error. For example:
+
+```
+enum Enum {
+    X = (1 << 500),
+    Y = (1 / 0)
+}
+```
+
+Ensure that the expressions given can be evaluated as the desired integer type.
+See the FFI section of the Reference for more information about using a custom
+integer type:
+
+http://doc.rust-lang.org/reference.html#ffi-attributes
+"##,
+
 E0133: r##"
 Using unsafe functionality, such as dereferencing raw pointers and calling
 functions via FFI or marked as unsafe, is potentially dangerous and disallowed
@@ -502,8 +527,6 @@ register_diagnostics! {
     E0017,
     E0019,
     E0022,
-    E0079, // enum variant: expected signed integer constant
-    E0080, // enum variant: constant evaluation error
     E0109,
     E0110,
     E0134,
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 33ba21bc7b1..5f9e282bc53 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -5732,8 +5732,10 @@ fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>,
                     Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
                     Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
                     Ok(_) => {
+                        let sign_desc = if repr_type.is_signed() { "signed" } else { "unsigned" };
                         span_err!(cx.sess, e.span, E0079,
-                                  "expected signed integer constant");
+                                  "expected {} integer constant",
+                                  sign_desc);
                         current_disr_val = attempt_fresh_value();
                     }
                     Err(ref err) => {
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 0af19e445f2..154d824e678 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -10,6 +10,85 @@
 
 #![allow(non_snake_case)]
 
+register_long_diagnostics! {
+
+E0081: r##"
+Enum discriminants are used to differentiate enum variants stored in memory.
+This error indicates that the same value was used for two or more variants,
+making them impossible to tell apart.
+
+```
+// Good.
+enum Enum {
+    P,
+    X = 3,
+    Y = 5
+}
+
+// Bad.
+enum Enum {
+    P = 3,
+    X = 3,
+    Y = 5
+}
+```
+
+Note that variants without a manually specified discriminant are numbered from
+top to bottom starting from 0, so clashes can occur with seemingly unrelated
+variants.
+
+```
+enum Bad {
+    X,
+    Y = 0
+}
+```
+
+Here `X` will have already been assigned the discriminant 0 by the time `Y` is
+encountered, so a conflict occurs.
+"##,
+
+E0082: r##"
+The default type for enum discriminants is `isize`, but it can be adjusted by
+adding the `repr` attribute to the enum declaration. This error indicates that
+an integer literal given as a discriminant is not a member of the discriminant
+type. For example:
+
+```
+#[repr(u8)]
+enum Thing {
+    A = 1024,
+    B = 5
+}
+```
+
+Here, 1024 lies outside the valid range for `u8`, so the discriminant for `A` is
+invalid. You may want to change representation types to fix this, or else change
+invalid discriminant values so that they fit within the existing type.
+
+Note also that without a representation manually defined, the compiler will
+optimize by using the smallest integer type possible.
+"##,
+
+E0083: r##"
+At present, it's not possible to define a custom representation for an enum with
+a single variant. As a workaround you can add a `Dummy` variant.
+
+See: https://github.com/rust-lang/rust/issues/10292
+"##,
+
+E0084: r##"
+It is impossible to define an integer type to be used to represent zero-variant
+enum values because there are no zero-variant enum values. There is no way to
+construct an instance of the following type using only safe code:
+
+```
+enum Empty {}
+```
+"##
+
+}
+
 register_diagnostics! {
     E0023,
     E0024,
@@ -51,10 +130,6 @@ register_diagnostics! {
     E0075,
     E0076,
     E0077,
-    E0081,
-    E0082,
-    E0083,
-    E0084,
     E0085,
     E0086,
     E0087,