]> git.lizzy.rs Git - rust.git/commitdiff
Change DST syntax: type -> Sized?
authorNick Cameron <ncameron@mozilla.com>
Tue, 8 Jul 2014 02:26:02 +0000 (14:26 +1200)
committerNick Cameron <ncameron@mozilla.com>
Tue, 8 Jul 2014 10:44:31 +0000 (22:44 +1200)
closes #13367

[breaking-change] Use `Sized?` to indicate a dynamically sized type parameter or trait (used to be `type`). E.g.,

```
trait Tr for Sized? {}

fn foo<Sized? X: Share>(x: X) {}
```

29 files changed:
src/librustc/front/config.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/middle/resolve.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/infer/error_reporting.rs
src/librustdoc/html/highlight.rs
src/libsyntax/ast.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/deriving/decodable.rs
src/libsyntax/ext/deriving/encodable.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/deriving/generic/ty.rs
src/libsyntax/ext/deriving/hash.rs
src/libsyntax/ext/deriving/rand.rs
src/libsyntax/fold.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/test/compile-fail/unsized-bare-typaram.rs
src/test/compile-fail/unsized-enum.rs
src/test/compile-fail/unsized-struct.rs
src/test/compile-fail/unsized3.rs
src/test/compile-fail/unsized4.rs
src/test/compile-fail/unsized5.rs
src/test/compile-fail/unsized6.rs
src/test/run-pass/unsized.rs
src/test/run-pass/unsized2.rs

index 2fa0ab9072c226f3ef566ba0cab6e37c5d4187e1..9bff6620aaafd624aea35b1acb4a7bd9f2c1f23e 100644 (file)
@@ -109,12 +109,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, b, ref c, ref methods) => {
+        ast::ItemTrait(ref a, ref 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, (*c).clone(), methods)
+            ast::ItemTrait((*a).clone(), (*b).clone(), (*c).clone(), methods)
         }
         ast::ItemStruct(ref def, ref generics) => {
             ast::ItemStruct(fold_struct(cx, &**def), generics.clone())
index f88c0d34ed83eebdf45eb7ce726e2fdf9e1df497..d16f24a0ad1b402d02f83d2a338beb846dbd9324 100644 (file)
@@ -164,19 +164,6 @@ 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| {
@@ -393,7 +380,6 @@ 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::empty_builtin_bounds();
     // Collect the builtin bounds from the encoded supertraits.
     // FIXME(#8559): They should be encoded directly.
@@ -405,12 +391,6 @@ 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 {types: tp_defs,
index 21713672f8149e82ab06ffce43dd4b2fb676e18b..0ec9e31872b60e3fc58b9c83639f8fcf2fa65c90 100644 (file)
@@ -881,16 +881,6 @@ 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).as_slice());
-    ebml_w.end_tag();
-}
-
 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
     stab_opt.map(|stab| {
         ebml_w.start_tag(tag_items_data_item_stability);
@@ -1149,7 +1139,7 @@ fn add_to_index(item: &Item, ebml_w: &Encoder,
                                    ast_method)
         }
       }
-      ItemTrait(_, sized, ref super_traits, ref ms) => {
+      ItemTrait(_, _, 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);
@@ -1163,9 +1153,6 @@ fn add_to_index(item: &Item, ebml_w: &Encoder,
         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);
         encode_stability(ebml_w, stab);
         for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
index 30a513407a5d5bae7bb2fbb3f471ae127d1a2efd..c2f4d2ff6b1e8d1c9252b4949d8c66f6cdd0daec 100644 (file)
@@ -3598,6 +3598,7 @@ fn resolve_item(&mut self, item: &Item) {
                                                                item.id,
                                                                ItemRibKind),
                                              |this| {
+                    this.resolve_type_parameters(&generics.ty_params);
                     visit::walk_item(this, item, ());
                 });
             }
@@ -3623,7 +3624,7 @@ fn resolve_item(&mut self, item: &Item) {
                                             methods.as_slice());
             }
 
-            ItemTrait(ref generics, _, ref traits, ref methods) => {
+            ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
                 // Create a new rib for the self type.
                 let self_type_rib = Rib::new(ItemRibKind);
 
@@ -3645,6 +3646,12 @@ fn resolve_item(&mut self, item: &Item) {
                     for trt in traits.iter() {
                         this.resolve_trait_reference(item.id, trt, TraitDerivation);
                     }
+                    match unbound {
+                        &Some(ast::TraitTyParamBound(ref tpb)) => {
+                            this.resolve_trait_reference(item.id, tpb, TraitDerivation);
+                        }
+                        _ => {}
+                    }
 
                     for method in (*methods).iter() {
                         // Create a new rib for the method-specific type
@@ -3856,11 +3863,15 @@ fn resolve_function(&mut self,
     }
 
     fn resolve_type_parameters(&mut self,
-                                   type_parameters: &OwnedSlice<TyParam>) {
+                               type_parameters: &OwnedSlice<TyParam>) {
         for type_parameter in type_parameters.iter() {
             for bound in type_parameter.bounds.iter() {
                 self.resolve_type_parameter_bound(type_parameter.id, bound);
             }
+            match &type_parameter.unbound {
+                &Some(ref unbound) => self.resolve_type_parameter_bound(type_parameter.id, unbound),
+                &None => {}
+            }
             match type_parameter.default {
                 Some(ref ty) => self.resolve_type(&**ty),
                 None => {}
@@ -3887,9 +3898,9 @@ fn resolve_type_parameter_bound(&mut self,
     }
 
     fn resolve_trait_reference(&mut self,
-                                   id: NodeId,
-                                   trait_reference: &TraitRef,
-                                   reference_type: TraitReferenceType) {
+                               id: NodeId,
+                               trait_reference: &TraitRef,
+                               reference_type: TraitReferenceType) {
         match self.resolve_path(id, &trait_reference.path, TypeNS, true) {
             None => {
                 let path_str = self.path_idents_to_str(&trait_reference.path);
index bf88ec5c438f28a62e3d52f61327a2b1dbb2b6af..7b871cbe0fe0da7819820e431096904812dc085b 100644 (file)
@@ -692,9 +692,9 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
         _ => {}
     }
 
-    let (generics, sized, supertraits) = match it.node {
-        ast::ItemTrait(ref generics, sized, ref supertraits, _) => {
-            (generics, sized, supertraits)
+    let (generics, unbound, supertraits) = match it.node {
+        ast::ItemTrait(ref generics, ref unbound, ref supertraits, _) => {
+            (generics, unbound, supertraits)
         }
         ref s => {
             tcx.sess.span_bug(
@@ -711,7 +711,7 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
                                             generics);
 
     let builtin_bounds =
-        ensure_supertraits(ccx, it.id, it.span, supertraits, sized);
+        ensure_supertraits(ccx, it.id, it.span, supertraits, unbound);
 
     let substs = mk_item_substs(ccx, &ty_generics);
     let trait_def = Rc::new(ty::TraitDef {
@@ -759,7 +759,7 @@ fn ensure_supertraits(ccx: &CrateCtxt,
                           id: ast::NodeId,
                           sp: codemap::Span,
                           ast_trait_refs: &Vec<ast::TraitRef>,
-                          sized: ast::Sized)
+                          unbound: &Option<ast::TyParamBound>)
                           -> ty::BuiltinBounds
     {
         let tcx = ccx.tcx;
@@ -798,15 +798,7 @@ fn ensure_supertraits(ccx: &CrateCtxt,
             }
         }
 
-        if sized == ast::StaticSize {
-            match tcx.lang_items.require(SizedTraitLangItem) {
-                Ok(def_id) => {
-                    ty::try_add_builtin_trait(tcx, def_id, &mut bounds);
-                }
-                Err(s) => tcx.sess.err(s.as_slice()),
-            };
-        }
-
+        add_unsized_bound(ccx, unbound, &mut bounds, "trait", sp);
         tcx.supertraits.borrow_mut().insert(local_def(id),
                                             Rc::new(ty_trait_refs));
         bounds
@@ -974,6 +966,43 @@ fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
                 &generics.ty_params, base_generics)
 }
 
+// Add the Sized bound, unless the type parameter is marked as `Sized?`.
+fn add_unsized_bound(ccx: &CrateCtxt,
+                     unbound: &Option<ast::TyParamBound>,
+                     bounds: &mut ty::BuiltinBounds,
+                     desc: &str,
+                     span: Span) {
+    let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
+    match unbound {
+        &Some(TraitTyParamBound(ref tpb)) => {
+            // #FIXME(8559) currently requires the unbound to be built-in.
+            let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
+            match kind_id {
+                Ok(kind_id) if trait_def_id != kind_id => {
+                    ccx.tcx.sess.span_warn(span,
+                                           format!("default bound relaxed \
+                                                    for a {}, but this does \
+                                                    nothing because the given \
+                                                    bound is not a default. \
+                                                    Only `Sized?` is supported.",
+                                                   desc).as_slice());
+                    ty::try_add_builtin_trait(ccx.tcx,
+                                              kind_id,
+                                              bounds);
+                }
+                _ => {}
+            }
+        }
+        _ if kind_id.is_ok() => {
+            ty::try_add_builtin_trait(ccx.tcx,
+                                      kind_id.unwrap(),
+                                      bounds);
+        }
+        // No lang item for Sized, so we can't add it as a bound.
+        _ => {}
+    }
+}
+
 fn ty_generics(ccx: &CrateCtxt,
                space: subst::ParamSpace,
                lifetimes: &Vec<ast::Lifetime>,
@@ -1016,7 +1045,7 @@ fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
         let bounds = Rc::new(compute_bounds(ccx,
                                             param_ty,
                                             &param.bounds,
-                                            param.sized,
+                                            &param.unbound,
                                             param.ident,
                                             param.span));
         let default = param.default.map(|path| {
@@ -1056,7 +1085,7 @@ fn compute_bounds(
         ccx: &CrateCtxt,
         param_ty: ty::ParamTy,
         ast_bounds: &OwnedSlice<ast::TyParamBound>,
-        sized: ast::Sized,
+        unbound: &Option<ast::TyParamBound>,
         ident: ast::Ident,
         span: Span) -> ty::ParamBounds
     {
@@ -1113,15 +1142,11 @@ fn compute_bounds(
             }
         }
 
-        if sized == ast::StaticSize {
-            match ccx.tcx.lang_items.require(SizedTraitLangItem) {
-                Ok(def_id) => { ty::try_add_builtin_trait(ccx.tcx,
-                                                          def_id,
-                                                          &mut param_bounds.builtin_bounds); },
-                // Fixme(13367) after `type` makes it into the snapshot, we can check this properly
-                Err(_s) => {}, //ccx.tcx.sess.err(s),
-            }
-        }
+        add_unsized_bound(ccx,
+                          unbound,
+                          &mut param_bounds.builtin_bounds,
+                          "type parameter",
+                          span);
 
         check_bounds_compatible(ccx.tcx, &param_bounds, ident, span);
 
index 053a75e72602ae8eb75e50eb345a7c6727663faf..35661c14aebe771a125e792f0e5133fa42633dd2 100644 (file)
@@ -895,9 +895,9 @@ fn rebuild_ty_params(&self,
                 ident: ty_param.ident,
                 id: ty_param.id,
                 bounds: bounds,
+                unbound: ty_param.unbound.clone(),
                 default: ty_param.default,
                 span: ty_param.span,
-                sized: ty_param.sized,
             }
         })
     }
index daa9ee3da844f88568d20df17b8eccece1425cd5..82bb1bd58a6d32f5164d8b630f46156a1f6542cd 100644 (file)
@@ -110,7 +110,7 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
             // miscellaneous, no highlighting
             t::DOT | t::DOTDOT | t::DOTDOTDOT | t::COMMA | t::SEMI |
                 t::COLON | t::MOD_SEP | t::LARROW | t::LPAREN |
-                t::RPAREN | t::LBRACKET | t::LBRACE | t::RBRACE => "",
+                t::RPAREN | t::LBRACKET | t::LBRACE | t::RBRACE | t::QUESTION => "",
             t::DOLLAR => {
                 if t::is_ident(&lexer.peek().tok) {
                     is_macro_nonterminal = true;
index ce1302c8db8749b31e813d3f8a132fb118d492f7..76dbae488393344245362b3c0d11b75fccd66551 100644 (file)
@@ -184,8 +184,8 @@ pub enum TyParamBound {
 pub struct TyParam {
     pub ident: Ident,
     pub id: NodeId,
-    pub sized: Sized,
     pub bounds: OwnedSlice<TyParamBound>,
+    pub unbound: Option<TyParamBound>,
     pub default: Option<P<Ty>>,
     pub span: Span
 }
@@ -1041,12 +1041,6 @@ pub fn inherit_from(&self, parent_visibility: Visibility) -> Visibility {
     }
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
-pub enum Sized {
-    DynSize,
-    StaticSize,
-}
-
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct StructField_ {
     pub kind: StructFieldKind,
@@ -1115,7 +1109,11 @@ pub enum Item_ {
     ItemEnum(EnumDef, Generics),
     ItemStruct(Gc<StructDef>, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Generics, Sized, Vec<TraitRef> , Vec<TraitMethod> ),
+    ItemTrait(Generics,
+              Option<TyParamBound>, // (optional) default bound not required for Self.
+                                    // Currently, only Sized makes sense here.
+              Vec<TraitRef> ,
+              Vec<TraitMethod>),
     ItemImpl(Generics,
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
index 46bc4ec11ce4f044ac14b35d1f603042558bf089..4d79ff3257a9a20cd3b58cd5e330ff923a019e97 100644 (file)
@@ -66,8 +66,8 @@ fn ty_rptr(&self, span: Span,
     fn typaram(&self,
                span: Span,
                id: ast::Ident,
-               sized: ast::Sized,
                bounds: OwnedSlice<ast::TyParamBound>,
+               unbound: Option<ast::TyParamBound>,
                default: Option<P<ast::Ty>>) -> ast::TyParam;
 
     fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
@@ -396,14 +396,14 @@ fn ty_nil(&self) -> P<ast::Ty> {
     fn typaram(&self,
                span: Span,
                id: ast::Ident,
-               sized: ast::Sized,
                bounds: OwnedSlice<ast::TyParamBound>,
+               unbound: Option<ast::TyParamBound>,
                default: Option<P<ast::Ty>>) -> ast::TyParam {
         ast::TyParam {
             ident: id,
             id: ast::DUMMY_NODE_ID,
-            sized: sized,
             bounds: bounds,
+            unbound: unbound,
             default: default,
             span: span
         }
@@ -423,7 +423,7 @@ fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>
 
     fn strip_bounds(&self, generics: &Generics) -> Generics {
         let new_params = generics.ty_params.map(|ty_param| {
-            ast::TyParam { bounds: OwnedSlice::empty(), ..*ty_param }
+            ast::TyParam { bounds: OwnedSlice::empty(), unbound: None, ..*ty_param }
         });
         Generics {
             ty_params: new_params,
index 0c23d65fde046e788da842b10c50008c0160d1b1..6da5f1e2700f1a969c5cb962f22a06697171dea9 100644 (file)
@@ -13,7 +13,6 @@
 encodable.rs for more.
 */
 
-use ast;
 use ast::{MetaItem, Item, Expr, MutMutable, Ident};
 use codemap::Span;
 use ext::base::ExtCtxt;
@@ -39,10 +38,10 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__D", ast::StaticSize, vec!(Path::new_(
+            bounds: vec!(("__D", None, vec!(Path::new_(
                             vec!("serialize", "Decoder"), None,
                             vec!(box Literal(Path::new_local("__E"))), true))),
-                         ("__E", ast::StaticSize, vec!()))
+                         ("__E", None, vec!()))
         },
         methods: vec!(
             MethodDef {
index f57670af1999b3c90be860f84f67907ba012f91a..652d593c0042ca97d973fafa124646403755bc19 100644 (file)
@@ -82,7 +82,6 @@ fn decode(d: &D) -> spanned<T> {
 ```
 */
 
-use ast;
 use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil};
 use codemap::Span;
 use ext::base::ExtCtxt;
@@ -107,10 +106,10 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__S", ast::StaticSize, vec!(Path::new_(
+            bounds: vec!(("__S", None, vec!(Path::new_(
                             vec!("serialize", "Encoder"), None,
                             vec!(box Literal(Path::new_local("__E"))), true))),
-                         ("__E", ast::StaticSize, vec!()))
+                         ("__E", None, vec!()))
         },
         methods: vec!(
             MethodDef {
index 157b64fb47c0a7fa3d699681bb0d223d7a718f46..7ad11b186f5004a3f0891983d79d0b87ff6fe003 100644 (file)
@@ -406,8 +406,8 @@ fn create_derived_impl(&self,
 
             cx.typaram(self.span,
                        ty_param.ident,
-                       ty_param.sized,
                        OwnedSlice::from_vec(bounds),
+                       ty_param.unbound.clone(),
                        None)
         }));
         let trait_generics = Generics {
index 7501b950770c2e0c96f603d7d536a612792265c3..28f39a4cb8c0fd470cf5b31ebd613a9dad6eb262 100644 (file)
@@ -188,17 +188,18 @@ pub fn to_path(&self,
 }
 
 
-fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, sized: ast::Sized, bounds: &[Path],
+fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
+               bounds: &[Path], unbound: Option<ast::TyParamBound>,
                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(span, cx.ident_of(name), sized, bounds, None)
+    cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
 }
 
-fn mk_generics(lifetimes: Vec<ast::Lifetime> ,  ty_params: Vec<ast::TyParam> ) -> Generics {
+fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
     Generics {
         lifetimes: lifetimes,
         ty_params: OwnedSlice::from_vec(ty_params)
@@ -208,7 +209,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, ast::Sized, Vec<Path<'a>>)>,
+    pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
 }
 
 impl<'a> LifetimeBounds<'a> {
@@ -228,12 +229,12 @@ pub fn to_generics(&self,
         }).collect();
         let ty_params = self.bounds.iter().map(|t| {
             match t {
-                &(ref name, sized, ref bounds) => {
+                &(ref name, ref unbound, ref bounds) => {
                     mk_ty_param(cx,
                                 span,
                                 *name,
-                                sized,
                                 bounds.as_slice(),
+                                unbound.clone(),
                                 self_ty,
                                 self_generics)
                 }
index 77fb013b269a222331a368e933bdedbb83e2946b..1b3ac47092a2d2e4dde17efc74a904ff3af74774 100644 (file)
@@ -8,7 +8,6 @@
 // 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;
@@ -30,7 +29,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                     vec!(box Literal(Path::new_local("__S"))), true),
          LifetimeBounds {
              lifetimes: Vec::new(),
-             bounds: vec!(("__S", ast::StaticSize,
+             bounds: vec!(("__S", None,
                            vec!(Path::new(vec!("std", "hash", "Writer"))))),
          },
          Path::new_local("__S"))
index f6a15ea917e187c74910ce9563da32f02e07e655..34b5f120d6ab8a62c4e094b30da52323b0960eba 100644 (file)
@@ -35,7 +35,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
                 generics: LifetimeBounds {
                     lifetimes: Vec::new(),
                     bounds: vec!(("R",
-                                  ast::StaticSize,
+                                  None,
                                   vec!( Path::new(vec!("std", "rand", "Rng")) )))
                 },
                 explicit_self: None,
index 04e6612daf1f008a7dcf3a7f4526fb23875dd2f9..80dd4a83e48f01876db8f4744a10831dfaae3a5f 100644 (file)
@@ -491,8 +491,8 @@ 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)),
+        unbound: tp.unbound.as_ref().map(|x| fold_ty_param_bound(x, fld)),
         default: tp.default.map(|x| fld.fold_ty(x)),
         span: tp.span
     }
@@ -666,7 +666,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 sized, ref traits, ref methods) => {
+        ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
             let methods = methods.iter().map(|method| {
                 match *method {
                     Required(ref m) => Required(folder.fold_type_method(m)),
@@ -674,7 +674,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
                 }
             }).collect();
             ItemTrait(fold_generics(generics, folder),
-                      *sized,
+                      unbound.clone(),
                       traits.iter().map(|p| fold_trait_ref(p, folder)).collect(),
                       methods)
         }
index 0f188fdf18a5a80c06ee94126b1ac47e16198674..1e72b2de20f732a024eec3d8fea49c0d845dfaf9 100644 (file)
@@ -849,6 +849,7 @@ fn next_token_inner(&mut self) -> token::Token {
           '@' => { self.bump(); return token::AT; }
           '#' => { self.bump(); return token::POUND; }
           '~' => { self.bump(); return token::TILDE; }
+          '?' => { self.bump(); return token::QUESTION; }
           ':' => {
             self.bump();
             if self.curr_is(':') {
index 6b6387b0127861828ea5382d75ee58b75c23f4e2..3119d34128184b279d49603cde766aeba6592f53 100644 (file)
@@ -42,7 +42,6 @@
 use ast::{PatTup, PatBox, 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;
@@ -3564,11 +3563,40 @@ fn parse_ty_param_bounds(&mut self, allow_any_lifetime: bool)
         return (ret_lifetime, OwnedSlice::from_vec(result));
     }
 
-    // matches typaram = type? IDENT optbounds ( EQ ty )?
+    fn trait_ref_from_ident(ident: Ident, span: Span) -> ast::TraitRef {
+        let segment = ast::PathSegment {
+            identifier: ident,
+            lifetimes: Vec::new(),
+            types: OwnedSlice::empty(),
+        };
+        let path = ast::Path {
+            span: span,
+            global: false,
+            segments: vec![segment],
+        };
+        ast::TraitRef {
+            path: path,
+            ref_id: ast::DUMMY_NODE_ID,
+        }
+    }
+
+    // matches typaram = (unbound`?`)? 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();
+        // This is a bit hacky. Currently we are only interested in a single
+        // unbound, and it may only be `Sized`. To avoid backtracking and other
+        // complications, we parse an ident, then check for `?`. If we find it,
+        // we use the ident as the unbound, otherwise, we use it as the name of
+        // type param.
+        let mut span = self.span;
+        let mut ident = self.parse_ident();
+        let mut unbound = None;
+        if self.eat(&token::QUESTION) {
+            let tref = Parser::trait_ref_from_ident(ident, span);
+            unbound = Some(TraitTyParamBound(tref));
+            span = self.span;
+            ident = self.parse_ident();
+        }
+
         let opt_bounds = {
             if self.eat(&token::COLON) {
                 let (_, bounds) = self.parse_ty_param_bounds(false);
@@ -3589,8 +3617,8 @@ fn parse_ty_param(&mut self) -> TyParam {
         TyParam {
             ident: ident,
             id: ast::DUMMY_NODE_ID,
-            sized: sized,
             bounds: bounds,
+            unbound: unbound,
             default: default,
             span: span,
         }
@@ -4209,21 +4237,19 @@ fn parse_visibility(&mut self) -> Visibility {
         else { Inherited }
     }
 
-    fn parse_sized(&mut self) -> Sized {
-        if self.eat_keyword(keywords::Type) { DynSize }
-        else { StaticSize }
-    }
-
-    fn parse_for_sized(&mut self) -> Sized {
+    fn parse_for_sized(&mut self) -> Option<ast::TyParamBound> {
         if self.eat_keyword(keywords::For) {
-            if !self.eat_keyword(keywords::Type) {
-                let last_span = self.last_span;
-                self.span_err(last_span,
-                    "expected 'type' after for in trait item");
+            let span = self.span;
+            let ident = self.parse_ident();
+            if !self.eat(&token::QUESTION) {
+                self.span_err(span,
+                    "expected 'Sized?' after `for` in trait item");
+                return None;
             }
-            DynSize
+            let tref = Parser::trait_ref_from_ident(ident, span);
+            Some(TraitTyParamBound(tref))
         } else {
-            StaticSize
+            None
         }
     }
 
index dcf37e37ff0a786f0bc40882052ec6efac5bf7d9..367b18916ac1ddf150b3126de104e8444ef31841 100644 (file)
@@ -76,6 +76,7 @@ pub enum Token {
     RBRACE,
     POUND,
     DOLLAR,
+    QUESTION,
 
     /* Literals */
     LIT_BYTE(u8),
@@ -195,6 +196,7 @@ pub fn to_str(t: &Token) -> String {
       RBRACE => "}".to_string(),
       POUND => "#".to_string(),
       DOLLAR => "$".to_string(),
+      QUESTION => "?".to_string(),
 
       /* Literals */
       LIT_BYTE(b) => {
index bf2101108293960cb25ea4c74b997f21ca33a4d9..cdaa9bbd8ddb3d65b8a8c2eaa295d7789f3f7ddf 100644 (file)
@@ -740,14 +740,19 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
                 }
                 try!(self.bclose(item.span));
             }
-            ast::ItemTrait(ref generics, ref sized, ref traits, ref methods) => {
+            ast::ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
                 try!(self.head(visibility_qualified(item.vis,
                                                     "trait").as_slice()));
                 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"));
+                match unbound {
+                    &Some(TraitTyParamBound(ref tref)) => {
+                        try!(space(&mut self.s));
+                        try!(self.word_space("for"));
+                        try!(self.print_trait_ref(tref));
+                        try!(word(&mut self.s, "?"));
+                    }
+                    _ => {}
                 }
                 if traits.len() != 0u {
                     try!(word(&mut self.s, ":"));
@@ -2029,8 +2034,12 @@ pub fn print_generics(&mut self,
                     } else {
                         let idx = idx - generics.lifetimes.len();
                         let param = generics.ty_params.get(idx);
-                        if param.sized == ast::DynSize {
-                            try!(s.word_space("type"));
+                        match param.unbound {
+                            Some(TraitTyParamBound(ref tref)) => {
+                                try!(s.print_trait_ref(tref));
+                                try!(s.word_space("?"));
+                            }
+                            _ => {}
                         }
                         try!(s.print_ident(param.ident));
                         try!(s.print_bounds(&None,
index fd09d78a4fa625a4d45ca766482943a6789a728a..6fd749b129819362c479ecf4d9ef759d7df1107e 100644 (file)
@@ -10,5 +10,5 @@
 
 // error-pattern: instantiating a type parameter with an incompatible type
 fn bar<T: Sized>() { }
-fn foo<type T>() { bar::<T>() }
+fn foo<Sized? T>() { bar::<T>() }
 fn main() { }
index f586fbb576b323110c24e5b6d9dac73b489254b4..651eb26cadc6fe268a1526d29dab7ae4fa2b2c61 100644 (file)
@@ -10,5 +10,5 @@
 
 // error-pattern: instantiating a type parameter with an incompatible type
 fn bar<T: Sized>() { }
-fn foo<type T>() { bar::<Option<T>>() }
+fn foo<Sized? T>() { bar::<Option<T>>() }
 fn main() { }
index 9fab3accbb9de8dcb8b7ae03c1e33aebb4ee6916..ec6aafb43f46f5dc04e082838d20b2e64559207c 100644 (file)
@@ -13,5 +13,5 @@
 struct Foo<T> { data: T }
 
 fn bar<T: Sized>() { }
-fn foo<type T>() { bar::<Foo<T>>() }
+fn foo<Sized? T>() { bar::<Foo<T>>() }
 fn main() { }
index c5cc7e8f7163b271d4c4a97535bb173500daf6d7..c07dcf9368385425b6cbd0411a5ac443666075b4 100644 (file)
 
 
 // Unbounded.
-fn f1<type X>(x: &X) {
+fn f1<Sized? X>(x: &X) {
     f2::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
 }
 fn f2<X>(x: &X) {
 }
 
 // Bounded.
-trait T for type {}
-fn f3<type X: T>(x: &X) {
+trait T for Sized? {}
+fn f3<Sized? X: T>(x: &X) {
     f4::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
 }
 fn f4<X: T>(x: &X) {
 }
 
 // Test with unsized enum.
-enum E<type X> {
+enum E<Sized? X> {
     V(X),
 }
 
 fn f5<Y>(x: &Y) {}
-fn f6<type X>(x: &X) {}
-fn f7<type X>(x1: &E<X>, x2: &E<X>) {
+fn f6<Sized? X>(x: &X) {}
+fn f7<Sized? X>(x1: &E<X>, x2: &E<X>) {
     f5(x1); //~ERROR instantiating a type parameter with an incompatible type `E<X>`, which does not
     f6(x2); // ok
 }
 
 
 // Test with unsized struct.
-struct S<type X> {
+struct S<Sized? X> {
     x: X,
 }
 
-fn f8<type X>(x1: &S<X>, x2: &S<X>) {
+fn f8<Sized? X>(x1: &S<X>, x2: &S<X>) {
     f5(x1); //~ERROR instantiating a type parameter with an incompatible type `S<X>`, which does not
     f6(x2); // ok
 }
 
 // Test some tuples.
-fn f9<type X>(x1: Box<S<X>>, x2: Box<E<X>>) {
+fn f9<Sized? X>(x1: Box<S<X>>, x2: Box<E<X>>) {
     f5(&(*x1, 34i)); //~ERROR instantiating a type parameter with an incompatible type `(S<X>,int)`,
     f5(&(32i, *x2)); //~ERROR instantiating a type parameter with an incompatible type `(int,E<X>)`,
 }
@@ -60,20 +60,20 @@ fn f9<type X>(x1: Box<S<X>>, x2: Box<E<X>>) {
 // impl - bounded
 trait T1<Z: T> {
 }
-struct S3<type Y>;
-impl<type X: T> T1<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type
+struct S3<Sized? Y>;
+impl<Sized? X: T> T1<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type
 }
 
 // impl - unbounded
 trait T2<Z> {
 }
-impl<type X> T2<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type `X`
+impl<Sized? X> T2<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type `X
 
 // impl - struct
-trait T3<type Z> {
+trait T3<Sized? Z> {
 }
 struct S4<Y>;
-impl<type X> T3<X> for S4<X> { //ERROR instantiating a type parameter with an incompatible type `X`
+impl<Sized? X> T3<X> for S4<X> { //ERROR instantiating a type parameter with an incompatible type `X
 }
 */
 
index 968716320fd5ed6b63f1f842181622bac368729f..e377c9d5f417342f578373fbe512b4a46c1d32f4 100644 (file)
@@ -11,7 +11,7 @@
 // Test that bounds are sized-compatible.
 
 trait T {}
-fn f<type Y: T>() {
+fn f<Sized? Y: T>() {
 //~^ERROR incompatible bounds on type parameter Y, bound T does not allow unsized type
 }
 
index 614b8e3a5ab67904e60ff1acaea0882b0bddca40..7028f7e798b014b99f1a529c7ec795f23281e7e7 100644 (file)
@@ -9,19 +9,19 @@
 // except according to those terms.
 #![feature(struct_variant)]
 
-// Test `type` types not allowed in fields.
+// Test `Sized?` types not allowed in fields.
 
-struct S1<type X> {
+struct S1<Sized? X> {
     f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the
     f2: int,
 }
-struct S2<type X> {
+struct S2<Sized? X> {
     f: int,
     g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty
     h: int,
 }
 
-enum E<type X> {
+enum E<Sized? X> {
     V1(X, int), //~ERROR type `X` is dynamically sized. dynamically sized types may only appear as t
     V2{f1: X, f: int}, //~ERROR type `f1` is dynamically sized. dynamically sized types may only app
 }
index 061b003b5e3f023360e1e3d64c68437eddb89d15..def1146526b3920ab687411646849e2564fc55bc 100644 (file)
@@ -8,37 +8,37 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test `type` local variables.
+// Test `Sized?` local variables.
 
 
-trait T for type {}
+trait T for Sized? {}
 
-fn f1<type X>(x: &X) {
+fn f1<Sized? X>(x: &X) {
     let _: X; //~ERROR variable `_` has dynamically sized type `X`
     let _: (int, (X, int)); //~ERROR variable `_` has dynamically sized type `(int,(X,int))`
     let y: X; //~ERROR variable `y` has dynamically sized type `X`
     let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
 }
-fn f2<type X: T>(x: &X) {
+fn f2<Sized? X: T>(x: &X) {
     let _: X; //~ERROR variable `_` has dynamically sized type `X`
     let _: (int, (X, int)); //~ERROR variable `_` has dynamically sized type `(int,(X,int))`
     let y: X; //~ERROR variable `y` has dynamically sized type `X`
     let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
 }
 
-fn f3<type X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+fn f3<Sized? X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
     let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
     let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
     let (y, z) = (*x3, 4i); //~ERROR variable `y` has dynamically sized type `X`
 }
-fn f4<type X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+fn f4<Sized? X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
     let y: X = *x1;         //~ERROR variable `y` has dynamically sized type `X`
     let y = *x2;            //~ERROR variable `y` has dynamically sized type `X`
     let (y, z) = (*x3, 4i); //~ERROR variable `y` has dynamically sized type `X`
 }
 
-fn g1<type X>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
-fn g2<type X: T>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
+fn g1<Sized? X>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
+fn g2<Sized? X: T>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
 
 pub fn main() {
 }
index db0cc83d7866af826dcdadb3602850083b1b822c..f49e8f46e78e6a476f56f7a5380300789f1ed3f5 100644 (file)
@@ -8,20 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test syntax checks for `type` keyword.
+// Test syntax checks for `Sized?` syntax.
 
-trait T1 for type {}
-pub trait T2 for type {}
-trait T3<X: T1> for type: T2 {}
-trait T4<type X> {}
-trait T5<type X, Y> {}
-trait T6<Y, type X> {}
-trait T7<type X, type Y> {}
-trait T8<type X: T2> {}
-struct S1<type X>;
-enum E<type X> {}
-impl <type X> T1 for S1<X> {}
-fn f<type X>() {}
+trait T1 for Sized? {}
+pub trait T2 for Sized? {}
+trait T3<X: T1> for Sized?: T2 {}
+trait T4<Sized? X> {}
+trait T5<Sized? X, Y> {}
+trait T6<Y, Sized? X> {}
+trait T7<Sized? X, Sized? Y> {}
+trait T8<Sized? X: T2> {}
+struct S1<Sized? X>;
+enum E<Sized? X> {}
+impl <Sized? X> T1 for S1<X> {}
+fn f<Sized? X>() {}
 
 pub fn main() {
 }
index 53db7f37e8d51309c4d2e6b224dd092a69dc8c09..9703b55cda760855c10c5bc9fd5b07af1190a0a3 100644 (file)
@@ -13,7 +13,7 @@
 // Test sized-ness checking in substitution.
 
 // Unbounded.
-fn f1<type X>(x: &X) {
+fn f1<Sized? X>(x: &X) {
     f1::<X>(x);
 }
 fn f2<X>(x: &X) {
@@ -22,8 +22,8 @@ fn f2<X>(x: &X) {
 }
 
 // Bounded.
-trait T for type {}
-fn f3<type X: T>(x: &X) {
+trait T for Sized? {}
+fn f3<Sized? X: T>(x: &X) {
     f3::<X>(x);
 }
 fn f4<X: T>(x: &X) {
@@ -32,7 +32,7 @@ fn f4<X: T>(x: &X) {
 }
 
 // Self type.
-trait T2 for type {
+trait T2 for Sized? {
     fn f() -> Box<Self>;
 }
 struct S;
@@ -41,14 +41,14 @@ fn f() -> Box<S> {
         box S
     }
 }
-fn f5<type X: T2>(x: &X) {
+fn f5<Sized? X: T2>(x: &X) {
     let _: Box<X> = T2::f();
 }
 fn f6<X: T2>(x: &X) {
     let _: Box<X> = T2::f();
 }
 
-trait T3 for type {
+trait T3 for Sized? {
     fn f() -> Box<Self>;
 }
 impl T3 for S {
@@ -56,7 +56,7 @@ fn f() -> Box<S> {
         box S
     }
 }
-fn f7<type X: T3>(x: &X) {
+fn f7<Sized? X: T3>(x: &X) {
     // This is valid, but the unsized bound on X is irrelevant because any type
     // which implements T3 must have statically known size.
     let _: Box<X> = T3::f();
@@ -66,7 +66,7 @@ trait T4<X> {
     fn m1(x: &T4<X>);
     fn m2(x: &T5<X>);
 }
-trait T5<type X> {
+trait T5<Sized? X> {
     // not an error (for now)
     fn m1(x: &T4<X>);
     fn m2(x: &T5<X>);
@@ -76,21 +76,21 @@ trait T6<X: T> {
     fn m1(x: &T4<X>);
     fn m2(x: &T5<X>);
 }
-trait T7<type X: T> {
+trait T7<Sized? X: T> {
     // not an error (for now)
     fn m1(x: &T4<X>);
     fn m2(x: &T5<X>);
 }
 
 // The last field in a struct or variant may be unsized
-struct S2<type X> {
+struct S2<Sized? X> {
     f: X,
 }
-struct S3<type X> {
+struct S3<Sized? X> {
     f1: int,
     f2: X,
 }
-enum E<type X> {
+enum E<Sized? X> {
     V1(X),
     V2{x: X},
     V3(int, X),