Skip to content

Commit f78add1

Browse files
committed
Support unsized types with the type keyword
1 parent c3b2f2b commit f78add1

39 files changed

+484
-73
lines changed

src/librustc/front/config.rs

Lines changed: 2 additions & 2 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 21 additions & 0 deletions
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

Lines changed: 14 additions & 1 deletion
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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ impl<'a> Resolver<'a> {
13251325

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

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

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

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

37943793
this.resolve_type(argument.ty);

src/librustc/middle/resolve_lifetime.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2591,16 +2591,24 @@ pub fn type_is_machine(ty: t) -> bool {
25912591
#[allow(dead_code)] // leaving in for DST
25922592
pub fn type_is_sized(cx: &ctxt, ty: ty::t) -> bool {
25932593
match get(ty).sty {
2594-
// FIXME(#6308) add trait, vec, str, etc here.
2595-
ty_param(p) => {
2594+
ty_param(tp) => {
2595+
assert_eq!(tp.def_id.krate, ast::LOCAL_CRATE);
2596+
25962597
let ty_param_defs = cx.ty_param_defs.borrow();
2597-
let param_def = ty_param_defs.get(&p.def_id.node);
2598-
if param_def.bounds.builtin_bounds.contains_elem(BoundSized) {
2599-
return true;
2600-
}
2601-
return false;
2598+
let param_def = ty_param_defs.get(&tp.def_id.node);
2599+
param_def.bounds.builtin_bounds.contains_elem(BoundSized)
26022600
},
2603-
_ => return true,
2601+
ty_self(def_id) => {
2602+
let trait_def = lookup_trait_def(cx, def_id);
2603+
trait_def.bounds.contains_elem(BoundSized)
2604+
},
2605+
ty_struct(def_id, ref substs) => {
2606+
let flds = lookup_struct_fields(cx, def_id);
2607+
let mut tps = flds.iter().map(|f| lookup_field_type(cx, def_id, f.id, substs));
2608+
!tps.any(|ty| !type_is_sized(cx, ty))
2609+
}
2610+
ty_tup(ref ts) => !ts.iter().any(|t| !type_is_sized(cx, *t)),
2611+
_ => true
26042612
}
26052613
}
26062614

@@ -3495,7 +3503,7 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
34953503
match cx.map.find(id.node) {
34963504
Some(ast_map::NodeItem(item)) => {
34973505
match item.node {
3498-
ItemTrait(_, _, ref ms) => {
3506+
ItemTrait(_, _, _, ref ms) => {
34993507
let (_, p) = ast_util::split_trait_methods(ms.as_slice());
35003508
p.iter().map(|m| method(cx, ast_util::local_def(m.id))).collect()
35013509
}

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

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -369,21 +369,21 @@ impl<'a> GatherLocalsVisitor<'a> {
369369
}
370370

371371
impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
372-
// Add explicitly-declared locals.
372+
// Add explicitly-declared locals.
373373
fn visit_local(&mut self, local: &ast::Local, _: ()) {
374-
let o_ty = match local.ty.node {
375-
ast::TyInfer => None,
376-
_ => Some(self.fcx.to_ty(local.ty))
377-
};
378-
self.assign(local.id, o_ty);
379-
debug!("Local variable {} is assigned type {}",
380-
self.fcx.pat_to_str(local.pat),
381-
self.fcx.infcx().ty_to_str(
382-
self.fcx.inh.locals.borrow().get_copy(&local.id)));
383-
visit::walk_local(self, local, ());
384-
374+
let o_ty = match local.ty.node {
375+
ast::TyInfer => None,
376+
_ => Some(self.fcx.to_ty(local.ty))
377+
};
378+
self.assign(local.id, o_ty);
379+
debug!("Local variable {} is assigned type {}",
380+
self.fcx.pat_to_str(local.pat),
381+
self.fcx.infcx().ty_to_str(
382+
self.fcx.inh.locals.borrow().get_copy(&local.id)));
383+
visit::walk_local(self, local, ());
385384
}
386-
// Add pattern bindings.
385+
386+
// Add pattern bindings.
387387
fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
388388
match p.node {
389389
ast::PatIdent(_, ref path, _)
@@ -561,14 +561,37 @@ fn check_for_field_shadowing(tcx: &ty::ctxt,
561561
}
562562
}
563563

564+
fn check_fields_sized(tcx: &ty::ctxt,
565+
id: ast::NodeId) {
566+
let struct_def = tcx.map.expect_struct(id);
567+
// FIXME(#13121) allow the last field to be DST
568+
for f in struct_def.fields.iter() {
569+
let t = ty::node_id_to_type(tcx, f.node.id);
570+
if !ty::type_is_sized(tcx, t) {
571+
match f.node.kind {
572+
ast::NamedField(ident, _) => {
573+
tcx.sess.span_err(f.span, format!("Dynamically sized type in field {}",
574+
token::get_ident(ident)));
575+
}
576+
ast::UnnamedField(_) => {
577+
tcx.sess.span_err(f.span, "Dynamically sized type in field");
578+
}
579+
}
580+
}
581+
}
582+
}
583+
564584
pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
565585
let tcx = ccx.tcx;
566586

567587
// Check that the struct is representable
568588
check_representable(tcx, span, id, "struct");
569589

570590
// Check that the struct is instantiable
571-
check_instantiable(tcx, span, id);
591+
if check_instantiable(tcx, span, id) {
592+
// This might cause stack overflow if id is not instantiable.
593+
check_fields_sized(tcx, id);
594+
}
572595

573596
// Check there are no overlapping fields in super-structs
574597
check_for_field_shadowing(tcx, local_def(id));
@@ -630,7 +653,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
630653
}
631654

632655
}
633-
ast::ItemTrait(_, _, ref trait_methods) => {
656+
ast::ItemTrait(_, _, _, ref trait_methods) => {
634657
let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
635658
for trait_method in (*trait_methods).iter() {
636659
match *trait_method {
@@ -3468,14 +3491,16 @@ pub fn check_representable(tcx: &ty::ctxt,
34683491
/// is representable, but not instantiable.
34693492
pub fn check_instantiable(tcx: &ty::ctxt,
34703493
sp: Span,
3471-
item_id: ast::NodeId) {
3494+
item_id: ast::NodeId) -> bool {
34723495
let item_ty = ty::node_id_to_type(tcx, item_id);
34733496
if !ty::is_instantiable(tcx, item_ty) {
34743497
tcx.sess.span_err(sp, format!("this type cannot be instantiated \
34753498
without an instance of itself; \
34763499
consider using `Option<{}>`",
34773500
ppaux::ty_to_str(tcx, item_ty)));
3501+
return false
34783502
}
3503+
true
34793504
}
34803505

34813506
pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {

0 commit comments

Comments
 (0)