Skip to content

Commit aef18be

Browse files
authoredOct 25, 2016
Auto merge of #37111 - TimNN:sized-enums, r=nikomatsakis
Disallow Unsized Enums Fixes #16812. This PR is a potential fix for #16812, an issue which is reported [again](#36801) and [again](#36975), with over a dozen duplicates by now. This PR is mainly meant to promoted discussion about the issue and the correct way to fix it. This is a [breaking-change] since the error is now reported during wfchecking, so that even the definition of a (potentially) unsized enum will cause an error (whereas it would previously cause an ICE at trans time if the enum was used in an unsized manner).
2 parents 67f26f7 + db03257 commit aef18be

File tree

8 files changed

+76
-33
lines changed

8 files changed

+76
-33
lines changed
 

‎src/librustc/traits/error_reporting.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -858,8 +858,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
858858
trait_name));
859859
}
860860
ObligationCauseCode::FieldSized => {
861-
err.note("only the last field of a struct or enum variant \
862-
may have a dynamically sized type");
861+
err.note("only the last field of a struct may have a dynamically sized type");
863862
}
864863
ObligationCauseCode::ConstSized => {
865864
err.note("constant expressions must have a statically known size");

‎src/librustc_typeck/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
150150
self.check_variances_for_type_defn(item, ast_generics);
151151
}
152152
hir::ItemEnum(ref enum_def, ref ast_generics) => {
153-
self.check_type_defn(item, false, |fcx| {
153+
self.check_type_defn(item, true, |fcx| {
154154
fcx.enum_variants(enum_def)
155155
});
156156

‎src/test/compile-fail/issue-17025.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// ignore-test the unsized enum no longer compiles
12+
1113
enum A {
1214
B(char),
1315
C([Box<A>]),

‎src/test/compile-fail/issue-5883.rs

-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,4 @@ fn new_struct(r: A+'static)
2020
Struct { r: r }
2121
}
2222

23-
trait Curve {}
24-
enum E {X(Curve+'static)}
2523
fn main() {}

‎src/test/compile-fail/unsized-enum.rs

-7
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,4 @@ fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
1919
//
2020
// Not OK: `T` is not sized.
2121

22-
enum Bar<U: ?Sized> { BarSome(U), BarNone }
23-
fn bar1<T: ?Sized>() { not_sized::<Bar<T>>() }
24-
fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
25-
//~^ ERROR `T: std::marker::Sized` is not satisfied
26-
//
27-
// Not OK: `Bar<T>` is not sized, but it should be.
28-
2922
fn main() { }
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 206 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::ops::Deref;
12+
13+
// Due to aggressive error message deduplication, we require 20 *different*
14+
// unsized types (even Path and [u8] are considered the "same").
15+
16+
trait Foo {}
17+
trait Bar {}
18+
trait FooBar {}
19+
trait BarFoo {}
20+
21+
trait PathHelper1 {}
22+
trait PathHelper2 {}
23+
trait PathHelper3 {}
24+
trait PathHelper4 {}
25+
26+
struct Path1(PathHelper1);
27+
struct Path2(PathHelper2);
28+
struct Path3(PathHelper3);
29+
struct Path4(PathHelper4);
30+
31+
enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
32+
// parameter
33+
VA(W), //~ ERROR `W: std::marker::Sized` is not satisfied
34+
VB{x: X}, //~ ERROR `X: std::marker::Sized` is not satisfied
35+
VC(isize, Y), //~ ERROR `Y: std::marker::Sized` is not satisfied
36+
VD{u: isize, x: Z}, //~ ERROR `Z: std::marker::Sized` is not satisfied
37+
38+
// slice / str
39+
VE([u8]), //~ ERROR `[u8]: std::marker::Sized` is not satisfied
40+
VF{x: str}, //~ ERROR `str: std::marker::Sized` is not satisfied
41+
VG(isize, [f32]), //~ ERROR `[f32]: std::marker::Sized` is not satisfied
42+
VH{u: isize, x: [u32]}, //~ ERROR `[u32]: std::marker::Sized` is not satisfied
43+
44+
// unsized struct
45+
VI(Path1), //~ ERROR `PathHelper1 + 'static: std::marker::Sized` is not satisfied
46+
VJ{x: Path2}, //~ ERROR `PathHelper2 + 'static: std::marker::Sized` is not satisfied
47+
VK(isize, Path3), //~ ERROR `PathHelper3 + 'static: std::marker::Sized` is not satisfied
48+
VL{u: isize, x: Path4}, //~ ERROR `PathHelper4 + 'static: std::marker::Sized` is not satisfied
49+
50+
// plain trait
51+
VM(Foo), //~ ERROR `Foo + 'static: std::marker::Sized` is not satisfied
52+
VN{x: Bar}, //~ ERROR `Bar + 'static: std::marker::Sized` is not satisfied
53+
VO(isize, FooBar), //~ ERROR `FooBar + 'static: std::marker::Sized` is not satisfied
54+
VP{u: isize, x: BarFoo}, //~ ERROR `BarFoo + 'static: std::marker::Sized` is not satisfied
55+
56+
// projected
57+
VQ(<&'static [i8] as Deref>::Target), //~ ERROR `[i8]: std::marker::Sized` is not satisfied
58+
VR{x: <&'static [char] as Deref>::Target},
59+
//~^ ERROR `[char]: std::marker::Sized` is not satisfied
60+
VS(isize, <&'static [f64] as Deref>::Target),
61+
//~^ ERROR `[f64]: std::marker::Sized` is not satisfied
62+
VT{u: isize, x: <&'static [i32] as Deref>::Target},
63+
//~^ ERROR `[i32]: std::marker::Sized` is not satisfied
64+
}
65+
66+
67+
fn main() { }
68+

‎src/test/compile-fail/unsized3.rs

+3-14
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,8 @@ fn f3<X: ?Sized + T>(x: &X) {
3131
fn f4<X: T>(x: &X) {
3232
}
3333

34-
// Test with unsized enum.
35-
enum E<X: ?Sized> {
36-
V(X),
37-
}
38-
3934
fn f5<Y>(x: &Y) {}
4035
fn f6<X: ?Sized>(x: &X) {}
41-
fn f7<X: ?Sized>(x1: &E<X>, x2: &E<X>) {
42-
f5(x1);
43-
//~^ ERROR `X: std::marker::Sized` is not satisfied
44-
f6(x2); // ok
45-
}
46-
4736

4837
// Test with unsized struct.
4938
struct S<X: ?Sized> {
@@ -57,13 +46,13 @@ fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
5746
}
5847

5948
// Test some tuples.
60-
fn f9<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
49+
fn f9<X: ?Sized>(x1: Box<S<X>>) {
6150
f5(&(*x1, 34));
6251
//~^ ERROR `X: std::marker::Sized` is not satisfied
6352
}
6453

65-
fn f10<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
66-
f5(&(32, *x2));
54+
fn f10<X: ?Sized>(x1: Box<S<X>>) {
55+
f5(&(32, *x1));
6756
//~^ ERROR `X: std::marker::Sized` is not satisfied
6857
}
6958

‎src/test/run-pass/unsized2.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -89,20 +89,14 @@ trait T7<X: ?Sized+T> {
8989
fn m2(&self, x: &T5<X>);
9090
}
9191

92-
// The last field in a struct or variant may be unsized
92+
// The last field in a struct may be unsized
9393
struct S2<X: ?Sized> {
9494
f: X,
9595
}
9696
struct S3<X: ?Sized> {
9797
f1: isize,
9898
f2: X,
9999
}
100-
enum E<X: ?Sized> {
101-
V1(X),
102-
V2{x: X},
103-
V3(isize, X),
104-
V4{u: isize, x: X},
105-
}
106100

107101
pub fn main() {
108102
}

0 commit comments

Comments
 (0)