diff --git a/mk/crates.mk b/mk/crates.mk index 0011a7245e5..ed3fce775f3 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -59,6 +59,7 @@ CRATES := $(TARGET_CRATES) $(HOST_CRATES) TOOLS := compiletest rustdoc rustc DEPS_core := +DEPS_libc := core DEPS_rlibc := core DEPS_unicode := core DEPS_alloc := core libc native:jemalloc diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 35b05a672b2..893038cd509 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -79,6 +79,8 @@ #![allow(missing_doc)] #![allow(non_snake_case)] +extern crate core; + #[cfg(test)] extern crate std; #[cfg(test)] extern crate test; #[cfg(test)] extern crate native; diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 49b12802f1e..36ba28dfc2a 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -58,8 +58,6 @@ register_diagnostics!( E0039, E0040, E0041, - E0042, - E0043, E0044, E0045, E0046, @@ -92,7 +90,6 @@ register_diagnostics!( E0075, E0076, E0077, - E0078, E0079, E0080, E0081, diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index db19ffd4fe2..9d66108cfc9 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -80,7 +80,10 @@ pub enum ObligationCauseCode { // Captures of variable the given id by a closure (span is the // span of the closure) - ClosureCapture(ast::NodeId, Span) + ClosureCapture(ast::NodeId, Span), + + // Types of fields (other than the last) in a struct must be sized. + FieldSized, } pub type Obligations = subst::VecPerParamSpace; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 6ef2e7b8fca..c7be2430cc9 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -381,17 +381,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> { } } -struct CheckItemSizedTypesVisitor<'a, 'tcx: 'a> { - ccx: &'a CrateCtxt<'a, 'tcx> -} - -impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemSizedTypesVisitor<'a, 'tcx> { - fn visit_item(&mut self, i: &ast::Item) { - check_item_sized(self.ccx, i); - visit::walk_item(self, i); - } -} - pub fn check_item_types(ccx: &CrateCtxt) { let krate = ccx.tcx.map.krate(); let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx); @@ -405,9 +394,6 @@ pub fn check_item_types(ccx: &CrateCtxt) { visit::walk_crate(&mut visit, krate); ccx.tcx.sess.abort_if_errors(); - - let mut visit = CheckItemSizedTypesVisitor { ccx: ccx }; - visit::walk_crate(&mut visit, krate); } fn check_bare_fn(ccx: &CrateCtxt, @@ -670,33 +656,6 @@ fn check_for_field_shadowing(tcx: &ty::ctxt, } } -fn check_fields_sized(tcx: &ty::ctxt, - struct_def: &ast::StructDef) { - let len = struct_def.fields.len(); - if len == 0 { - return; - } - for f in struct_def.fields.slice_to(len - 1).iter() { - let t = ty::node_id_to_type(tcx, f.node.id); - if !ty::type_is_sized(tcx, t) { - match f.node.kind { - ast::NamedField(ident, _) => { - span_err!(tcx.sess, f.span, E0042, - "type `{}` is dynamically sized. \ - dynamically sized types may only \ - appear as the type of the final \ - field in a struct", - token::get_ident(ident)); - } - ast::UnnamedField(_) => { - span_err!(tcx.sess, f.span, E0043, - "dynamically sized type in field"); - } - } - } - } -} - pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { let tcx = ccx.tcx; @@ -711,24 +670,6 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { } } -pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) { - debug!("check_item(it.id={}, it.ident={})", - it.id, - ty::item_path_str(ccx.tcx, local_def(it.id))); - let _indenter = indenter(); - - match it.node { - ast::ItemEnum(ref enum_definition, _) => { - check_enum_variants_sized(ccx, - enum_definition.variants.as_slice()); - } - ast::ItemStruct(..) => { - check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id)); - } - _ => {} - } -} - pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { debug!("check_item(it.id={}, it.ident={})", it.id, @@ -4946,39 +4887,6 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) { } } - -pub fn check_enum_variants_sized(ccx: &CrateCtxt, - vs: &[P]) { - for v in vs.iter() { - match v.node.kind { - ast::TupleVariantKind(ref args) if args.len() > 0 => { - let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id); - let arg_tys: Vec = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect(); - let len = arg_tys.len(); - if len == 0 { - return; - } - for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() { - // Allow the last field in an enum to be unsized. - // We want to do this so that we can support smart pointers. - // A struct value with an unsized final field is itself - // unsized and we must track this in the type system. - if !ty::type_is_sized(ccx.tcx, *t) { - span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078, - "type `{}` is dynamically sized. dynamically sized types may only \ - appear as the final type in a variant", - ppaux::ty_to_string(ccx.tcx, *t)); - } - } - }, - ast::StructVariantKind(ref struct_def) => { - check_fields_sized(ccx.tcx, &**struct_def) - } - _ => {} - } - } -} - pub fn check_enum_variants(ccx: &CrateCtxt, sp: Span, vs: &[P], diff --git a/src/librustc/middle/typeck/check/vtable2.rs b/src/librustc/middle/typeck/check/vtable2.rs index 345e74fbc90..bcbcebc3f59 100644 --- a/src/librustc/middle/typeck/check/vtable2.rs +++ b/src/librustc/middle/typeck/check/vtable2.rs @@ -406,5 +406,10 @@ fn note_obligation_cause(fcx: &FnCtxt, name, trait_name); } + traits::FieldSized => { + span_note!(tcx.sess, obligation.cause.span, + "only the last field of a struct or enum variant \ + may have a dynamically sized type") + } } } diff --git a/src/librustc/middle/typeck/check/wf.rs b/src/librustc/middle/typeck/check/wf.rs index 8a7de70ea2b..67f93feae41 100644 --- a/src/librustc/middle/typeck/check/wf.rs +++ b/src/librustc/middle/typeck/check/wf.rs @@ -59,7 +59,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { item.id, ty::item_path_str(ccx.tcx, local_def(item.id))); - let ccx = self.ccx; match item.node { ast::ItemImpl(..) => { self.check_impl(item); @@ -70,26 +69,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { ast::ItemStatic(..) => { self.check_item_type(item); } - ast::ItemStruct(..) => { + ast::ItemStruct(ref struct_def, _) => { self.check_type_defn(item, |fcx| { - ty::struct_fields(ccx.tcx, local_def(item.id), - &fcx.inh.param_env.free_substs) - .iter() - .map(|f| f.mt.ty) - .collect() + vec![struct_variant(fcx, &**struct_def)] }); } - ast::ItemEnum(..) => { + ast::ItemEnum(ref enum_def, _) => { self.check_type_defn(item, |fcx| { - ty::substd_enum_variants(ccx.tcx, local_def(item.id), - &fcx.inh.param_env.free_substs) - .iter() - .flat_map(|variant| { - variant.args - .iter() - .map(|&arg_ty| arg_ty) - }) - .collect() + enum_variants(fcx, enum_def) }); } _ => {} @@ -116,7 +103,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { fn check_type_defn(&mut self, item: &ast::Item, - lookup_fields: |&FnCtxt| -> Vec) + lookup_fields: |&FnCtxt| -> Vec) { /*! * In a type definition, we check that to ensure that the types of the fields are @@ -124,14 +111,31 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { */ self.with_fcx(self.ccx, item, |this, fcx| { - let field_tys = lookup_fields(fcx); + let variants = lookup_fields(fcx); let mut bounds_checker = BoundsChecker::new(fcx, item.span, item.id, Some(&mut this.cache)); - for &ty in field_tys.iter() { - // Regions are checked below. - bounds_checker.check_traits_in_ty(ty); + for variant in variants.iter() { + for field in variant.fields.iter() { + // Regions are checked below. + bounds_checker.check_traits_in_ty(field.ty); + } + + // For DST, all intermediate types must be sized. + if variant.fields.len() > 0 { + for field in variant.fields.init().iter() { + let cause = traits::ObligationCause::new(field.span, traits::FieldSized); + fcx.register_obligation( + traits::obligation_for_builtin_bound(fcx.tcx(), + cause, + field.ty, + ty::BoundSized)); + } + } } + let field_tys: Vec = + variants.iter().flat_map(|v| v.fields.iter().map(|f| f.ty)).collect(); + regionck::regionck_ensure_component_tys_wf( fcx, item.span, field_tys.as_slice()); }); @@ -381,6 +385,62 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { } } +/////////////////////////////////////////////////////////////////////////// +// ADT + +struct AdtVariant { + fields: Vec, +} + +struct AdtField { + ty: ty::t, + span: Span, +} + +fn struct_variant(fcx: &FnCtxt, struct_def: &ast::StructDef) -> AdtVariant { + let fields = + struct_def.fields + .iter() + .map(|field| { + let field_ty = ty::node_id_to_type(fcx.tcx(), field.node.id); + let field_ty = field_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs); + AdtField { ty: field_ty, span: field.span } + }) + .collect(); + AdtVariant { fields: fields } +} + +fn enum_variants(fcx: &FnCtxt, enum_def: &ast::EnumDef) -> Vec { + enum_def.variants.iter() + .map(|variant| { + match variant.node.kind { + ast::TupleVariantKind(ref args) if args.len() > 0 => { + let ctor_ty = ty::node_id_to_type(fcx.tcx(), variant.node.id); + let arg_tys = ty::ty_fn_args(ctor_ty); + AdtVariant { + fields: args.iter().enumerate().map(|(index, arg)| { + let arg_ty = arg_tys[index]; + let arg_ty = arg_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs); + AdtField { + ty: arg_ty, + span: arg.ty.span + } + }).collect() + } + } + ast::TupleVariantKind(_) => { + AdtVariant { + fields: Vec::new() + } + } + ast::StructVariantKind(ref struct_def) => { + struct_variant(fcx, &**struct_def) + } + } + }) + .collect() +} + /////////////////////////////////////////////////////////////////////////// // Special drop trait checking diff --git a/src/test/compile-fail/regions-enum-not-wf.rs b/src/test/compile-fail/regions-enum-not-wf.rs index 6395ee62f16..0691ad0de73 100644 --- a/src/test/compile-fail/regions-enum-not-wf.rs +++ b/src/test/compile-fail/regions-enum-not-wf.rs @@ -10,7 +10,6 @@ // Various examples of structs whose fields are not well-formed. -#![no_std] #![allow(dead_code)] enum Ref1<'a, T> { //~ ERROR the parameter type `T` may not live long enough diff --git a/src/test/compile-fail/unsized5.rs b/src/test/compile-fail/unsized5.rs index 6eecc723431..41196b60c8e 100644 --- a/src/test/compile-fail/unsized5.rs +++ b/src/test/compile-fail/unsized5.rs @@ -12,25 +12,25 @@ // Test `Sized?` types not allowed in fields (except the last one). struct S1 { - f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the + f1: X, //~ ERROR `core::kinds::Sized` is not implemented f2: int, } struct S2 { f: int, - g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty + g: X, //~ ERROR `core::kinds::Sized` is not implemented h: int, } struct S3 { - f: str, //~ ERROR type `f` is dynamically sized. dynamically sized types may only appear + f: str, //~ ERROR `core::kinds::Sized` is not implemented g: [uint] } struct S4 { - f: str, //~ ERROR type `f` is dynamically sized. dynamically sized types may only appear + f: str, //~ ERROR `core::kinds::Sized` is not implemented g: uint } enum E { - V1(X, int), //~ERROR type `X` is dynamically sized. dynamically sized types may only appear as t - V2{f1: X, f: int}, //~ERROR type `f1` is dynamically sized. dynamically sized types may only app + V1(X, int), //~ERROR `core::kinds::Sized` is not implemented + V2{f1: X, f: int}, //~ERROR `core::kinds::Sized` is not implemented } pub fn main() {