Skip to content

Commit

Permalink
auto merge of rust-lang#13398 : nick29581/rust/unsized-enum, r=nikoma…
Browse files Browse the repository at this point in the history
…tsakis

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 rust-lang#12969 and rust-lang#13121, supersedes rust-lang#13375 (all the discussion there is valid here too).
  • Loading branch information
bors committed Apr 23, 2014
2 parents bcc3e8c + 5729d9b commit 696f16e
Show file tree
Hide file tree
Showing 40 changed files with 643 additions and 84 deletions.
4 changes: 2 additions & 2 deletions src/librustc/front/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ fn fold_item_underscore(cx: &mut Context, item: &ast::Item_) -> ast::Item_ {
.map(|x| *x).collect();
ast::ItemImpl((*a).clone(), (*b).clone(), c, methods)
}
ast::ItemTrait(ref a, ref b, ref methods) => {
ast::ItemTrait(ref a, b, ref c, ref methods) => {
let methods = methods.iter()
.filter(|m| trait_method_in_cfg(cx, *m) )
.map(|x| (*x).clone())
.collect();
ast::ItemTrait((*a).clone(), (*b).clone(), methods)
ast::ItemTrait((*a).clone(), b, (*c).clone(), methods)
}
ast::ItemStruct(def, ref generics) => {
ast::ItemStruct(fold_struct(cx, def), generics.clone())
Expand Down
1 change: 1 addition & 0 deletions src/librustc/metadata/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ pub static tag_lang_items_item_node_id: uint = 0x73;

pub static tag_item_unnamed_field: uint = 0x74;
pub static tag_items_data_item_visibility: uint = 0x76;
pub static tag_items_data_item_sized: uint = 0x77;

pub static tag_item_method_tps: uint = 0x79;
pub static tag_item_method_fty: uint = 0x7a;
Expand Down
21 changes: 21 additions & 0 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,19 @@ fn item_visibility(item: ebml::Doc) -> ast::Visibility {
}
}

fn item_sized(item: ebml::Doc) -> ast::Sized {
match reader::maybe_get_doc(item, tag_items_data_item_sized) {
None => ast::StaticSize,
Some(sized_doc) => {
match reader::doc_as_u8(sized_doc) as char {
'd' => ast::DynSize,
's' => ast::StaticSize,
_ => fail!("unknown sized-ness character")
}
}
}
}

fn item_method_sort(item: ebml::Doc) -> char {
let mut ret = 'r';
reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
Expand Down Expand Up @@ -371,6 +384,7 @@ pub fn get_trait_def(cdata: Cmd,
let tp_defs = item_ty_param_defs(item_doc, tcx, cdata,
tag_items_data_item_ty_param_bounds);
let rp_defs = item_region_param_defs(item_doc, cdata);
let sized = item_sized(item_doc);
let mut bounds = ty::EmptyBuiltinBounds();
// Collect the builtin bounds from the encoded supertraits.
// FIXME(#8559): They should be encoded directly.
Expand All @@ -382,6 +396,13 @@ pub fn get_trait_def(cdata: Cmd,
});
true
});
// Turn sized into a bound, FIXME(#8559).
if sized == ast::StaticSize {
tcx.lang_items.to_builtin_kind(tcx.lang_items.sized_trait().unwrap()).map(|bound| {
bounds.add(bound);
});
}

ty::TraitDef {
generics: ty::Generics {type_param_defs: tp_defs,
region_param_defs: rp_defs},
Expand Down
15 changes: 14 additions & 1 deletion src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,16 @@ fn encode_extension_implementations(ecx: &EncodeContext,
}
}

fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
ebml_w.start_tag(tag_items_data_item_sized);
let ch = match sized {
DynSize => 'd',
StaticSize => 's',
};
ebml_w.wr_str(str::from_char(ch));
ebml_w.end_tag();
}

fn encode_info_for_item(ecx: &EncodeContext,
ebml_w: &mut Encoder,
item: &Item,
Expand Down Expand Up @@ -1070,7 +1080,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
ast_method)
}
}
ItemTrait(_, ref super_traits, ref ms) => {
ItemTrait(_, sized, ref super_traits, ref ms) => {
add_to_index(item, ebml_w, index);
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, def_id);
Expand All @@ -1084,6 +1094,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
encode_name(ebml_w, item.ident.name);
encode_attributes(ebml_w, item.attrs.as_slice());
// When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
// should no longer need this ugly little hack either.
encode_sized(ebml_w, sized);
encode_visibility(ebml_w, vis);
for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
ebml_w.start_tag(tag_item_trait_method);
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl Visitor<()> for ParentVisitor {
// method to the root. In this case, if the trait is private, then
// parent all the methods to the trait to indicate that they're
// private.
ast::ItemTrait(_, _, ref methods) if item.vis != ast::Public => {
ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
for m in methods.iter() {
match *m {
ast::Provided(ref m) => self.parents.insert(m.id, item.id),
Expand Down Expand Up @@ -274,7 +274,7 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {

// Default methods on traits are all public so long as the trait
// is public
ast::ItemTrait(_, _, ref methods) if public_first => {
ast::ItemTrait(_, _, _, ref methods) if public_first => {
for method in methods.iter() {
match *method {
ast::Provided(ref m) => {
Expand Down Expand Up @@ -1082,7 +1082,7 @@ impl<'a> SanePrivacyVisitor<'a> {
}
}

ast::ItemTrait(_, _, ref methods) => {
ast::ItemTrait(_, _, _, ref methods) => {
for m in methods.iter() {
match *m {
ast::Provided(ref m) => {
Expand Down Expand Up @@ -1142,7 +1142,7 @@ impl<'a> SanePrivacyVisitor<'a> {

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

ast::ItemTrait(_, _, ref methods) => {
ast::ItemTrait(_, _, _, ref methods) => {
for m in methods.iter() {
match *m {
ast::Required(..) => {}
Expand Down
7 changes: 3 additions & 4 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1326,7 +1326,7 @@ impl<'a> Resolver<'a> {

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

ItemTrait(_, _, ref methods) => {
ItemTrait(_, _, _, ref methods) => {
let name_bindings =
self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);

Expand Down Expand Up @@ -3579,7 +3579,7 @@ impl<'a> Resolver<'a> {
methods.as_slice());
}

ItemTrait(ref generics, ref traits, ref methods) => {
ItemTrait(ref generics, _, ref traits, ref methods) => {
// Create a new rib for the self type.
let self_type_rib = Rib::new(NormalRibKind);
// plain insert (no renaming)
Expand Down Expand Up @@ -3787,9 +3787,8 @@ impl<'a> Resolver<'a> {
}
Some(declaration) => {
for argument in declaration.inputs.iter() {
let binding_mode = ArgumentIrrefutableMode;
this.resolve_pattern(argument.pat,
binding_mode,
ArgumentIrrefutableMode,
None);

this.resolve_type(argument.ty);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
ast::ItemEnum(_, ref generics) |
ast::ItemStruct(_, ref generics) |
ast::ItemImpl(ref generics, _, _, _) |
ast::ItemTrait(ref generics, _, _) => {
ast::ItemTrait(ref generics, _, _, _) => {
self.check_lifetime_names(&generics.lifetimes);
EarlyScope(0, &generics.lifetimes, &root)
}
Expand Down
15 changes: 2 additions & 13 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2595,18 +2595,7 @@ pub fn type_is_machine(ty: t) -> bool {
// Is the type's representation size known at compile time?
#[allow(dead_code)] // leaving in for DST
pub fn type_is_sized(cx: &ctxt, ty: ty::t) -> bool {
match get(ty).sty {
// FIXME(#6308) add trait, vec, str, etc here.
ty_param(p) => {
let ty_param_defs = cx.ty_param_defs.borrow();
let param_def = ty_param_defs.get(&p.def_id.node);
if param_def.bounds.builtin_bounds.contains_elem(BoundSized) {
return true;
}
return false;
},
_ => return true,
}
type_contents(cx, ty).is_sized(cx)
}

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

0 comments on commit 696f16e

Please sign in to comment.