diff options
| author | bors <bors@rust-lang.org> | 2014-04-22 20:51:31 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-04-22 20:51:31 -0700 |
| commit | 696f16ec2e54e8563702b1cdbbaaa1877562aa60 (patch) | |
| tree | 10336f159476418bd7a39af74a87359319ad5522 /src/libsyntax | |
| parent | bcc3e8c0d44bbbbf752db45a9c85f7ac4b4d61ce (diff) | |
| parent | 5729d9b41392ad153224acc2160f62205c9c1374 (diff) | |
| download | rust-696f16ec2e54e8563702b1cdbbaaa1877562aa60.tar.gz rust-696f16ec2e54e8563702b1cdbbaaa1877562aa60.zip | |
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).
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/ast_map.rs | 27 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/decodable.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/encodable.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/hash.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/rand.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/ty.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 29 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
13 files changed, 103 insertions, 22 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a6146e0eaea..116411c9e05 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -180,8 +180,10 @@ pub enum TyParamBound { pub struct TyParam { pub ident: Ident, pub id: NodeId, + pub sized: Sized, pub bounds: OwnedSlice<TyParamBound>, - pub default: Option<P<Ty>> + pub default: Option<P<Ty>>, + pub span: Span } #[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] @@ -1052,6 +1054,12 @@ impl Visibility { } #[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] +pub enum Sized { + DynSize, + StaticSize, +} + +#[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)] pub struct StructField_ { pub kind: StructFieldKind, pub id: NodeId, @@ -1109,7 +1117,7 @@ pub enum Item_ { ItemTy(P<Ty>, Generics), ItemEnum(EnumDef, Generics), ItemStruct(@StructDef, Generics), - ItemTrait(Generics, Vec<TraitRef> , Vec<TraitMethod> ), + ItemTrait(Generics, Sized, Vec<TraitRef> , Vec<TraitMethod> ), ItemImpl(Generics, Option<TraitRef>, // (optional) trait this impl implements P<Ty>, // self diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 45954800e7e..7a167237d3e 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -265,6 +265,31 @@ impl Map { } } + pub fn expect_struct(&self, id: NodeId) -> @StructDef { + match self.find(id) { + Some(NodeItem(i)) => { + match i.node { + ItemStruct(struct_def, _) => struct_def, + _ => fail!("struct ID bound to non-struct") + } + } + Some(NodeVariant(ref variant)) => { + match (*variant).node.kind { + StructVariantKind(struct_def) => struct_def, + _ => fail!("struct ID bound to enum variant that isn't struct-like"), + } + } + _ => fail!(format!("expected struct, found {}", self.node_to_str(id))), + } + } + + pub fn expect_variant(&self, id: NodeId) -> P<Variant> { + match self.find(id) { + Some(NodeVariant(variant)) => variant, + _ => fail!(format!("expected variant, found {}", self.node_to_str(id))), + } + } + pub fn expect_foreign_item(&self, id: NodeId) -> @ForeignItem { match self.find(id) { Some(NodeForeignItem(item)) => item, @@ -453,7 +478,7 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> { None => {} } } - ItemTrait(_, ref traits, ref methods) => { + ItemTrait(_, _, ref traits, ref methods) => { for t in traits.iter() { self.insert(t.ref_id, EntryItem(self.parent, i)); } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 203edf6590f..e1174ea6cc4 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -66,7 +66,9 @@ pub trait AstBuilder { fn strip_bounds(&self, bounds: &Generics) -> Generics; fn typaram(&self, + span: Span, id: ast::Ident, + sized: ast::Sized, bounds: OwnedSlice<ast::TyParamBound>, default: Option<P<ast::Ty>>) -> ast::TyParam; @@ -368,14 +370,18 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn typaram(&self, + span: Span, id: ast::Ident, + sized: ast::Sized, bounds: OwnedSlice<ast::TyParamBound>, default: Option<P<ast::Ty>>) -> ast::TyParam { ast::TyParam { ident: id, id: ast::DUMMY_NODE_ID, + sized: sized, bounds: bounds, - default: default + default: default, + span: span } } diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 579de82c8db..35a1eb0bb83 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -13,6 +13,7 @@ The compiler code necessary for `#[deriving(Decodable)]`. See encodable.rs for more. */ +use ast; use ast::{MetaItem, Item, Expr, MutMutable, Ident}; use codemap::Span; use ext::base::ExtCtxt; @@ -35,10 +36,10 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, additional_bounds: Vec::new(), generics: LifetimeBounds { lifetimes: Vec::new(), - bounds: vec!(("__D", vec!(Path::new_( + bounds: vec!(("__D", ast::StaticSize, vec!(Path::new_( vec!("serialize", "Decoder"), None, vec!(~Literal(Path::new_local("__E"))), true))), - ("__E", vec!())) + ("__E", ast::StaticSize, vec!())) }, methods: vec!( MethodDef { diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 1c3edce96fb..806560f6826 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -82,6 +82,7 @@ would yield functions like: ``` */ +use ast; use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil}; use codemap::Span; use ext::base::ExtCtxt; @@ -103,10 +104,10 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, additional_bounds: Vec::new(), generics: LifetimeBounds { lifetimes: Vec::new(), - bounds: vec!(("__S", vec!(Path::new_( + bounds: vec!(("__S", ast::StaticSize, vec!(Path::new_( vec!("serialize", "Encoder"), None, vec!(~Literal(Path::new_local("__E"))), true))), - ("__E", vec!())) + ("__E", ast::StaticSize, vec!())) }, methods: vec!( MethodDef { diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 1d4aa08f9e3..914451fb402 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -380,7 +380,11 @@ impl<'a> TraitDef<'a> { // require the current trait bounds.push(cx.typarambound(trait_path.clone())); - cx.typaram(ty_param.ident, OwnedSlice::from_vec(bounds), None) + cx.typaram(self.span, + ty_param.ident, + ty_param.sized, + OwnedSlice::from_vec(bounds), + None) })); let trait_generics = Generics { lifetimes: lifetimes, diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 23331dc03cb..d22027d203f 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use ast; use ast::{MetaItem, Item, Expr, MutMutable}; use codemap::Span; use ext::base::ExtCtxt; @@ -25,7 +26,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, vec!(~Literal(Path::new_local("__S"))), true), LifetimeBounds { lifetimes: Vec::new(), - bounds: vec!(("__S", vec!(Path::new(vec!("std", "io", "Writer"))))), + bounds: vec!(("__S", ast::StaticSize, vec!(Path::new(vec!("std", "io", "Writer"))))), }, Path::new_local("__S")) } else { diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 6b824e52bb3..e81aa55d10d 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -32,7 +32,8 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, generics: LifetimeBounds { lifetimes: Vec::new(), bounds: vec!(("R", - vec!( Path::new(vec!("rand", "Rng")) ))) + ast::StaticSize, + vec!( Path::new(vec!("rand", "Rng")) ))) }, explicit_self: None, args: vec!( diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs index c4ca2601f60..6e3327b4039 100644 --- a/src/libsyntax/ext/deriving/ty.rs +++ b/src/libsyntax/ext/deriving/ty.rs @@ -186,14 +186,14 @@ impl<'a> Ty<'a> { } -fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, bounds: &[Path], +fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, sized: ast::Sized, bounds: &[Path], self_ident: Ident, self_generics: &Generics) -> ast::TyParam { let bounds = bounds.iter().map(|b| { let path = b.to_path(cx, span, self_ident, self_generics); cx.typarambound(path) }).collect(); - cx.typaram(cx.ident_of(name), bounds, None) + cx.typaram(span, cx.ident_of(name), sized, bounds, None) } fn mk_generics(lifetimes: Vec<ast::Lifetime> , ty_params: Vec<ast::TyParam> ) -> Generics { @@ -206,7 +206,7 @@ fn mk_generics(lifetimes: Vec<ast::Lifetime> , ty_params: Vec<ast::TyParam> ) - /// Lifetimes and bounds on type parameters pub struct LifetimeBounds<'a> { pub lifetimes: Vec<&'a str>, - pub bounds: Vec<(&'a str, Vec<Path<'a>>)>, + pub bounds: Vec<(&'a str, ast::Sized, Vec<Path<'a>>)>, } impl<'a> LifetimeBounds<'a> { @@ -226,10 +226,11 @@ impl<'a> LifetimeBounds<'a> { }).collect(); let ty_params = self.bounds.iter().map(|t| { match t { - &(ref name, ref bounds) => { + &(ref name, sized, ref bounds) => { mk_ty_param(cx, span, *name, + sized, bounds.as_slice(), self_ty, self_generics) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 73ad2664be4..04b289b9fca 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -447,8 +447,10 @@ pub fn fold_ty_param<T: Folder>(tp: &TyParam, fld: &mut T) -> TyParam { TyParam { ident: tp.ident, id: id, + sized: tp.sized, bounds: tp.bounds.map(|x| fold_ty_param_bound(x, fld)), - default: tp.default.map(|x| fld.fold_ty(x)) + default: tp.default.map(|x| fld.fold_ty(x)), + span: tp.span } } @@ -619,7 +621,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_ methods.iter().map(|x| folder.fold_method(*x)).collect() ) } - ItemTrait(ref generics, ref traits, ref methods) => { + ItemTrait(ref generics, ref sized, ref traits, ref methods) => { let methods = methods.iter().map(|method| { match *method { Required(ref m) => Required(folder.fold_type_method(m)), @@ -627,6 +629,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_ } }).collect(); ItemTrait(fold_generics(generics, folder), + *sized, traits.iter().map(|p| fold_trait_ref(p, folder)).collect(), methods) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6485b5a3622..8808312bed7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -42,6 +42,7 @@ use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatUniq, PatWild, PatWildMulti}; use ast::{BiRem, Required}; use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl}; +use ast::{Sized, DynSize, StaticSize}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; use ast::{StructVariantKind, BiSub}; use ast::StrStyle; @@ -3390,8 +3391,10 @@ impl<'a> Parser<'a> { return (ret_lifetime, Some(OwnedSlice::from_vec(result))); } - // matches typaram = IDENT optbounds ( EQ ty )? + // matches typaram = type? IDENT optbounds ( EQ ty )? fn parse_ty_param(&mut self) -> TyParam { + let sized = self.parse_sized(); + let span = self.span; let ident = self.parse_ident(); let (_, opt_bounds) = self.parse_optional_ty_param_bounds(false); // For typarams we don't care about the difference b/w "<T>" and "<T:>". @@ -3406,8 +3409,10 @@ impl<'a> Parser<'a> { TyParam { ident: ident, id: ast::DUMMY_NODE_ID, + sized: sized, bounds: bounds, - default: default + default: default, + span: span, } } @@ -3795,6 +3800,7 @@ impl<'a> Parser<'a> { fn parse_item_trait(&mut self) -> ItemInfo { let ident = self.parse_ident(); let tps = self.parse_generics(); + let sized = self.parse_for_sized(); // Parse traits, if necessary. let traits; @@ -3806,7 +3812,7 @@ impl<'a> Parser<'a> { } let meths = self.parse_trait_methods(); - (ident, ItemTrait(tps, traits, meths), None) + (ident, ItemTrait(tps, sized, traits, meths), None) } // Parses two variants (with the region/type params always optional): @@ -3997,6 +4003,23 @@ impl<'a> Parser<'a> { else { Inherited } } + fn parse_sized(&mut self) -> Sized { + if self.eat_keyword(keywords::Type) { DynSize } + else { StaticSize } + } + + fn parse_for_sized(&mut self) -> Sized { + if self.eat_keyword(keywords::For) { + if !self.eat_keyword(keywords::Type) { + self.span_err(self.last_span, + "expected 'type' after for in trait item"); + } + DynSize + } else { + StaticSize + } + } + // given a termination token and a vector of already-parsed // attributes (of length 0 or 1), parse all of the items in a module fn parse_mod_items(&mut self, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f4e337e2048..f768bf22ce0 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -673,10 +673,14 @@ impl<'a> State<'a> { } try!(self.bclose(item.span)); } - ast::ItemTrait(ref generics, ref traits, ref methods) => { + ast::ItemTrait(ref generics, ref sized, ref traits, ref methods) => { try!(self.head(visibility_qualified(item.vis, "trait"))); try!(self.print_ident(item.ident)); try!(self.print_generics(generics)); + if *sized == ast::DynSize { + try!(space(&mut self.s)); + try!(word(&mut self.s, "for type")); + } if traits.len() != 0u { try!(word(&mut self.s, ":")); for (i, trait_) in traits.iter().enumerate() { @@ -1910,6 +1914,9 @@ impl<'a> State<'a> { } else { let idx = idx - generics.lifetimes.len(); let param = generics.ty_params.get(idx); + if param.sized == ast::DynSize { + try!(s.word_space("type")); + } try!(s.print_ident(param.ident)); try!(s.print_bounds(&None, ¶m.bounds, false)); match param.default { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 1f75c2e062f..e830daf8ede 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -257,7 +257,7 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E) item.id, env) } - ItemTrait(ref generics, ref trait_paths, ref methods) => { + ItemTrait(ref generics, _, ref trait_paths, ref methods) => { visitor.visit_generics(generics, env.clone()); for trait_path in trait_paths.iter() { visitor.visit_path(&trait_path.path, |
