about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2017-08-16 18:45:54 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2017-08-18 10:24:53 +0200
commitc3c99b92c7cd188c0f85c3e2f47ad6dc6ee975ba (patch)
treee8c4e83757258a8a2e485ce8d1321c4fffca05b2
parent589d994c38dc634545b4e08030bbb86a1558aa40 (diff)
downloadrust-c3c99b92c7cd188c0f85c3e2f47ad6dc6ee975ba.tar.gz
rust-c3c99b92c7cd188c0f85c3e2f47ad6dc6ee975ba.zip
Handle structs, unions and enums unsized field/variant separately
-rw-r--r--src/librustc/hir/mod.rs10
-rw-r--r--src/librustc/traits/error_reporting.rs19
-rw-r--r--src/librustc/traits/mod.rs4
-rw-r--r--src/librustc/traits/structural_impls.rs6
-rw-r--r--src/librustc_typeck/check/wfcheck.rs5
-rw-r--r--src/test/ui/union-sized-field.rs9
-rw-r--r--src/test/ui/union-sized-field.stderr24
7 files changed, 64 insertions, 13 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 3806b517f77..400f46d66f8 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -42,6 +42,7 @@ use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
 use syntax::tokenstream::TokenStream;
 use syntax::util::ThinVec;
+use ty::AdtKind;
 
 use rustc_data_structures::indexed_vec;
 
@@ -1789,6 +1790,15 @@ impl Item_ {
             ItemDefaultImpl(..) => "item",
         }
     }
+
+    pub fn adt_kind(&self) -> Option<AdtKind> {
+        match *self {
+            ItemStruct(..) => Some(AdtKind::Struct),
+            ItemUnion(..) => Some(AdtKind::Union),
+            ItemEnum(..) => Some(AdtKind::Enum),
+            _ => None,
+        }
+    }
 }
 
 /// A reference from an trait to one of its associated items. This
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index c1a443a5322..3e64c8c7dea 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -1111,9 +1111,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             ObligationCauseCode::StructInitializerSized => {
                 err.note("structs must have a statically known size to be initialized");
             }
-            ObligationCauseCode::FieldSized => {
-                err.note("only the last field of a struct or an union may have a dynamically \
-                          sized type");
+            ObligationCauseCode::FieldSized(ref item) => {
+                match *item {
+                    AdtKind::Struct => {
+                        err.note("only the last field of a struct may have a dynamically \
+                                  sized type");
+                    }
+                    AdtKind::Union => {
+                        err.note("no field of a union may have a dynamically sized type");
+                    }
+                    AdtKind::Enum => {
+                        err.note("no field of an enum variant may have a dynamically sized type");
+                    }
+                }
             }
             ObligationCauseCode::ConstSized => {
                 err.note("constant expressions must have a statically known size");
@@ -1155,8 +1165,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) {
         let current_limit = self.tcx.sess.recursion_limit.get();
         let suggested_limit = current_limit * 2;
-        err.help(&format!(
-                          "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
+        err.help(&format!("consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                           suggested_limit));
     }
 }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index d1938197e65..5bae82c1a33 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -20,7 +20,7 @@ use hir::def_id::DefId;
 use middle::region::RegionMaps;
 use middle::free_region::FreeRegionMap;
 use ty::subst::Substs;
-use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate};
+use ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, ToPredicate};
 use ty::error::{ExpectedFound, TypeError};
 use infer::{InferCtxt};
 
@@ -133,7 +133,7 @@ pub enum ObligationCauseCode<'tcx> {
     RepeatVec,
 
     /// Types of fields (other than the last) in a struct must be sized.
-    FieldSized,
+    FieldSized(AdtKind),
 
     /// Constant expressions must be sized.
     ConstSized,
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index f1c176561ea..e80e82fa94f 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -195,7 +195,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
             super::ReturnType(id) => Some(super::ReturnType(id)),
             super::SizedReturnType => Some(super::SizedReturnType),
             super::RepeatVec => Some(super::RepeatVec),
-            super::FieldSized => Some(super::FieldSized),
+            super::FieldSized(item) => Some(super::FieldSized(item)),
             super::ConstSized => Some(super::ConstSized),
             super::SharedStatic => Some(super::SharedStatic),
             super::BuiltinDerivedObligation(ref cause) => {
@@ -484,7 +484,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
             super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
-            super::FieldSized |
+            super::FieldSized(_) |
             super::ConstSized |
             super::SharedStatic |
             super::BlockTailExpression(_) |
@@ -532,7 +532,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
             super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
-            super::FieldSized |
+            super::FieldSized(_) |
             super::ConstSized |
             super::SharedStatic |
             super::BlockTailExpression(_) |
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index f85835e3800..69f045ab4e9 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -233,7 +233,10 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
                         fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
                         traits::ObligationCause::new(field.span,
                                                      fcx.body_id,
-                                                     traits::FieldSized));
+                                                     traits::FieldSized(match item.node.adt_kind() {
+                                                        Some(i) => i,
+                                                        None => bug!(),
+                                                     })));
                 }
 
                 // All field types must be well-formed.
diff --git a/src/test/ui/union-sized-field.rs b/src/test/ui/union-sized-field.rs
index 9a237f0fd16..eeca5ab7404 100644
--- a/src/test/ui/union-sized-field.rs
+++ b/src/test/ui/union-sized-field.rs
@@ -14,4 +14,13 @@ union Foo<T: ?Sized> {
     value: T,
 }
 
+struct Foo2<T: ?Sized> {
+    value: T,
+    t: u32,
+}
+
+enum Foo3<T: ?Sized> {
+    Value(T),
+}
+
 fn main() {}
diff --git a/src/test/ui/union-sized-field.stderr b/src/test/ui/union-sized-field.stderr
index 4dd8befd2cb..ea90d97c4c3 100644
--- a/src/test/ui/union-sized-field.stderr
+++ b/src/test/ui/union-sized-field.stderr
@@ -6,7 +6,27 @@ error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
    |
    = help: the trait `std::marker::Sized` is not implemented for `T`
    = help: consider adding a `where T: std::marker::Sized` bound
-   = note: only the last field of a struct or an union may have a dynamically sized type
+   = note: no field of a union may have a dynamically sized type
 
-error: aborting due to previous error
+error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
+  --> $DIR/union-sized-field.rs:18:5
+   |
+18 |     value: T,
+   |     ^^^^^^^^ `T` does not have a constant size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: only the last field of a struct may have a dynamically sized type
+
+error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
+  --> $DIR/union-sized-field.rs:23:11
+   |
+23 |     Value(T),
+   |           ^^ `T` does not have a constant size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error: aborting due to 3 previous errors