about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-12-30 08:02:39 +0000
committerbors <bors@rust-lang.org>2014-12-30 08:02:39 +0000
commitd2368c3c11ddab9d812c4ddec2e44579326ad347 (patch)
treeb976bc0eb040da67646a9d99bb9b901cb9f55abd /src/libsyntax
parentfea5aa656ff4349f4d3e1fea1447d26986762ae1 (diff)
parent470ae101d6e26a6ce07292b7fca6eaed527451c7 (diff)
downloadrust-d2368c3c11ddab9d812c4ddec2e44579326ad347.tar.gz
rust-d2368c3c11ddab9d812c4ddec2e44579326ad347.zip
auto merge of #20320 : alexcrichton/rust/rollup, r=alexcrichton
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs15
-rw-r--r--src/libsyntax/ast_map/mod.rs4
-rw-r--r--src/libsyntax/config.rs4
-rw-r--r--src/libsyntax/ext/build.rs5
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs4
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs1
-rw-r--r--src/libsyntax/ext/deriving/generic/ty.rs17
-rw-r--r--src/libsyntax/ext/deriving/hash.rs2
-rw-r--r--src/libsyntax/ext/deriving/rand.rs1
-rw-r--r--src/libsyntax/fold.rs8
-rw-r--r--src/libsyntax/parse/parser.rs102
-rw-r--r--src/libsyntax/parse/token.rs2
-rw-r--r--src/libsyntax/print/pprust.rs31
-rw-r--r--src/libsyntax/visit.rs13
15 files changed, 137 insertions, 76 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index debcbcd2154..f253943943d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -371,10 +371,18 @@ pub const DUMMY_NODE_ID: NodeId = -1;
 /// detects Copy, Send and Sync.
 #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub enum TyParamBound {
-    TraitTyParamBound(PolyTraitRef),
+    TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
     RegionTyParamBound(Lifetime)
 }
 
+/// A modifier on a bound, currently this is only used for `?Sized`, where the
+/// modifier is `Maybe`. Negative bounds should also be handled here.
+#[deriving(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
+pub enum TraitBoundModifier {
+    None,
+    Maybe,
+}
+
 pub type TyParamBounds = OwnedSlice<TyParamBound>;
 
 #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
@@ -382,7 +390,6 @@ pub struct TyParam {
     pub ident: Ident,
     pub id: NodeId,
     pub bounds: TyParamBounds,
-    pub unbound: Option<TraitRef>,
     pub default: Option<P<Ty>>,
     pub span: Span
 }
@@ -1488,7 +1495,7 @@ pub struct PolyTraitRef {
     pub bound_lifetimes: Vec<LifetimeDef>,
 
     /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
-    pub trait_ref: TraitRef
+    pub trait_ref: TraitRef,
 }
 
 #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
@@ -1577,8 +1584,6 @@ pub enum Item_ {
     /// Represents a Trait Declaration
     ItemTrait(Unsafety,
               Generics,
-              Option<TraitRef>, // (optional) default bound not required for Self.
-                                // Currently, only Sized makes sense here.
               TyParamBounds,
               Vec<TraitItem>),
     ItemImpl(Unsafety,
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 9b42a8f7540..5a4f5731be5 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -780,9 +780,9 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                     None => {}
                 }
             }
-            ItemTrait(_, _, _, ref bounds, ref trait_items) => {
+            ItemTrait(_, _, ref bounds, ref trait_items) => {
                 for b in bounds.iter() {
-                    if let TraitTyParamBound(ref t) = *b {
+                    if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
                         self.insert(t.trait_ref.ref_id, NodeItem(i));
                     }
                 }
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index d2185a00876..94a3784291d 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -139,11 +139,11 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
                                        .collect();
             ast::ItemImpl(u, a, b, c, impl_items)
         }
-        ast::ItemTrait(u, a, b, c, methods) => {
+        ast::ItemTrait(u, a, b, methods) => {
             let methods = methods.into_iter()
                                  .filter(|m| trait_method_in_cfg(cx, m))
                                  .collect();
-            ast::ItemTrait(u, a, b, c, methods)
+            ast::ItemTrait(u, a, b, methods)
         }
         ast::ItemStruct(def, generics) => {
             ast::ItemStruct(fold_struct(cx, def), generics)
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 77165168746..239af188909 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -68,7 +68,6 @@ pub trait AstBuilder {
                span: Span,
                id: ast::Ident,
                bounds: OwnedSlice<ast::TyParamBound>,
-               unbound: Option<ast::TraitRef>,
                default: Option<P<ast::Ty>>) -> ast::TyParam;
 
     fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
@@ -414,13 +413,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                span: Span,
                id: ast::Ident,
                bounds: OwnedSlice<ast::TyParamBound>,
-               unbound: Option<ast::TraitRef>,
                default: Option<P<ast::Ty>>) -> ast::TyParam {
         ast::TyParam {
             ident: id,
             id: ast::DUMMY_NODE_ID,
             bounds: bounds,
-            unbound: unbound,
             default: default,
             span: span
         }
@@ -455,7 +452,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
-        ast::TraitTyParamBound(self.poly_trait_ref(path))
+        ast::TraitTyParamBound(self.poly_trait_ref(path), ast::TraitBoundModifier::None)
     }
 
     fn lifetime(&self, span: Span, name: ast::Name) -> ast::Lifetime {
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index 57dfbc0c6e8..3c8d74c14ee 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -58,10 +58,10 @@ fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__D", None, vec!(Path::new_(
+            bounds: vec!(("__D", vec!(Path::new_(
                             vec!(krate, "Decoder"), None,
                             vec!(box Literal(Path::new_local("__E"))), true))),
-                         ("__E", None, vec!()))
+                         ("__E", vec!()))
         },
         methods: vec!(
             MethodDef {
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 8bd3df6232c..5829f34bccc 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -134,10 +134,10 @@ fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__S", None, vec!(Path::new_(
+            bounds: vec!(("__S", vec!(Path::new_(
                             vec!(krate, "Encoder"), None,
                             vec!(box Literal(Path::new_local("__E"))), true))),
-                         ("__E", None, vec!()))
+                         ("__E", vec!()))
         },
         methods: vec!(
             MethodDef {
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index cf0201294ae..e4e31139d82 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -417,7 +417,6 @@ impl<'a> TraitDef<'a> {
             cx.typaram(self.span,
                        ty_param.ident,
                        OwnedSlice::from_vec(bounds),
-                       ty_param.unbound.clone(),
                        None)
         }));
 
diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs
index 56d11c2377f..95bdd8b9ffd 100644
--- a/src/libsyntax/ext/deriving/generic/ty.rs
+++ b/src/libsyntax/ext/deriving/generic/ty.rs
@@ -189,15 +189,19 @@ impl<'a> Ty<'a> {
 }
 
 
-fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
-               bounds: &[Path], unbound: Option<ast::TraitRef>,
-               self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
+fn mk_ty_param(cx: &ExtCtxt,
+               span: Span,
+               name: &str,
+               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(span, cx.ident_of(name), bounds, unbound, None)
+    cx.typaram(span, cx.ident_of(name), bounds, None)
 }
 
 fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
@@ -216,7 +220,7 @@ fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
 #[deriving(Clone)]
 pub struct LifetimeBounds<'a> {
     pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
-    pub bounds: Vec<(&'a str, Option<ast::TraitRef>, Vec<Path<'a>>)>,
+    pub bounds: Vec<(&'a str, Vec<Path<'a>>)>,
 }
 
 impl<'a> LifetimeBounds<'a> {
@@ -239,12 +243,11 @@ impl<'a> LifetimeBounds<'a> {
         }).collect();
         let ty_params = self.bounds.iter().map(|t| {
             match t {
-                &(ref name, ref unbound, ref bounds) => {
+                &(ref name, ref bounds) => {
                     mk_ty_param(cx,
                                 span,
                                 *name,
                                 bounds.as_slice(),
-                                unbound.clone(),
                                 self_ty,
                                 self_generics)
                 }
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index 4e59124a129..72e3b45dc91 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -30,7 +30,7 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
                     vec!(box Literal(Path::new_local("__S"))), true),
          LifetimeBounds {
              lifetimes: Vec::new(),
-             bounds: vec!(("__S", None,
+             bounds: vec!(("__S",
                            vec!(Path::new(vec!("std", "hash", "Writer"))))),
          },
          Path::new_local("__S"))
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index 4f6e4d1fb3c..1ddf5b2a5c3 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -36,7 +36,6 @@ pub fn expand_deriving_rand<F>(cx: &mut ExtCtxt,
                 generics: LifetimeBounds {
                     lifetimes: Vec::new(),
                     bounds: vec!(("R",
-                                  None,
                                   vec!( Path::new(vec!("std", "rand", "Rng")) )))
                 },
                 explicit_self: None,
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 11a9fdee0b9..4f0169e31f2 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -736,18 +736,17 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
                                    -> TyParamBound
                                    where T: Folder {
     match tpb {
-        TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_poly_trait_ref(ty)),
+        TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
         RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
     }
 }
 
 pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
-    let TyParam {id, ident, bounds, unbound, default, span} = tp;
+    let TyParam {id, ident, bounds, default, span} = tp;
     TyParam {
         id: fld.new_id(id),
         ident: ident,
         bounds: fld.fold_bounds(bounds),
-        unbound: unbound.map(|x| fld.fold_trait_ref(x)),
         default: default.map(|x| fld.fold_ty(x)),
         span: span
     }
@@ -1043,7 +1042,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
                      folder.fold_ty(ty),
                      new_impl_items)
         }
-        ItemTrait(unsafety, generics, unbound, bounds, methods) => {
+        ItemTrait(unsafety, generics, bounds, methods) => {
             let bounds = folder.fold_bounds(bounds);
             let methods = methods.into_iter().flat_map(|method| {
                 let r = match method {
@@ -1073,7 +1072,6 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             }).collect();
             ItemTrait(unsafety,
                       folder.fold_generics(generics),
-                      unbound,
                       bounds,
                       methods)
         }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2f43661eebe..e88aabb044c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -15,7 +15,7 @@ use self::ItemOrViewItem::*;
 
 use abi;
 use ast::{AssociatedType, BareFnTy, ClosureTy};
-use ast::{RegionTyParamBound, TraitTyParamBound};
+use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::{ProvidedMethod, Public, Unsafety};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
 use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, Block};
@@ -117,6 +117,13 @@ pub enum PathParsingMode {
     LifetimeAndTypesWithColons,
 }
 
+/// How to parse a bound, whether to allow bound modifiers such as `?`.
+#[deriving(Copy, PartialEq)]
+pub enum BoundParsingMode {
+    Bare,
+    Modified,
+}
+
 enum ItemOrViewItem {
     /// Indicates a failure to parse any kind of item. The attributes are
     /// returned.
@@ -1087,12 +1094,12 @@ impl<'a> Parser<'a> {
             let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs,
                                                      trait_ref: trait_ref };
             let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
-                self.parse_ty_param_bounds()
+                self.parse_ty_param_bounds(BoundParsingMode::Bare)
             } else {
                 OwnedSlice::empty()
             };
             let all_bounds =
-                Some(TraitTyParamBound(poly_trait_ref)).into_iter()
+                Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
                 .chain(other_bounds.into_vec().into_iter())
                 .collect();
             ast::TyPolyTraitRef(all_bounds)
@@ -1165,7 +1172,7 @@ impl<'a> Parser<'a> {
         // To be helpful, parse the proc as ever
         let _ = self.parse_legacy_lifetime_defs(lifetime_defs);
         let _ = self.parse_fn_args(false, false);
-        let _ = self.parse_colon_then_ty_param_bounds();
+        let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
         let _ = self.parse_ret_ty();
 
         self.obsolete(proc_span, ObsoleteProcType);
@@ -1255,7 +1262,7 @@ impl<'a> Parser<'a> {
             inputs
         };
 
-        let bounds = self.parse_colon_then_ty_param_bounds();
+        let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
 
         let output = self.parse_ret_ty();
         let decl = P(FnDecl {
@@ -1481,7 +1488,7 @@ impl<'a> Parser<'a> {
             return lhs;
         }
 
-        let bounds = self.parse_ty_param_bounds();
+        let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare);
 
         // In type grammar, `+` is treated like a binary operator,
         // and hence both L and R side are required.
@@ -4029,13 +4036,14 @@ impl<'a> Parser<'a> {
 
     // Parses a sequence of bounds if a `:` is found,
     // otherwise returns empty list.
-    fn parse_colon_then_ty_param_bounds(&mut self)
+    fn parse_colon_then_ty_param_bounds(&mut self,
+                                        mode: BoundParsingMode)
                                         -> OwnedSlice<TyParamBound>
     {
         if !self.eat(&token::Colon) {
             OwnedSlice::empty()
         } else {
-            self.parse_ty_param_bounds()
+            self.parse_ty_param_bounds(mode)
         }
     }
 
@@ -4043,14 +4051,20 @@ impl<'a> Parser<'a> {
     // where   boundseq  = ( polybound + boundseq ) | polybound
     // and     polybound = ( 'for' '<' 'region '>' )? bound
     // and     bound     = 'region | trait_ref
-    // NB: The None/Some distinction is important for issue #7264.
-    fn parse_ty_param_bounds(&mut self)
+    fn parse_ty_param_bounds(&mut self,
+                             mode: BoundParsingMode)
                              -> OwnedSlice<TyParamBound>
     {
         let mut result = vec!();
         loop {
+            let question_span = self.span;
+            let ate_question = self.eat(&token::Question);
             match self.token {
                 token::Lifetime(lifetime) => {
+                    if ate_question {
+                        self.span_err(question_span,
+                                      "`?` may only modify trait bounds, not lifetime bounds");
+                    }
                     result.push(RegionTyParamBound(ast::Lifetime {
                         id: ast::DUMMY_NODE_ID,
                         span: self.span,
@@ -4060,7 +4074,18 @@ impl<'a> Parser<'a> {
                 }
                 token::ModSep | token::Ident(..) => {
                     let poly_trait_ref = self.parse_poly_trait_ref();
-                    result.push(TraitTyParamBound(poly_trait_ref))
+                    let modifier = if ate_question {
+                        if mode == BoundParsingMode::Modified {
+                            TraitBoundModifier::Maybe
+                        } else {
+                            self.span_err(question_span,
+                                          "unexpected `?`");
+                            TraitBoundModifier::None
+                        }
+                    } else {
+                        TraitBoundModifier::None
+                    };
+                    result.push(TraitTyParamBound(poly_trait_ref, modifier))
                 }
                 _ => break,
             }
@@ -4089,13 +4114,14 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Matches typaram = (unbound`?`)? IDENT optbounds ( EQ ty )?
+    /// Matches typaram = (unbound `?`)? IDENT (`?` unbound)? optbounds ( EQ ty )?
     fn parse_ty_param(&mut self) -> TyParam {
         // 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.
+        // type param. Even worse, for now, we need to check for `?` before or
+        // after the bound.
         let mut span = self.span;
         let mut ident = self.parse_ident();
         let mut unbound = None;
@@ -4106,7 +4132,14 @@ impl<'a> Parser<'a> {
             ident = self.parse_ident();
         }
 
-        let bounds = self.parse_colon_then_ty_param_bounds();
+        let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified);
+        if let Some(unbound) = unbound {
+            let mut bounds_as_vec = bounds.into_vec();
+            bounds_as_vec.push(TraitTyParamBound(PolyTraitRef { bound_lifetimes: vec![],
+                                                                trait_ref: unbound },
+                                                 TraitBoundModifier::Maybe));
+            bounds = OwnedSlice::from_vec(bounds_as_vec);
+        };
 
         let default = if self.check(&token::Eq) {
             self.bump();
@@ -4118,7 +4151,6 @@ impl<'a> Parser<'a> {
             ident: ident,
             id: ast::DUMMY_NODE_ID,
             bounds: bounds,
-            unbound: unbound,
             default: default,
             span: span,
         }
@@ -4260,7 +4292,7 @@ impl<'a> Parser<'a> {
                     let bounded_ty = self.parse_ty();
 
                     if self.eat(&token::Colon) {
-                        let bounds = self.parse_ty_param_bounds();
+                        let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare);
                         let hi = self.span.hi;
                         let span = mk_sp(lo, hi);
 
@@ -4747,15 +4779,23 @@ impl<'a> Parser<'a> {
     fn parse_item_trait(&mut self, unsafety: Unsafety) -> ItemInfo {
         let ident = self.parse_ident();
         let mut tps = self.parse_generics();
-        let sized = self.parse_for_sized();
+        let unbound = self.parse_for_sized();
 
         // Parse supertrait bounds.
-        let bounds = self.parse_colon_then_ty_param_bounds();
+        let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
+
+        if let Some(unbound) = unbound {
+            let mut bounds_as_vec = bounds.into_vec();
+            bounds_as_vec.push(TraitTyParamBound(PolyTraitRef { bound_lifetimes: vec![],
+                                                                trait_ref: unbound },
+                                                 TraitBoundModifier::Maybe));
+            bounds = OwnedSlice::from_vec(bounds_as_vec);
+        };
 
         self.parse_where_clause(&mut tps);
 
         let meths = self.parse_trait_items();
-        (ident, ItemTrait(unsafety, tps, sized, bounds, meths), None)
+        (ident, ItemTrait(unsafety, tps, bounds, meths), None)
     }
 
     fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
@@ -4974,12 +5014,25 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_for_sized(&mut self) -> Option<ast::TraitRef> {
+        // FIXME, this should really use TraitBoundModifier, but it will get
+        // re-jigged shortly in any case, so leaving the hacky version for now.
         if self.eat_keyword(keywords::For) {
             let span = self.span;
+            let mut ate_question = false;
+            if self.eat(&token::Question) {
+                ate_question = true;
+            }
             let ident = self.parse_ident();
-            if !self.eat(&token::Question) {
+            if self.eat(&token::Question) {
+                if ate_question {
+                    self.span_err(span,
+                        "unexpected `?`");
+                }
+                ate_question = true;
+            }
+            if !ate_question {
                 self.span_err(span,
-                    "expected 'Sized?' after `for` in trait item");
+                    "expected `?Sized` after `for` in trait item");
                 return None;
             }
             let tref = Parser::trait_ref_from_ident(ident, span);
@@ -5924,7 +5977,7 @@ impl<'a> Parser<'a> {
     }
 
 
-    /// Matches view_path : MOD? IDENT EQ non_global_path
+    /// Matches view_path : MOD? non_global_path as IDENT
     /// | MOD? non_global_path MOD_SEP LBRACE RBRACE
     /// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
     /// | MOD? non_global_path MOD_SEP STAR
@@ -6036,7 +6089,7 @@ impl<'a> Parser<'a> {
         }
         let mut rename_to = path[path.len() - 1u];
         let path = ast::Path {
-            span: mk_sp(lo, self.span.hi),
+            span: mk_sp(lo, self.last_span.hi),
             global: false,
             segments: path.into_iter().map(|identifier| {
                 ast::PathSegment {
@@ -6048,7 +6101,8 @@ impl<'a> Parser<'a> {
         if self.eat_keyword(keywords::As) {
             rename_to = self.parse_ident()
         }
-        P(spanned(lo, self.last_span.hi,
+        P(spanned(lo,
+                  self.last_span.hi,
                   ViewPathSimple(rename_to, path, ast::DUMMY_NODE_ID)))
     }
 
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index f575d3d6c67..f22a4b5c6ed 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -724,7 +724,7 @@ pub fn fresh_name(src: &ast::Ident) -> ast::Name {
     // following: debug version. Could work in final except that it's incompatible with
     // good error messages and uses of struct names in ambiguous could-be-binding
     // locations. Also definitely destroys the guarantee given above about ptr_eq.
-    /*let num = rand::task_rng().gen_uint_range(0,0xffff);
+    /*let num = rand::thread_rng().gen_uint_range(0,0xffff);
     gensym(format!("{}_{}",ident_to_string(src),num))*/
 }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index accffbc35ba..02a03285d3b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -13,7 +13,7 @@ pub use self::AnnNode::*;
 use abi;
 use ast::{mod, FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
-use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound};
+use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem};
 use ast::{UnboxedClosureKind};
 use ast_util;
@@ -958,20 +958,25 @@ impl<'a> State<'a> {
                 }
                 try!(self.bclose(item.span));
             }
-            ast::ItemTrait(unsafety, ref generics, ref unbound, ref bounds, ref methods) => {
+            ast::ItemTrait(unsafety, ref generics, ref bounds, ref methods) => {
                 try!(self.head(""));
                 try!(self.print_visibility(item.vis));
                 try!(self.print_unsafety(unsafety));
                 try!(self.word_nbsp("trait"));
                 try!(self.print_ident(item.ident));
                 try!(self.print_generics(generics));
-                if let &Some(ref tref) = unbound {
-                    try!(space(&mut self.s));
-                    try!(self.word_space("for"));
-                    try!(self.print_trait_ref(tref));
-                    try!(word(&mut self.s, "?"));
+                let bounds: Vec<_> = bounds.iter().map(|b| b.clone()).collect();
+                let mut real_bounds = Vec::with_capacity(bounds.len());
+                for b in bounds.into_iter() {
+                    if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = b {
+                        try!(space(&mut self.s));
+                        try!(self.word_space("for ?"));
+                        try!(self.print_trait_ref(&ptr.trait_ref));
+                    } else {
+                        real_bounds.push(b);
+                    }
                 }
-                try!(self.print_bounds(":", bounds[]));
+                try!(self.print_bounds(":", real_bounds[]));
                 try!(self.print_where_clause(generics));
                 try!(word(&mut self.s, " "));
                 try!(self.bopen());
@@ -2345,7 +2350,11 @@ impl<'a> State<'a> {
                 }
 
                 try!(match *bound {
-                    TraitTyParamBound(ref tref) => {
+                    TraitTyParamBound(ref tref, TraitBoundModifier::None) => {
+                        self.print_poly_trait_ref(tref)
+                    }
+                    TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => {
+                        try!(word(&mut self.s, "?"));
                         self.print_poly_trait_ref(tref)
                     }
                     RegionTyParamBound(ref lt) => {
@@ -2412,10 +2421,6 @@ impl<'a> State<'a> {
     }
 
     pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
-        if let Some(ref tref) = param.unbound {
-            try!(self.print_trait_ref(tref));
-            try!(self.word_space("?"));
-        }
         try!(self.print_ident(param.ident));
         try!(self.print_bounds(":", param.bounds[]));
         match param.default {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 22cfea86251..1cd21ccac7a 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -85,8 +85,8 @@ pub trait Visitor<'v> {
     fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
         walk_ty_param_bound(self, bounds)
     }
-    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef) {
-        walk_poly_trait_ref(self, t)
+    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
+        walk_poly_trait_ref(self, t, m)
     }
     fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
         walk_struct_def(self, s)
@@ -244,7 +244,8 @@ pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
 /// Like with walk_method_helper this doesn't correspond to a method
 /// in Visitor, and so it gets a _helper suffix.
 pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
-                                         trait_ref: &'v PolyTraitRef)
+                                  trait_ref: &'v PolyTraitRef,
+                                  _modifier: &'v TraitBoundModifier)
     where V: Visitor<'v>
 {
     walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
@@ -324,7 +325,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
                                      generics,
                                      item.id)
         }
-        ItemTrait(_, ref generics, _, ref bounds, ref methods) => {
+        ItemTrait(_, ref generics, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
             walk_ty_param_bounds_helper(visitor, bounds);
             for method in methods.iter() {
@@ -558,8 +559,8 @@ pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
                                                bound: &'v TyParamBound) {
     match *bound {
-        TraitTyParamBound(ref typ) => {
-            visitor.visit_poly_trait_ref(typ);
+        TraitTyParamBound(ref typ, ref modifier) => {
+            visitor.visit_poly_trait_ref(typ, modifier);
         }
         RegionTyParamBound(ref lifetime) => {
             visitor.visit_lifetime_bound(lifetime);