Skip to content

Commit 696f16e

Browse files
committed
auto merge of #13398 : nick29581/rust/unsized-enum, r=nikomatsakis
Now with proper checking of enums and allows unsized fields as the last field in a struct or variant. This PR only checks passing of unsized types and distinguishing them from sized ones. To be safe we also need to control storage. Closes issues #12969 and #13121, supersedes #13375 (all the discussion there is valid here too).
2 parents bcc3e8c + 5729d9b commit 696f16e

40 files changed

+643
-84
lines changed

src/librustc/front/config.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ fn fold_item_underscore(cx: &mut Context, item: &ast::Item_) -> ast::Item_ {
103103
.map(|x| *x).collect();
104104
ast::ItemImpl((*a).clone(), (*b).clone(), c, methods)
105105
}
106-
ast::ItemTrait(ref a, ref b, ref methods) => {
106+
ast::ItemTrait(ref a, b, ref c, ref methods) => {
107107
let methods = methods.iter()
108108
.filter(|m| trait_method_in_cfg(cx, *m) )
109109
.map(|x| (*x).clone())
110110
.collect();
111-
ast::ItemTrait((*a).clone(), (*b).clone(), methods)
111+
ast::ItemTrait((*a).clone(), b, (*c).clone(), methods)
112112
}
113113
ast::ItemStruct(def, ref generics) => {
114114
ast::ItemStruct(fold_struct(cx, def), generics.clone())

src/librustc/metadata/common.rs

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ pub static tag_lang_items_item_node_id: uint = 0x73;
170170

171171
pub static tag_item_unnamed_field: uint = 0x74;
172172
pub static tag_items_data_item_visibility: uint = 0x76;
173+
pub static tag_items_data_item_sized: uint = 0x77;
173174

174175
pub static tag_item_method_tps: uint = 0x79;
175176
pub static tag_item_method_fty: uint = 0x7a;

src/librustc/metadata/decoder.rs

+21
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,19 @@ fn item_visibility(item: ebml::Doc) -> ast::Visibility {
164164
}
165165
}
166166

167+
fn item_sized(item: ebml::Doc) -> ast::Sized {
168+
match reader::maybe_get_doc(item, tag_items_data_item_sized) {
169+
None => ast::StaticSize,
170+
Some(sized_doc) => {
171+
match reader::doc_as_u8(sized_doc) as char {
172+
'd' => ast::DynSize,
173+
's' => ast::StaticSize,
174+
_ => fail!("unknown sized-ness character")
175+
}
176+
}
177+
}
178+
}
179+
167180
fn item_method_sort(item: ebml::Doc) -> char {
168181
let mut ret = 'r';
169182
reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
@@ -371,6 +384,7 @@ pub fn get_trait_def(cdata: Cmd,
371384
let tp_defs = item_ty_param_defs(item_doc, tcx, cdata,
372385
tag_items_data_item_ty_param_bounds);
373386
let rp_defs = item_region_param_defs(item_doc, cdata);
387+
let sized = item_sized(item_doc);
374388
let mut bounds = ty::EmptyBuiltinBounds();
375389
// Collect the builtin bounds from the encoded supertraits.
376390
// FIXME(#8559): They should be encoded directly.
@@ -382,6 +396,13 @@ pub fn get_trait_def(cdata: Cmd,
382396
});
383397
true
384398
});
399+
// Turn sized into a bound, FIXME(#8559).
400+
if sized == ast::StaticSize {
401+
tcx.lang_items.to_builtin_kind(tcx.lang_items.sized_trait().unwrap()).map(|bound| {
402+
bounds.add(bound);
403+
});
404+
}
405+
385406
ty::TraitDef {
386407
generics: ty::Generics {type_param_defs: tp_defs,
387408
region_param_defs: rp_defs},

src/librustc/metadata/encoder.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,16 @@ fn encode_extension_implementations(ecx: &EncodeContext,
832832
}
833833
}
834834

835+
fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
836+
ebml_w.start_tag(tag_items_data_item_sized);
837+
let ch = match sized {
838+
DynSize => 'd',
839+
StaticSize => 's',
840+
};
841+
ebml_w.wr_str(str::from_char(ch));
842+
ebml_w.end_tag();
843+
}
844+
835845
fn encode_info_for_item(ecx: &EncodeContext,
836846
ebml_w: &mut Encoder,
837847
item: &Item,
@@ -1070,7 +1080,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
10701080
ast_method)
10711081
}
10721082
}
1073-
ItemTrait(_, ref super_traits, ref ms) => {
1083+
ItemTrait(_, sized, ref super_traits, ref ms) => {
10741084
add_to_index(item, ebml_w, index);
10751085
ebml_w.start_tag(tag_items_data_item);
10761086
encode_def_id(ebml_w, def_id);
@@ -1084,6 +1094,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
10841094
encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
10851095
encode_name(ebml_w, item.ident.name);
10861096
encode_attributes(ebml_w, item.attrs.as_slice());
1097+
// When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
1098+
// should no longer need this ugly little hack either.
1099+
encode_sized(ebml_w, sized);
10871100
encode_visibility(ebml_w, vis);
10881101
for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
10891102
ebml_w.start_tag(tag_item_trait_method);

src/librustc/middle/privacy.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl Visitor<()> for ParentVisitor {
7979
// method to the root. In this case, if the trait is private, then
8080
// parent all the methods to the trait to indicate that they're
8181
// private.
82-
ast::ItemTrait(_, _, ref methods) if item.vis != ast::Public => {
82+
ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
8383
for m in methods.iter() {
8484
match *m {
8585
ast::Provided(ref m) => self.parents.insert(m.id, item.id),
@@ -274,7 +274,7 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
274274

275275
// Default methods on traits are all public so long as the trait
276276
// is public
277-
ast::ItemTrait(_, _, ref methods) if public_first => {
277+
ast::ItemTrait(_, _, _, ref methods) if public_first => {
278278
for method in methods.iter() {
279279
match *method {
280280
ast::Provided(ref m) => {
@@ -1082,7 +1082,7 @@ impl<'a> SanePrivacyVisitor<'a> {
10821082
}
10831083
}
10841084

1085-
ast::ItemTrait(_, _, ref methods) => {
1085+
ast::ItemTrait(_, _, _, ref methods) => {
10861086
for m in methods.iter() {
10871087
match *m {
10881088
ast::Provided(ref m) => {
@@ -1142,7 +1142,7 @@ impl<'a> SanePrivacyVisitor<'a> {
11421142

11431143
ast::ItemStruct(ref def, _) => check_struct(def),
11441144

1145-
ast::ItemTrait(_, _, ref methods) => {
1145+
ast::ItemTrait(_, _, _, ref methods) => {
11461146
for m in methods.iter() {
11471147
match *m {
11481148
ast::Required(..) => {}

src/librustc/middle/resolve.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,7 @@ impl<'a> Resolver<'a> {
13261326

13271327
ItemImpl(_, Some(_), _, _) => parent,
13281328

1329-
ItemTrait(_, _, ref methods) => {
1329+
ItemTrait(_, _, _, ref methods) => {
13301330
let name_bindings =
13311331
self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
13321332

@@ -3579,7 +3579,7 @@ impl<'a> Resolver<'a> {
35793579
methods.as_slice());
35803580
}
35813581

3582-
ItemTrait(ref generics, ref traits, ref methods) => {
3582+
ItemTrait(ref generics, _, ref traits, ref methods) => {
35833583
// Create a new rib for the self type.
35843584
let self_type_rib = Rib::new(NormalRibKind);
35853585
// plain insert (no renaming)
@@ -3787,9 +3787,8 @@ impl<'a> Resolver<'a> {
37873787
}
37883788
Some(declaration) => {
37893789
for argument in declaration.inputs.iter() {
3790-
let binding_mode = ArgumentIrrefutableMode;
37913790
this.resolve_pattern(argument.pat,
3792-
binding_mode,
3791+
ArgumentIrrefutableMode,
37933792
None);
37943793

37953794
this.resolve_type(argument.ty);

src/librustc/middle/resolve_lifetime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
8484
ast::ItemEnum(_, ref generics) |
8585
ast::ItemStruct(_, ref generics) |
8686
ast::ItemImpl(ref generics, _, _, _) |
87-
ast::ItemTrait(ref generics, _, _) => {
87+
ast::ItemTrait(ref generics, _, _, _) => {
8888
self.check_lifetime_names(&generics.lifetimes);
8989
EarlyScope(0, &generics.lifetimes, &root)
9090
}

src/librustc/middle/ty.rs

+2-13
Original file line numberDiff line numberDiff line change
@@ -2595,18 +2595,7 @@ pub fn type_is_machine(ty: t) -> bool {
25952595
// Is the type's representation size known at compile time?
25962596
#[allow(dead_code)] // leaving in for DST
25972597
pub fn type_is_sized(cx: &ctxt, ty: ty::t) -> bool {
2598-
match get(ty).sty {
2599-
// FIXME(#6308) add trait, vec, str, etc here.
2600-
ty_param(p) => {
2601-
let ty_param_defs = cx.ty_param_defs.borrow();
2602-
let param_def = ty_param_defs.get(&p.def_id.node);
2603-
if param_def.bounds.builtin_bounds.contains_elem(BoundSized) {
2604-
return true;
2605-
}
2606-
return false;
2607-
},
2608-
_ => return true,
2609-
}
2598+
type_contents(cx, ty).is_sized(cx)
26102599
}
26112600

26122601
// Whether a type is enum like, that is an enum type with only nullary
@@ -3500,7 +3489,7 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
35003489
match cx.map.find(id.node) {
35013490
Some(ast_map::NodeItem(item)) => {
35023491
match item.node {
3503-
ItemTrait(_, _, ref ms) => {
3492+
ItemTrait(_, _, _, ref ms) => {
35043493
let (_, p) = ast_util::split_trait_methods(ms.as_slice());
35053494
p.iter().map(|m| method(cx, ast_util::local_def(m.id))).collect()
35063495
}

0 commit comments

Comments
 (0)