about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-08-18 10:57:55 +0000
committerbors <bors@rust-lang.org>2017-08-18 10:57:55 +0000
commitb8ce1a3d2e4fe22034845e76b4b11d5b71aba43e (patch)
tree107a5fb6248f14afedfeb5a7875b8987b364fe4f
parente6ab51165a1b67409c1ee1efeaf0cd139dc6c592 (diff)
parentc3c99b92c7cd188c0f85c3e2f47ad6dc6ee975ba (diff)
downloadrust-b8ce1a3d2e4fe22034845e76b4b11d5b71aba43e.tar.gz
rust-b8ce1a3d2e4fe22034845e76b4b11d5b71aba43e.zip
Auto merge of #43901 - GuillaumeGomez:unsized-union-field, r=petrochenkov
udpdate error message for unsized union field

Fixes #36312.
-rw-r--r--src/librustc/hir/mod.rs10
-rw-r--r--src/librustc/traits/error_reporting.rs18
-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.rs26
-rw-r--r--src/test/ui/union-sized-field.stderr32
7 files changed, 91 insertions, 10 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 c04d448716c..3e64c8c7dea 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -1111,8 +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 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");
@@ -1154,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
new file mode 100644
index 00000000000..eeca5ab7404
--- /dev/null
+++ b/src/test/ui/union-sized-field.rs
@@ -0,0 +1,26 @@
+// Copyright 2017 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.
+
+#![feature(untagged_unions)]
+
+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
new file mode 100644
index 00000000000..ea90d97c4c3
--- /dev/null
+++ b/src/test/ui/union-sized-field.stderr
@@ -0,0 +1,32 @@
+error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
+  --> $DIR/union-sized-field.rs:14:5
+   |
+14 |     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 a union may have a dynamically sized type
+
+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
+