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 { + 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(untagged_unions)] + +union Foo { + value: T, +} + +struct Foo2 { + value: T, + t: u32, +} + +enum Foo3 { + 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 +