diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3806b517f7782d43dff4201f59ec99da65b472af..400f46d66f8681d0e8169e046c2f98564022d8b6 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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 { + 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 c04d448716c5bf205419843eaa71f05ab9e175b7..3e64c8c7dea997ad668916246eb63f0b9bfc633e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1111,8 +1111,19 @@ fn note_obligation_cause_code(&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 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 @@ fn note_obligation_cause_code(&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)); } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index d1938197e652965dbf338ac1c233141f36c9e909..5bae82c1a332fee87e53ac62087c34c4b70cfe85 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -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, diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index f1c176561ea4875d908cc67689c2fc4166d02308..e80e82fa94ff6dd70091d7b891a87f74ca548324 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -195,7 +195,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option 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>(&self, visitor: &mut V) -> bool { 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 f85835e3800f41777fbd6378ebff9a599578e4af..69f045ab4e96a0da3ce286333a230ae470d9b87e 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -233,7 +233,10 @@ fn check_type_defn(&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. diff --git a/src/test/ui/union-sized-field.rs b/src/test/ui/union-sized-field.rs new file mode 100644 index 0000000000000000000000000000000000000000..eeca5ab740450494ae97b80515ddedbbb4096f30 --- /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 0000000000000000000000000000000000000000..ea90d97c4c3d1f1d2f6150582a287d82d727a060 --- /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 +