From f1695238cae0c7c6598fa736820837d35a2143cf Mon Sep 17 00:00:00 2001
From: Tim Neumann <mail@timnn.me>
Date: Wed, 12 Oct 2016 12:40:48 +0200
Subject: [PATCH 1/3] disallow unsized enums

---
 src/librustc/traits/error_reporting.rs | 3 +--
 src/librustc_typeck/check/wfcheck.rs   | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 52ddd8ab5dac0..4aff84d81996d 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -856,8 +856,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                              trait_name));
             }
             ObligationCauseCode::FieldSized => {
-                err.note("only the last field of a struct or enum variant \
-                          may have a dynamically sized type");
+                err.note("only the last field of a struct may have a dynamically sized type");
             }
             ObligationCauseCode::ConstSized => {
                 err.note("constant expressions must have a statically known size");
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index bc5cb68995b2f..e3634cfe5f5e3 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -150,7 +150,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
                 self.check_variances_for_type_defn(item, ast_generics);
             }
             hir::ItemEnum(ref enum_def, ref ast_generics) => {
-                self.check_type_defn(item, false, |fcx| {
+                self.check_type_defn(item, true, |fcx| {
                     fcx.enum_variants(enum_def)
                 });
 

From d22f7061507e78d5b83b03f6e3cf420b9969a92c Mon Sep 17 00:00:00 2001
From: Tim Neumann <mail@timnn.me>
Date: Mon, 24 Oct 2016 20:55:56 +0200
Subject: [PATCH 2/3] adapt existing tests

---
 src/test/compile-fail/issue-17025.rs  |  2 ++
 src/test/compile-fail/issue-5883.rs   |  2 --
 src/test/compile-fail/unsized-enum.rs |  7 -------
 src/test/compile-fail/unsized3.rs     | 17 +++--------------
 src/test/run-pass/unsized2.rs         |  8 +-------
 5 files changed, 6 insertions(+), 30 deletions(-)

diff --git a/src/test/compile-fail/issue-17025.rs b/src/test/compile-fail/issue-17025.rs
index 2a1a3397d5447..f250103b14407 100644
--- a/src/test/compile-fail/issue-17025.rs
+++ b/src/test/compile-fail/issue-17025.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-test the unsized enum no longer compiles
+
 enum A {
     B(char),
     C([Box<A>]),
diff --git a/src/test/compile-fail/issue-5883.rs b/src/test/compile-fail/issue-5883.rs
index 019a7bdc734d4..e14d9f3a35c84 100644
--- a/src/test/compile-fail/issue-5883.rs
+++ b/src/test/compile-fail/issue-5883.rs
@@ -20,6 +20,4 @@ fn new_struct(r: A+'static)
     Struct { r: r }
 }
 
-trait Curve {}
-enum E {X(Curve+'static)}
 fn main() {}
diff --git a/src/test/compile-fail/unsized-enum.rs b/src/test/compile-fail/unsized-enum.rs
index 61b2b01b35584..5d791215f36c6 100644
--- a/src/test/compile-fail/unsized-enum.rs
+++ b/src/test/compile-fail/unsized-enum.rs
@@ -19,11 +19,4 @@ fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
 //
 // Not OK: `T` is not sized.
 
-enum Bar<U: ?Sized> { BarSome(U), BarNone }
-fn bar1<T: ?Sized>() { not_sized::<Bar<T>>() }
-fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
-//~^ ERROR `T: std::marker::Sized` is not satisfied
-//
-// Not OK: `Bar<T>` is not sized, but it should be.
-
 fn main() { }
diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs
index f88165c02e988..9b6ccf22c8da5 100644
--- a/src/test/compile-fail/unsized3.rs
+++ b/src/test/compile-fail/unsized3.rs
@@ -31,19 +31,8 @@ fn f3<X: ?Sized + T>(x: &X) {
 fn f4<X: T>(x: &X) {
 }
 
-// Test with unsized enum.
-enum E<X: ?Sized> {
-    V(X),
-}
-
 fn f5<Y>(x: &Y) {}
 fn f6<X: ?Sized>(x: &X) {}
-fn f7<X: ?Sized>(x1: &E<X>, x2: &E<X>) {
-    f5(x1);
-    //~^ ERROR `X: std::marker::Sized` is not satisfied
-    f6(x2); // ok
-}
-
 
 // Test with unsized struct.
 struct S<X: ?Sized> {
@@ -57,13 +46,13 @@ fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
 }
 
 // Test some tuples.
-fn f9<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
+fn f9<X: ?Sized>(x1: Box<S<X>>) {
     f5(&(*x1, 34));
     //~^ ERROR `X: std::marker::Sized` is not satisfied
 }
 
-fn f10<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
-    f5(&(32, *x2));
+fn f10<X: ?Sized>(x1: Box<S<X>>) {
+    f5(&(32, *x1));
     //~^ ERROR `X: std::marker::Sized` is not satisfied
 }
 
diff --git a/src/test/run-pass/unsized2.rs b/src/test/run-pass/unsized2.rs
index 5b9fa5230d1e0..50d8d3d27f27b 100644
--- a/src/test/run-pass/unsized2.rs
+++ b/src/test/run-pass/unsized2.rs
@@ -89,7 +89,7 @@ trait T7<X: ?Sized+T> {
     fn m2(&self, x: &T5<X>);
 }
 
-// The last field in a struct or variant may be unsized
+// The last field in a struct may be unsized
 struct S2<X: ?Sized> {
     f: X,
 }
@@ -97,12 +97,6 @@ struct S3<X: ?Sized> {
     f1: isize,
     f2: X,
 }
-enum E<X: ?Sized> {
-    V1(X),
-    V2{x: X},
-    V3(isize, X),
-    V4{u: isize, x: X},
-}
 
 pub fn main() {
 }

From db032578a436df5974be8bf9404b26d7661008e3 Mon Sep 17 00:00:00 2001
From: Tim Neumann <mail@timnn.me>
Date: Mon, 24 Oct 2016 21:40:43 +0200
Subject: [PATCH 3/3] add new test case

---
 src/test/compile-fail/unsized-enum2.rs | 68 ++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)
 create mode 100644 src/test/compile-fail/unsized-enum2.rs

diff --git a/src/test/compile-fail/unsized-enum2.rs b/src/test/compile-fail/unsized-enum2.rs
new file mode 100644
index 0000000000000..95fc3243fbed3
--- /dev/null
+++ b/src/test/compile-fail/unsized-enum2.rs
@@ -0,0 +1,68 @@
+// Copyright 206 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.
+
+use std::ops::Deref;
+
+// Due to aggressive error message deduplication, we require 20 *different*
+// unsized types (even Path and [u8] are considered the "same").
+
+trait Foo {}
+trait Bar {}
+trait FooBar {}
+trait BarFoo {}
+
+trait PathHelper1 {}
+trait PathHelper2 {}
+trait PathHelper3 {}
+trait PathHelper4 {}
+
+struct Path1(PathHelper1);
+struct Path2(PathHelper2);
+struct Path3(PathHelper3);
+struct Path4(PathHelper4);
+
+enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+    // parameter
+    VA(W), //~ ERROR `W: std::marker::Sized` is not satisfied
+    VB{x: X}, //~ ERROR `X: std::marker::Sized` is not satisfied
+    VC(isize, Y), //~ ERROR `Y: std::marker::Sized` is not satisfied
+    VD{u: isize, x: Z}, //~ ERROR `Z: std::marker::Sized` is not satisfied
+
+    // slice / str
+    VE([u8]), //~ ERROR `[u8]: std::marker::Sized` is not satisfied
+    VF{x: str}, //~ ERROR `str: std::marker::Sized` is not satisfied
+    VG(isize, [f32]), //~ ERROR `[f32]: std::marker::Sized` is not satisfied
+    VH{u: isize, x: [u32]}, //~ ERROR `[u32]: std::marker::Sized` is not satisfied
+
+    // unsized struct
+    VI(Path1), //~ ERROR `PathHelper1 + 'static: std::marker::Sized` is not satisfied
+    VJ{x: Path2}, //~ ERROR `PathHelper2 + 'static: std::marker::Sized` is not satisfied
+    VK(isize, Path3), //~ ERROR `PathHelper3 + 'static: std::marker::Sized` is not satisfied
+    VL{u: isize, x: Path4}, //~ ERROR `PathHelper4 + 'static: std::marker::Sized` is not satisfied
+
+    // plain trait
+    VM(Foo),  //~ ERROR `Foo + 'static: std::marker::Sized` is not satisfied
+    VN{x: Bar}, //~ ERROR `Bar + 'static: std::marker::Sized` is not satisfied
+    VO(isize, FooBar), //~ ERROR `FooBar + 'static: std::marker::Sized` is not satisfied
+    VP{u: isize, x: BarFoo}, //~ ERROR `BarFoo + 'static: std::marker::Sized` is not satisfied
+
+    // projected
+    VQ(<&'static [i8] as Deref>::Target), //~ ERROR `[i8]: std::marker::Sized` is not satisfied
+    VR{x: <&'static [char] as Deref>::Target},
+    //~^ ERROR `[char]: std::marker::Sized` is not satisfied
+    VS(isize, <&'static [f64] as Deref>::Target),
+    //~^ ERROR `[f64]: std::marker::Sized` is not satisfied
+    VT{u: isize, x: <&'static [i32] as Deref>::Target},
+    //~^ ERROR `[i32]: std::marker::Sized` is not satisfied
+}
+
+
+fn main() { }
+