Skip to content

Commit 3694f42

Browse files
committed
Move checking of whether fields are Sized or not into wf / trait code.
1 parent e924357 commit 3694f42

File tree

9 files changed

+100
-125
lines changed

9 files changed

+100
-125
lines changed

mk/crates.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ CRATES := $(TARGET_CRATES) $(HOST_CRATES)
5959
TOOLS := compiletest rustdoc rustc
6060

6161
DEPS_core :=
62+
DEPS_libc := core
6263
DEPS_rlibc := core
6364
DEPS_unicode := core
6465
DEPS_alloc := core libc native:jemalloc

src/liblibc/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
#![allow(missing_doc)]
8080
#![allow(non_snake_case)]
8181

82+
extern crate core;
83+
8284
#[cfg(test)] extern crate std;
8385
#[cfg(test)] extern crate test;
8486
#[cfg(test)] extern crate native;

src/librustc/diagnostics.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ register_diagnostics!(
5858
E0039,
5959
E0040,
6060
E0041,
61-
E0042,
62-
E0043,
6361
E0044,
6462
E0045,
6563
E0046,
@@ -92,7 +90,6 @@ register_diagnostics!(
9290
E0075,
9391
E0076,
9492
E0077,
95-
E0078,
9693
E0079,
9794
E0080,
9895
E0081,

src/librustc/middle/traits/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ pub enum ObligationCauseCode {
8080

8181
// Captures of variable the given id by a closure (span is the
8282
// span of the closure)
83-
ClosureCapture(ast::NodeId, Span)
83+
ClosureCapture(ast::NodeId, Span),
84+
85+
// Types of fields (other than the last) in a struct must be sized.
86+
FieldSized,
8487
}
8588

8689
pub type Obligations = subst::VecPerParamSpace<Obligation>;

src/librustc/middle/typeck/check/mod.rs

Lines changed: 0 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -381,17 +381,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
381381
}
382382
}
383383

384-
struct CheckItemSizedTypesVisitor<'a, 'tcx: 'a> {
385-
ccx: &'a CrateCtxt<'a, 'tcx>
386-
}
387-
388-
impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemSizedTypesVisitor<'a, 'tcx> {
389-
fn visit_item(&mut self, i: &ast::Item) {
390-
check_item_sized(self.ccx, i);
391-
visit::walk_item(self, i);
392-
}
393-
}
394-
395384
pub fn check_item_types(ccx: &CrateCtxt) {
396385
let krate = ccx.tcx.map.krate();
397386
let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
@@ -405,9 +394,6 @@ pub fn check_item_types(ccx: &CrateCtxt) {
405394
visit::walk_crate(&mut visit, krate);
406395

407396
ccx.tcx.sess.abort_if_errors();
408-
409-
let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
410-
visit::walk_crate(&mut visit, krate);
411397
}
412398

413399
fn check_bare_fn(ccx: &CrateCtxt,
@@ -670,33 +656,6 @@ fn check_for_field_shadowing(tcx: &ty::ctxt,
670656
}
671657
}
672658

673-
fn check_fields_sized(tcx: &ty::ctxt,
674-
struct_def: &ast::StructDef) {
675-
let len = struct_def.fields.len();
676-
if len == 0 {
677-
return;
678-
}
679-
for f in struct_def.fields.slice_to(len - 1).iter() {
680-
let t = ty::node_id_to_type(tcx, f.node.id);
681-
if !ty::type_is_sized(tcx, t) {
682-
match f.node.kind {
683-
ast::NamedField(ident, _) => {
684-
span_err!(tcx.sess, f.span, E0042,
685-
"type `{}` is dynamically sized. \
686-
dynamically sized types may only \
687-
appear as the type of the final \
688-
field in a struct",
689-
token::get_ident(ident));
690-
}
691-
ast::UnnamedField(_) => {
692-
span_err!(tcx.sess, f.span, E0043,
693-
"dynamically sized type in field");
694-
}
695-
}
696-
}
697-
}
698-
}
699-
700659
pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
701660
let tcx = ccx.tcx;
702661

@@ -711,24 +670,6 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
711670
}
712671
}
713672

714-
pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
715-
debug!("check_item(it.id={}, it.ident={})",
716-
it.id,
717-
ty::item_path_str(ccx.tcx, local_def(it.id)));
718-
let _indenter = indenter();
719-
720-
match it.node {
721-
ast::ItemEnum(ref enum_definition, _) => {
722-
check_enum_variants_sized(ccx,
723-
enum_definition.variants.as_slice());
724-
}
725-
ast::ItemStruct(..) => {
726-
check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
727-
}
728-
_ => {}
729-
}
730-
}
731-
732673
pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
733674
debug!("check_item(it.id={}, it.ident={})",
734675
it.id,
@@ -4946,39 +4887,6 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
49464887
}
49474888
}
49484889

4949-
4950-
pub fn check_enum_variants_sized(ccx: &CrateCtxt,
4951-
vs: &[P<ast::Variant>]) {
4952-
for v in vs.iter() {
4953-
match v.node.kind {
4954-
ast::TupleVariantKind(ref args) if args.len() > 0 => {
4955-
let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
4956-
let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
4957-
let len = arg_tys.len();
4958-
if len == 0 {
4959-
return;
4960-
}
4961-
for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
4962-
// Allow the last field in an enum to be unsized.
4963-
// We want to do this so that we can support smart pointers.
4964-
// A struct value with an unsized final field is itself
4965-
// unsized and we must track this in the type system.
4966-
if !ty::type_is_sized(ccx.tcx, *t) {
4967-
span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078,
4968-
"type `{}` is dynamically sized. dynamically sized types may only \
4969-
appear as the final type in a variant",
4970-
ppaux::ty_to_string(ccx.tcx, *t));
4971-
}
4972-
}
4973-
},
4974-
ast::StructVariantKind(ref struct_def) => {
4975-
check_fields_sized(ccx.tcx, &**struct_def)
4976-
}
4977-
_ => {}
4978-
}
4979-
}
4980-
}
4981-
49824890
pub fn check_enum_variants(ccx: &CrateCtxt,
49834891
sp: Span,
49844892
vs: &[P<ast::Variant>],

src/librustc/middle/typeck/check/vtable2.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,5 +406,10 @@ fn note_obligation_cause(fcx: &FnCtxt,
406406
name,
407407
trait_name);
408408
}
409+
traits::FieldSized => {
410+
span_note!(tcx.sess, obligation.cause.span,
411+
"only the last field of a struct or enum variant \
412+
may have a dynamically sized type")
413+
}
409414
}
410415
}

src/librustc/middle/typeck/check/wf.rs

Lines changed: 82 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
5959
item.id,
6060
ty::item_path_str(ccx.tcx, local_def(item.id)));
6161

62-
let ccx = self.ccx;
6362
match item.node {
6463
ast::ItemImpl(..) => {
6564
self.check_impl(item);
@@ -70,26 +69,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
7069
ast::ItemStatic(..) => {
7170
self.check_item_type(item);
7271
}
73-
ast::ItemStruct(..) => {
72+
ast::ItemStruct(ref struct_def, _) => {
7473
self.check_type_defn(item, |fcx| {
75-
ty::struct_fields(ccx.tcx, local_def(item.id),
76-
&fcx.inh.param_env.free_substs)
77-
.iter()
78-
.map(|f| f.mt.ty)
79-
.collect()
74+
vec![struct_variant(fcx, &**struct_def)]
8075
});
8176
}
82-
ast::ItemEnum(..) => {
77+
ast::ItemEnum(ref enum_def, _) => {
8378
self.check_type_defn(item, |fcx| {
84-
ty::substd_enum_variants(ccx.tcx, local_def(item.id),
85-
&fcx.inh.param_env.free_substs)
86-
.iter()
87-
.flat_map(|variant| {
88-
variant.args
89-
.iter()
90-
.map(|&arg_ty| arg_ty)
91-
})
92-
.collect()
79+
enum_variants(fcx, enum_def)
9380
});
9481
}
9582
_ => {}
@@ -116,22 +103,39 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
116103

117104
fn check_type_defn(&mut self,
118105
item: &ast::Item,
119-
lookup_fields: |&FnCtxt| -> Vec<ty::t>)
106+
lookup_fields: |&FnCtxt| -> Vec<AdtVariant>)
120107
{
121108
/*!
122109
* In a type definition, we check that to ensure that the types of the fields are
123110
* well-formed.
124111
*/
125112

126113
self.with_fcx(self.ccx, item, |this, fcx| {
127-
let field_tys = lookup_fields(fcx);
114+
let variants = lookup_fields(fcx);
128115
let mut bounds_checker = BoundsChecker::new(fcx, item.span,
129116
item.id, Some(&mut this.cache));
130-
for &ty in field_tys.iter() {
131-
// Regions are checked below.
132-
bounds_checker.check_traits_in_ty(ty);
117+
for variant in variants.iter() {
118+
for field in variant.fields.iter() {
119+
// Regions are checked below.
120+
bounds_checker.check_traits_in_ty(field.ty);
121+
}
122+
123+
// For DST, all intermediate types must be sized.
124+
if variant.fields.len() > 0 {
125+
for field in variant.fields.init().iter() {
126+
let cause = traits::ObligationCause::new(field.span, traits::FieldSized);
127+
fcx.register_obligation(
128+
traits::obligation_for_builtin_bound(fcx.tcx(),
129+
cause,
130+
field.ty,
131+
ty::BoundSized));
132+
}
133+
}
133134
}
134135

136+
let field_tys: Vec<ty::t> =
137+
variants.iter().flat_map(|v| v.fields.iter().map(|f| f.ty)).collect();
138+
135139
regionck::regionck_ensure_component_tys_wf(
136140
fcx, item.span, field_tys.as_slice());
137141
});
@@ -381,6 +385,62 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
381385
}
382386
}
383387

388+
///////////////////////////////////////////////////////////////////////////
389+
// ADT
390+
391+
struct AdtVariant {
392+
fields: Vec<AdtField>,
393+
}
394+
395+
struct AdtField {
396+
ty: ty::t,
397+
span: Span,
398+
}
399+
400+
fn struct_variant(fcx: &FnCtxt, struct_def: &ast::StructDef) -> AdtVariant {
401+
let fields =
402+
struct_def.fields
403+
.iter()
404+
.map(|field| {
405+
let field_ty = ty::node_id_to_type(fcx.tcx(), field.node.id);
406+
let field_ty = field_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
407+
AdtField { ty: field_ty, span: field.span }
408+
})
409+
.collect();
410+
AdtVariant { fields: fields }
411+
}
412+
413+
fn enum_variants(fcx: &FnCtxt, enum_def: &ast::EnumDef) -> Vec<AdtVariant> {
414+
enum_def.variants.iter()
415+
.map(|variant| {
416+
match variant.node.kind {
417+
ast::TupleVariantKind(ref args) if args.len() > 0 => {
418+
let ctor_ty = ty::node_id_to_type(fcx.tcx(), variant.node.id);
419+
let arg_tys = ty::ty_fn_args(ctor_ty);
420+
AdtVariant {
421+
fields: args.iter().enumerate().map(|(index, arg)| {
422+
let arg_ty = arg_tys[index];
423+
let arg_ty = arg_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
424+
AdtField {
425+
ty: arg_ty,
426+
span: arg.ty.span
427+
}
428+
}).collect()
429+
}
430+
}
431+
ast::TupleVariantKind(_) => {
432+
AdtVariant {
433+
fields: Vec::new()
434+
}
435+
}
436+
ast::StructVariantKind(ref struct_def) => {
437+
struct_variant(fcx, &**struct_def)
438+
}
439+
}
440+
})
441+
.collect()
442+
}
443+
384444
///////////////////////////////////////////////////////////////////////////
385445
// Special drop trait checking
386446

src/test/compile-fail/regions-enum-not-wf.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
// Various examples of structs whose fields are not well-formed.
1212

13-
#![no_std]
1413
#![allow(dead_code)]
1514

1615
enum Ref1<'a, T> { //~ ERROR the parameter type `T` may not live long enough

src/test/compile-fail/unsized5.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,25 @@
1212
// Test `Sized?` types not allowed in fields (except the last one).
1313

1414
struct S1<Sized? X> {
15-
f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the
15+
f1: X, //~ ERROR `core::kinds::Sized` is not implemented
1616
f2: int,
1717
}
1818
struct S2<Sized? X> {
1919
f: int,
20-
g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty
20+
g: X, //~ ERROR `core::kinds::Sized` is not implemented
2121
h: int,
2222
}
2323
struct S3 {
24-
f: str, //~ ERROR type `f` is dynamically sized. dynamically sized types may only appear
24+
f: str, //~ ERROR `core::kinds::Sized` is not implemented
2525
g: [uint]
2626
}
2727
struct S4 {
28-
f: str, //~ ERROR type `f` is dynamically sized. dynamically sized types may only appear
28+
f: str, //~ ERROR `core::kinds::Sized` is not implemented
2929
g: uint
3030
}
3131
enum E<Sized? X> {
32-
V1(X, int), //~ERROR type `X` is dynamically sized. dynamically sized types may only appear as t
33-
V2{f1: X, f: int}, //~ERROR type `f1` is dynamically sized. dynamically sized types may only app
32+
V1(X, int), //~ERROR `core::kinds::Sized` is not implemented
33+
V2{f1: X, f: int}, //~ERROR `core::kinds::Sized` is not implemented
3434
}
3535

3636
pub fn main() {

0 commit comments

Comments
 (0)