From 8c004b830838473651b306d15a2d74e1cae19785 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Thu, 17 May 2018 21:17:53 +0200
Subject: [PATCH] Add E0665

---
 src/libsyntax_ext/asm.rs              | 11 --------
 src/libsyntax_ext/deriving/default.rs |  4 +--
 src/libsyntax_ext/deriving/mod.rs     | 11 ++++++++
 src/libsyntax_ext/diagnostics.rs      | 36 ++++++++++++++++++++++++++-
 src/libsyntax_ext/lib.rs              |  8 +++---
 src/test/ui/E0665.rs                  | 20 +++++++++++++++
 src/test/ui/E0665.stderr              |  9 +++++++
 7 files changed, 82 insertions(+), 17 deletions(-)
 create mode 100644 src/test/ui/E0665.rs
 create mode 100644 src/test/ui/E0665.stderr

diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 369c5b1ff60db..9a0eb2ef30e49 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -45,17 +45,6 @@ impl State {
     }
 }
 
-macro_rules! span_err_if_not_stage0 {
-    ($cx:expr, $sp:expr, $code:ident, $text:tt) => {
-        #[cfg(not(stage0))] {
-            span_err!($cx, $sp, $code, $text)
-        }
-        #[cfg(stage0)] {
-            $cx.span_err($sp, $text)
-        }
-    }
-}
-
 const OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
 
 pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs
index 99e7bb4baeff4..cbd6a257b77e8 100644
--- a/src/libsyntax_ext/deriving/default.rs
+++ b/src/libsyntax_ext/deriving/default.rs
@@ -76,8 +76,8 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
             }
         }
         StaticEnum(..) => {
-            cx.span_err(trait_span,
-                        "`Default` cannot be derived for enums, only structs");
+            span_err_if_not_stage0!(cx, trait_span, E0665,
+                                    "`Default` cannot be derived for enums, only structs");
             // let compilation continue
             cx.expr_usize(trait_span, 0)
         }
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 6bc4ee0b399f9..0dd55f8d77738 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -19,6 +19,17 @@ use syntax::ptr::P;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
+macro_rules! span_err_if_not_stage0 {
+    ($cx:expr, $sp:expr, $code:ident, $text:tt) => {
+        #[cfg(not(stage0))] {
+            span_err!($cx, $sp, $code, $text)
+        }
+        #[cfg(stage0)] {
+            $cx.span_err($sp, $text)
+        }
+    }
+}
+
 macro path_local($x:ident) {
     generic::ty::Path::new_local(stringify!($x))
 }
diff --git a/src/libsyntax_ext/diagnostics.rs b/src/libsyntax_ext/diagnostics.rs
index 33ae24c37e53f..f99a6c3c2166d 100644
--- a/src/libsyntax_ext/diagnostics.rs
+++ b/src/libsyntax_ext/diagnostics.rs
@@ -82,7 +82,7 @@ A clobber was surrounded by braces in the `asm` macro.
 
 Erroneous code example:
 
-```compile_fail,E0663
+```compile_fail,E0664
 asm!("mov $$0x200, %eax"
      :
      :
@@ -94,4 +94,38 @@ Considering that this would be a long explanation, we instead recommend you to
 take a look at the unstable book:
 https://doc.rust-lang.org/unstable-book/language-features/asm.html
 "##,
+
+E0665: r##"
+The `Default` trait was derived on an enum.
+
+Erroneous code example:
+
+```compile_fail,E0665
+#[derive(Default)]
+enum Food {
+    Sweet,
+    Salty,
+}
+```
+
+The `Default` cannot be derived on an enum for the simple reason that the
+compiler doesn't know which value to pick by default whereas it can for a
+struct as long as all its fields implement the `Default` trait as well.
+
+If you still want to implement `Default` on your enum, you'll have to do it "by
+hand":
+
+```
+enum Food {
+    Sweet,
+    Salty,
+}
+
+impl Default for Food {
+    fn default() -> Food {
+        Food::Sweet
+    }
+}
+```
+"##,
 }
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index b6721dd28f367..3b5fb14aae3c9 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -32,8 +32,12 @@ extern crate rustc_target;
 #[cfg(not(stage0))]
 mod diagnostics;
 
-mod assert;
+#[macro_use]
+// for custom_derive
+pub mod deriving;
+
 mod asm;
+mod assert;
 mod cfg;
 mod compile_error;
 mod concat;
@@ -47,8 +51,6 @@ mod trace_macros;
 
 pub mod proc_macro_registrar;
 
-// for custom_derive
-pub mod deriving;
 
 pub mod proc_macro_impl;
 
diff --git a/src/test/ui/E0665.rs b/src/test/ui/E0665.rs
new file mode 100644
index 0000000000000..8888bedf01687
--- /dev/null
+++ b/src/test/ui/E0665.rs
@@ -0,0 +1,20 @@
+// Copyright 2018 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.
+
+// ignore-stage1
+
+#[derive(Default)] //~ ERROR E0665
+enum Food {
+    Sweet,
+    Salty,
+}
+
+fn main() {
+}
diff --git a/src/test/ui/E0665.stderr b/src/test/ui/E0665.stderr
new file mode 100644
index 0000000000000..c97e9e5ea89d0
--- /dev/null
+++ b/src/test/ui/E0665.stderr
@@ -0,0 +1,9 @@
+error[E0665]: `Default` cannot be derived for enums, only structs
+  --> $DIR/E0665.rs:13:10
+   |
+LL | #[derive(Default)] //~ ERROR E0665
+   |          ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0665`.