]> git.lizzy.rs Git - rust.git/commitdiff
Handle structs, unions and enums unsized field/variant separately
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Wed, 16 Aug 2017 16:45:54 +0000 (18:45 +0200)
committerGuillaume Gomez <guillaume1.gomez@gmail.com>
Fri, 18 Aug 2017 08:24:53 +0000 (10:24 +0200)
src/librustc/hir/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/structural_impls.rs
src/librustc_typeck/check/wfcheck.rs
src/test/ui/union-sized-field.rs
src/test/ui/union-sized-field.stderr

index 3806b517f7782d43dff4201f59ec99da65b472af..400f46d66f8681d0e8169e046c2f98564022d8b6 100644 (file)
@@ -42,6 +42,7 @@
 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 @@ pub fn descriptive_variant(&self) -> &str {
             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
index c1a443a532200801f2886266ed8cdbcf06401b3f..3e64c8c7dea997ad668916246eb63f0b9bfc633e 100644 (file)
@@ -1111,9 +1111,19 @@ fn note_obligation_cause_code<T>(&self,
             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 @@ fn note_obligation_cause_code<T>(&self,
     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));
     }
 }
index d1938197e652965dbf338ac1c233141f36c9e909..5bae82c1a332fee87e53ac62087c34c4b70cfe85 100644 (file)
@@ -20,7 +20,7 @@
 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,
index f1c176561ea4875d908cc67689c2fc4166d02308..e80e82fa94ff6dd70091d7b891a87f74ca548324 100644 (file)
@@ -195,7 +195,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             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 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
-            super::FieldSized |
+            super::FieldSized(_) |
             super::ConstSized |
             super::SharedStatic |
             super::BlockTailExpression(_) |
@@ -532,7 +532,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
-            super::FieldSized |
+            super::FieldSized(_) |
             super::ConstSized |
             super::SharedStatic |
             super::BlockTailExpression(_) |
index f85835e3800f41777fbd6378ebff9a599578e4af..69f045ab4e96a0da3ce286333a230ae470d9b87e 100644 (file)
@@ -233,7 +233,10 @@ fn check_type_defn<F>(&mut self, item: &hir::Item, all_sized: bool, mut lookup_f
                         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.
index 9a237f0fd16cb32c17773877bb2da9e256d9cacd..eeca5ab740450494ae97b80515ddedbbb4096f30 100644 (file)
@@ -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() {}
index 4dd8befd2cb932904c874b71c713493b9fbf9982..ea90d97c4c3d1f1d2f6150582a287d82d727a060 100644 (file)
@@ -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