diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 3edcd0b515641..35c29f646e4a0 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1782,9 +1782,9 @@ impl LintPass for Stability { if self.is_internal(cx, item.span) { return } match item.node { - ast::ItemTrait(_, _, _, ref supertraits, _) => { + ast::ItemTrait(_, _, ref supertraits, _) => { for t in supertraits.iter() { - if let ast::TraitTyParamBound(ref t) = *t { + if let ast::TraitTyParamBound(ref t, _) = *t { let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref); self.lint(cx, id, t.trait_ref.path.span); } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 6782b3a74813e..2a670b308b6b2 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1308,7 +1308,7 @@ fn encode_info_for_item(ecx: &EncodeContext, } } } - ast::ItemTrait(_, _, _, _, ref ms) => { + ast::ItemTrait(_, _, _, ref ms) => { add_to_index(item, rbml_w, index); rbml_w.start_tag(tag_items_data_item); encode_def_id(rbml_w, def_id); diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 2f62858071f6a..3d3eac7b6ed9f 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1043,7 +1043,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { ident: ty_param.ident, id: ty_param.id, bounds: bounds, - unbound: ty_param.unbound.clone(), default: ty_param.default.clone(), span: ty_param.span, } @@ -1063,7 +1062,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { // be passing down a map. ast::RegionTyParamBound(lt) } - &ast::TraitTyParamBound(ref poly_tr) => { + &ast::TraitTyParamBound(ref poly_tr, modifier) => { let tr = &poly_tr.trait_ref; let last_seg = tr.path.segments.last().unwrap(); let mut insert = Vec::new(); @@ -1087,7 +1086,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { path: new_path, ref_id: tr.ref_id, } - }) + }, modifier) } } }) diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 6f63ae166fe41..730da26eda3dc 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -122,7 +122,7 @@ impl<'v> Visitor<'v> for ParentVisitor { // method to the root. In this case, if the trait is private, then // parent all the methods to the trait to indicate that they're // private. - ast::ItemTrait(_, _, _, _, ref methods) if item.vis != ast::Public => { + ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => { for m in methods.iter() { match *m { ast::ProvidedMethod(ref m) => { @@ -328,7 +328,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // Default methods on traits are all public so long as the trait // is public - ast::ItemTrait(_, _, _, _, ref methods) if public_first => { + ast::ItemTrait(_, _, _, ref methods) if public_first => { for method in methods.iter() { match *method { ast::ProvidedMethod(ref m) => { @@ -1178,7 +1178,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } - ast::ItemTrait(_, _, _, _, ref methods) => { + ast::ItemTrait(_, _, _, ref methods) => { for m in methods.iter() { match *m { ast::ProvidedMethod(ref m) => { @@ -1242,7 +1242,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { ast::ItemStruct(ref def, _) => check_struct(&**def), - ast::ItemTrait(_, _, _, _, ref methods) => { + ast::ItemTrait(_, _, _, ref methods) => { for m in methods.iter() { match *m { ast::RequiredMethod(..) => {} @@ -1306,7 +1306,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { fn check_ty_param_bound(&self, ty_param_bound: &ast::TyParamBound) { - if let ast::TraitTyParamBound(ref trait_ref) = *ty_param_bound { + if let ast::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound { if !self.tcx.sess.features.borrow().visible_private_types && self.path_is_private_type(trait_ref.trait_ref.ref_id) { let span = trait_ref.trait_ref.path.span; @@ -1349,7 +1349,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // namespace (the contents have their own privacies). ast::ItemForeignMod(_) => {} - ast::ItemTrait(_, _, _, ref bounds, _) => { + ast::ItemTrait(_, _, ref bounds, _) => { if !self.trait_is_public(item.id) { return } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 22dea3be1d4b6..4feafff3b9211 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -105,7 +105,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { ast::ItemTy(_, ref generics) | ast::ItemEnum(_, ref generics) | ast::ItemStruct(_, ref generics) | - ast::ItemTrait(_, ref generics, _, _, _) | + ast::ItemTrait(_, ref generics, _, _) | ast::ItemImpl(_, ref generics, _, _, _) => { // These kinds of items have only early bound lifetime parameters. let lifetimes = &generics.lifetimes; @@ -232,7 +232,9 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } } - fn visit_poly_trait_ref(&mut self, trait_ref: &ast::PolyTraitRef) { + fn visit_poly_trait_ref(&mut self, trait_ref: + &ast::PolyTraitRef, + _modifier: &ast::TraitBoundModifier) { debug!("visit_poly_trait_ref trait_ref={}", trait_ref); self.with(LateScope(&trait_ref.bound_lifetimes, self.scope), |old_scope, this| { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 232646f64a7d1..617be82701a09 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4740,7 +4740,7 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) match cx.map.find(id.node) { Some(ast_map::NodeItem(item)) => { match item.node { - ItemTrait(_, _, _, _, ref ms) => { + ItemTrait(_, _, _, ref ms) => { let (_, p) = ast_util::split_trait_methods(ms[]); p.iter() diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c168709eec5b9..8e3eb4bf853bb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1493,7 +1493,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ItemImpl(_, _, Some(_), _, _) => parent, - ItemTrait(_, _, _, _, ref items) => { + ItemTrait(_, _, _, ref items) => { let name_bindings = self.add_child(name, parent.clone(), @@ -4093,7 +4093,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { impl_items[]); } - ItemTrait(_, ref generics, ref unbound, ref bounds, ref trait_items) => { + ItemTrait(_, ref generics, ref bounds, ref trait_items) => { // Create a new rib for the self type. let mut self_type_rib = Rib::new(ItemRibKind); @@ -4114,13 +4114,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { this.resolve_type_parameter_bounds(item.id, bounds, TraitDerivation); - match *unbound { - Some(ref tpb) => { - this.resolve_trait_reference(item.id, tpb, TraitDerivation); - } - None => {} - } - for trait_item in (*trait_items).iter() { // Create a new rib for the trait_item-specific type // parameters. @@ -4368,12 +4361,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_type_parameter_bound(type_parameter.id, bound, TraitBoundingTypeParameter); } - match &type_parameter.unbound { - &Some(ref unbound) => - self.resolve_trait_reference( - type_parameter.id, unbound, TraitBoundingTypeParameter), - &None => {} - } match type_parameter.default { Some(ref ty) => self.resolve_type(&**ty), None => {} @@ -4395,7 +4382,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { type_parameter_bound: &TyParamBound, reference_type: TraitReferenceType) { match *type_parameter_bound { - TraitTyParamBound(ref tref) => { + TraitTyParamBound(ref tref, _) => { self.resolve_poly_trait_reference(id, tref, reference_type) } RegionTyParamBound(..) => {} diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index f491bc84b62c4..08f5dee717a9c 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -710,7 +710,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { // super-traits for super_bound in trait_refs.iter() { let trait_ref = match *super_bound { - ast::TraitTyParamBound(ref trait_ref) => { + ast::TraitTyParamBound(ref trait_ref, _) => { trait_ref } ast::RegionTyParamBound(..) => { @@ -1052,7 +1052,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { &**typ, impl_items) } - ast::ItemTrait(_, ref generics, _, ref trait_refs, ref methods) => + ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) => self.process_trait(item, generics, trait_refs, methods), ast::ItemMod(ref m) => self.process_mod(item, m), ast::ItemTy(ref ty, ref ty_params) => { @@ -1076,7 +1076,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { fn visit_generics(&mut self, generics: &ast::Generics) { for param in generics.ty_params.iter() { for bound in param.bounds.iter() { - if let ast::TraitTyParamBound(ref trait_ref) = *bound { + if let ast::TraitTyParamBound(ref trait_ref, _) = *bound { self.process_trait_ref(&trait_ref.trait_ref, None); } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 81e6ec4df5627..c8a084584b5e2 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1626,7 +1626,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, let mut trait_def_ids = DefIdMap::new(); for ast_bound in ast_bounds.iter() { match *ast_bound { - ast::TraitTyParamBound(ref b) => { + ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => { match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { def::DefTrait(trait_did) => { match trait_def_ids.get(&trait_did) { @@ -1664,6 +1664,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, } trait_bounds.push(b); } + ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {} ast::RegionTyParamBound(ref l) => { region_bounds.push(l); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fb23ad8e340ce..c8c8211f29253 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -673,7 +673,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { } } - ast::ItemTrait(_, _, _, _, ref trait_methods) => { + ast::ItemTrait(_, _, _, ref trait_methods) => { let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); for trait_method in trait_methods.iter() { match *trait_method { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 793c5f5b4a058..8d07f1e435503 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -259,7 +259,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_def: &ty::TraitDef<'tcx>) { let tcx = ccx.tcx; if let ast_map::NodeItem(item) = tcx.map.get(trait_id) { - if let ast::ItemTrait(_, _, _, _, ref trait_items) = item.node { + if let ast::ItemTrait(_, _, _, ref trait_items) = item.node { // For each method, construct a suitable ty::Method and // store it into the `tcx.impl_or_trait_items` table: for trait_item in trait_items.iter() { @@ -627,11 +627,6 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, ast::RegionTyParamBound(..) => { } } } - - match ty_param.unbound { - Some(_) => { warn = true; } - None => { } - } } if warn { @@ -1146,7 +1141,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { AllowEqConstraints::DontAllow); } }, - ast::ItemTrait(_, _, _, _, ref trait_methods) => { + ast::ItemTrait(_, _, _, ref trait_methods) => { let trait_def = trait_def_of_item(ccx, it); debug!("trait_def: ident={} trait_def={}", @@ -1338,13 +1333,12 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return def.clone(); } - let (unsafety, generics, unbound, bounds, items) = match it.node { + let (unsafety, generics, bounds, items) = match it.node { ast::ItemTrait(unsafety, ref generics, - ref unbound, ref supertraits, ref items) => { - (unsafety, generics, unbound, supertraits, items.as_slice()) + (unsafety, generics, supertraits, items.as_slice()) } ref s => { tcx.sess.span_bug( @@ -1367,7 +1361,6 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, token::SELF_KEYWORD_NAME, self_param_ty, bounds.as_slice(), - unbound, it.span); let substs = mk_item_substs(ccx, &ty_generics); @@ -1683,29 +1676,37 @@ fn ty_generics_for_fn_or_method<'tcx,AC>( create_type_parameters_for_associated_types) } -// Add the Sized bound, unless the type parameter is marked as `Sized?`. +// Add the Sized bound, unless the type parameter is marked as `?Sized`. fn add_unsized_bound<'tcx,AC>(this: &AC, - unbound: &Option, bounds: &mut ty::BuiltinBounds, - desc: &str, + ast_bounds: &[ast::TyParamBound], span: Span) where AC: AstConv<'tcx> { + // Try to find an unbound in bounds. + let mut unbound = None; + for ab in ast_bounds.iter() { + if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab { + if unbound.is_none() { + assert!(ptr.bound_lifetimes.is_empty()); + unbound = Some(ptr.trait_ref.clone()); + } else { + this.tcx().sess.span_err(span, "type parameter has more than one relaxed default \ + bound, only one is supported"); + } + } + } + let kind_id = this.tcx().lang_items.require(SizedTraitLangItem); match unbound { - &Some(ref tpb) => { + Some(ref tpb) => { // FIXME(#8559) currently requires the unbound to be built-in. let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb); match kind_id { Ok(kind_id) if trait_def_id != kind_id => { this.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)[]); + "default bound relaxed for a type parameter, but \ + this does nothing because the given bound is not \ + a default. Only `?Sized` is supported"); ty::try_add_builtin_trait(this.tcx(), kind_id, bounds); @@ -1717,7 +1718,7 @@ fn add_unsized_bound<'tcx,AC>(this: &AC, ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds); } // No lang item for Sized, so we can't add it as a bound. - &None => {} + None => {} } } @@ -1807,7 +1808,7 @@ fn ty_generics<'tcx,AC>(this: &AC, for bound in bound_pred.bounds.iter() { match bound { - &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref) => { + &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => { let trait_ref = astconv::instantiate_poly_trait_ref( this, &ExplicitRscope, @@ -1880,7 +1881,7 @@ fn ty_generics<'tcx,AC>(this: &AC, for bound in param.bounds.iter() { // In the above example, `ast_trait_ref` is `Iterator`. let ast_trait_ref = match *bound { - ast::TraitTyParamBound(ref r) => r, + ast::TraitTyParamBound(ref r, _) => r, ast::RegionTyParamBound(..) => { continue; } }; @@ -1978,7 +1979,6 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, param.ident.name, param_ty, param.bounds[], - ¶m.unbound, param.span); let default = match param.default { None => None, @@ -2023,7 +2023,6 @@ fn compute_bounds<'tcx,AC>(this: &AC, name_of_bounded_thing: ast::Name, param_ty: ty::ParamTy, ast_bounds: &[ast::TyParamBound], - unbound: &Option, span: Span) -> ty::ParamBounds<'tcx> where AC: AstConv<'tcx> { @@ -2032,11 +2031,9 @@ fn compute_bounds<'tcx,AC>(this: &AC, param_ty, ast_bounds); - add_unsized_bound(this, - unbound, &mut param_bounds.builtin_bounds, - "type parameter", + ast_bounds, span); check_bounds_compatible(this.tcx(), diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index bdd8c7c3da7c0..30869186ba5e9 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -353,7 +353,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { match item.node { ast::ItemEnum(_, ref generics) | ast::ItemStruct(_, ref generics) | - ast::ItemTrait(_, ref generics, _, _, _) => { + ast::ItemTrait(_, ref generics, _, _) => { for (i, p) in generics.lifetimes.iter().enumerate() { let id = p.lifetime.id; self.add_inferred(item.id, RegionParam, TypeSpace, i, id); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cdc51bb801c58..3eda39f54a997 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -163,13 +163,12 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, } }); let trait_def = ty::lookup_trait_def(tcx, did); - let (bounds, default_unbound) = trait_def.bounds.clean(cx); + let bounds = trait_def.bounds.clean(cx); clean::Trait { unsafety: def.unsafety, generics: (&def.generics, subst::TypeSpace).clean(cx), items: items.collect(), bounds: bounds, - default_unbound: default_unbound } } @@ -328,7 +327,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt, derived: clean::detect_derived(attrs.as_slice()), trait_: associated_trait.clean(cx).map(|bound| { match bound { - clean::TraitBound(polyt) => polyt.trait_, + clean::TraitBound(polyt, _) => polyt.trait_, clean::RegionBound(..) => unreachable!(), } }), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0308194527e95..b7845f23be298 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -458,8 +458,6 @@ pub struct TyParam { pub did: ast::DefId, pub bounds: Vec, pub default: Option, - /// An optional default bound on the parameter which is unbound, like `Sized?` - pub default_unbound: Option } impl Clean for ast::TyParam { @@ -469,7 +467,6 @@ impl Clean for ast::TyParam { did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id }, bounds: self.bounds.clean(cx), default: self.default.clean(cx), - default_unbound: self.unbound.clean(cx) } } } @@ -478,13 +475,12 @@ impl<'tcx> Clean for ty::TypeParameterDef<'tcx> { fn clean(&self, cx: &DocContext) -> TyParam { cx.external_typarams.borrow_mut().as_mut().unwrap() .insert(self.def_id, self.name.clean(cx)); - let (bounds, default_unbound) = self.bounds.clean(cx); + let bounds = self.bounds.clean(cx); TyParam { name: self.name.clean(cx), did: self.def_id, bounds: bounds, default: self.default.clean(cx), - default_unbound: default_unbound } } } @@ -492,14 +488,14 @@ impl<'tcx> Clean for ty::TypeParameterDef<'tcx> { #[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)] pub enum TyParamBound { RegionBound(Lifetime), - TraitBound(PolyTrait) + TraitBound(PolyTrait, ast::TraitBoundModifier) } impl Clean for ast::TyParamBound { fn clean(&self, cx: &DocContext) -> TyParamBound { match *self { ast::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)), - ast::TraitTyParamBound(ref t) => TraitBound(t.clean(cx)), + ast::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier), } } } @@ -600,7 +596,7 @@ impl Clean for ty::BuiltinBound { did: did, }, lifetimes: vec![] - }) + }, ast::TraitBoundModifier::None) } } @@ -648,37 +644,20 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { TraitBound(PolyTrait { trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, }, lifetimes: late_bounds - }) + }, ast::TraitBoundModifier::None) } } -// Returns (bounds, default_unbound) -impl<'tcx> Clean<(Vec, Option)> for ty::ParamBounds<'tcx> { - fn clean(&self, cx: &DocContext) -> (Vec, Option) { +impl<'tcx> Clean> for ty::ParamBounds<'tcx> { + fn clean(&self, cx: &DocContext) -> Vec { let mut v = Vec::new(); - let mut has_sized_bound = false; - for b in self.builtin_bounds.iter() { - if b != ty::BoundSized { - v.push(b.clean(cx)); - } else { - has_sized_bound = true; - } - } for t in self.trait_bounds.iter() { v.push(t.clean(cx)); } for r in self.region_bounds.iter().filter_map(|r| r.clean(cx)) { v.push(RegionBound(r)); } - if has_sized_bound { - (v, None) - } else { - let ty = match ty::BoundSized.clean(cx) { - TraitBound(polyt) => polyt.trait_, - _ => unreachable!() - }; - (v, Some(ty)) - } + v } } @@ -689,7 +668,7 @@ impl<'tcx> Clean>> for subst::Substs<'tcx> { v.extend(self.types.iter().map(|t| TraitBound(PolyTrait { trait_: t.clean(cx), lifetimes: vec![] - }))); + }, ast::TraitBoundModifier::None))); if v.len() > 0 {Some(v)} else {None} } } @@ -1047,8 +1026,6 @@ pub struct Trait { pub items: Vec, pub generics: Generics, pub bounds: Vec, - /// An optional default bound not required for `Self`, like `Sized?` - pub default_unbound: Option } impl Clean for doctree::Trait { @@ -1065,7 +1042,6 @@ impl Clean for doctree::Trait { items: self.items.clean(cx), generics: self.generics.clean(cx), bounds: self.bounds.clean(cx), - default_unbound: self.default_unbound.clean(cx) }), } } @@ -2412,7 +2388,6 @@ impl Clean for ty::AssociatedType { }, bounds: vec![], default: None, - default_unbound: None }), visibility: None, def_id: self.def_id, diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 7f7c055062aaa..251ce5aefeb71 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -178,7 +178,6 @@ pub struct Trait { pub whence: Span, pub vis: ast::Visibility, pub stab: Option, - pub default_unbound: Option // FIXME(tomjakubowski) } pub struct Impl { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 25c4f4e01b620..f20a74f937b75 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -97,9 +97,6 @@ impl fmt::Show for clean::Generics { if i > 0 { try!(f.write(", ".as_bytes())) } - if let Some(ref unbound) = tp.default_unbound { - try!(write!(f, "{}? ", unbound)); - }; try!(f.write(tp.name.as_bytes())); if tp.bounds.len() > 0 { @@ -182,8 +179,12 @@ impl fmt::Show for clean::TyParamBound { clean::RegionBound(ref lt) => { write!(f, "{}", *lt) } - clean::TraitBound(ref ty) => { - write!(f, "{}", *ty) + clean::TraitBound(ref ty, modifier) => { + let modifier_str = match modifier { + ast::TraitBoundModifier::None => "", + ast::TraitBoundModifier::Maybe => "?", + }; + write!(f, "{}{}", modifier_str, *ty) } } } @@ -458,12 +459,15 @@ impl fmt::Show for clean::Type { for bound in decl.bounds.iter() { match *bound { clean::RegionBound(..) => {} - clean::TraitBound(ref t) => { + clean::TraitBound(ref t, modifier) => { if ret.len() == 0 { ret.push_str(": "); } else { ret.push_str(" + "); } + if modifier == ast::TraitBoundModifier::Maybe { + ret.push_str("?"); + } ret.push_str(format!("{}", *t).as_slice()); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 304dbe201e8fd..bfb03cb2589c2 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1679,9 +1679,6 @@ fn item_function(w: &mut fmt::Formatter, it: &clean::Item, fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, t: &clean::Trait) -> fmt::Result { let mut bounds = String::new(); - if let Some(ref ty) = t.default_unbound { - bounds.push_str(format!(" for {}?", ty).as_slice()); - } if t.bounds.len() > 0 { if bounds.len() > 0 { bounds.push(' '); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 4374ce5deef4e..e71711aa8d6e7 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -322,7 +322,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.constants.push(s); }, - ast::ItemTrait(unsafety, ref gen, ref def_ub, ref b, ref items) => { + ast::ItemTrait(unsafety, ref gen, ref b, ref items) => { let t = Trait { unsafety: unsafety, name: name, @@ -334,7 +334,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: item.span, vis: item.vis, stab: self.stability(item.id), - default_unbound: def_ub.clone() }; om.traits.push(t); }, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index debcbcd2154bd..f253943943dcc 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; #[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, pub default: Option>, pub span: Span } @@ -1488,7 +1495,7 @@ pub struct PolyTraitRef { pub bound_lifetimes: Vec, /// 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, // (optional) default bound not required for Self. - // Currently, only Sized makes sense here. TyParamBounds, Vec), ItemImpl(Unsafety, diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 9b42a8f754069..5a4f5731be50d 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 d2185a00876d2..94a3784291d0b 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -139,11 +139,11 @@ fn fold_item_underscore(cx: &mut Context, 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 77165168746b7..239af18890909 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, - unbound: Option, default: Option>) -> 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, - unbound: Option, default: Option>) -> 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 57dfbc0c6e8bc..3c8d74c14ee63 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -58,10 +58,10 @@ fn expand_deriving_decodable_imp(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 8bd3df6232ce5..5829f34bccc5d 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -134,10 +134,10 @@ fn expand_deriving_encodable_imp(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 cf0201294ae54..e4e31139d82f4 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 56d11c2377fa4..95bdd8b9ffd2f 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, - 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, ty_params: Vec) @@ -216,7 +220,7 @@ fn mk_generics(lifetimes: Vec, ty_params: Vec) #[deriving(Clone)] pub struct LifetimeBounds<'a> { pub lifetimes: Vec<(&'a str, Vec<&'a str>)>, - pub bounds: Vec<(&'a str, Option, Vec>)>, + pub bounds: Vec<(&'a str, Vec>)>, } 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 4e59124a1294f..72e3b45dc91b7 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -30,7 +30,7 @@ pub fn expand_deriving_hash(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 4f6e4d1fb3c10..1ddf5b2a5c31e 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -36,7 +36,6 @@ pub fn expand_deriving_rand(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 11a9fdee0b9b0..4f0169e31f229 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -736,18 +736,17 @@ pub fn noop_fold_ty_param_bound(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(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(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(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 2f43661eebeba..fd64511cc041a 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 { 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 { 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, Vec) { @@ -4974,12 +5014,25 @@ impl<'a> Parser<'a> { } fn parse_for_sized(&mut self) -> Option { + // 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); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index accffbc35babe..02a03285d3b86 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 22cfea862517e..1cd21ccac7a0e 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); diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs index 19af9fd7ea7b4..d3d2e3581aaf7 100644 --- a/src/test/run-pass/dst-raw.rs +++ b/src/test/run-pass/dst-raw.rs @@ -23,7 +23,7 @@ impl Trait for A { } } -struct Foo { +struct Foo { f: T } diff --git a/src/test/run-pass/dst-struct-sole.rs b/src/test/run-pass/dst-struct-sole.rs index 26cb27cc65392..47547bb7e5a27 100644 --- a/src/test/run-pass/dst-struct-sole.rs +++ b/src/test/run-pass/dst-struct-sole.rs @@ -10,7 +10,7 @@ // As dst-struct.rs, but the unsized field is the only field in the struct. -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/run-pass/dst-struct.rs b/src/test/run-pass/dst-struct.rs index 3644ca81d5659..fb536904ac80f 100644 --- a/src/test/run-pass/dst-struct.rs +++ b/src/test/run-pass/dst-struct.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T diff --git a/src/test/run-pass/dst-trait.rs b/src/test/run-pass/dst-trait.rs index 907c7810736ba..abe55d78ac69a 100644 --- a/src/test/run-pass/dst-trait.rs +++ b/src/test/run-pass/dst-trait.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T diff --git a/src/test/run-pass/issue-15155.rs b/src/test/run-pass/issue-15155.rs index 053a4916e229a..3a63e63355cd0 100644 --- a/src/test/run-pass/issue-15155.rs +++ b/src/test/run-pass/issue-15155.rs @@ -22,7 +22,7 @@ struct IndirectBlah { x: Box } impl TraitWithSend for IndirectBlah {} impl IndirectTraitWithSend for IndirectBlah {} -fn test_trait() { println!("got here!") } +fn test_trait() { println!("got here!") } fn main() { test_trait::(); diff --git a/src/test/run-pass/issue-17361.rs b/src/test/run-pass/issue-17361.rs index fa38dcc198673..092bcf661a76a 100644 --- a/src/test/run-pass/issue-17361.rs +++ b/src/test/run-pass/issue-17361.rs @@ -11,6 +11,6 @@ // Test that astconv doesn't forget about mutability of &mut str fn main() { - fn foo(_: &mut T) {} + fn foo(_: &mut T) {} let _f: fn(&mut str) = foo; } diff --git a/src/test/run-pass/method-recursive-blanket-impl.rs b/src/test/run-pass/method-recursive-blanket-impl.rs index b45faca2de602..4e4fb75b428cc 100644 --- a/src/test/run-pass/method-recursive-blanket-impl.rs +++ b/src/test/run-pass/method-recursive-blanket-impl.rs @@ -16,7 +16,7 @@ use std::kinds::Sized; // Note: this must be generic for the problem to show up -trait Foo for Sized? { +trait Foo for ?Sized { fn foo(&self); } diff --git a/src/test/run-pass/unsized.rs b/src/test/run-pass/unsized.rs index 141d6c88dd961..07b9fac66554e 100644 --- a/src/test/run-pass/unsized.rs +++ b/src/test/run-pass/unsized.rs @@ -10,21 +10,22 @@ // // ignore-lexer-test FIXME #15879 -// Test syntax checks for `Sized?` syntax. +// Test syntax checks for `?Sized` syntax. -trait T1 for Sized? {} -pub trait T2 for Sized? {} -trait T3 for Sized?: T2 {} -trait T4 {} -trait T5 {} -trait T6 {} -trait T7 {} -trait T8 {} -struct S1; -enum E {} -impl T1 for S1 {} -fn f() {} -type TT = T; +trait T1 for ?Sized {} +pub trait T2 for ?Sized {} +trait T3 for ?Sized: T2 {} +trait T4 {} +trait T5 {} +trait T6 {} +trait T7 {} +trait T8 {} +trait T9 {} +struct S1; +enum E {} +impl T1 for S1 {} +fn f() {} +type TT = T; pub fn main() { } diff --git a/src/test/run-pass/unsized2.rs b/src/test/run-pass/unsized2.rs index d28d47c0cfb85..8d2c99d4414c9 100644 --- a/src/test/run-pass/unsized2.rs +++ b/src/test/run-pass/unsized2.rs @@ -13,7 +13,7 @@ // Test sized-ness checking in substitution. // Unbounded. -fn f1(x: &X) { +fn f1(x: &X) { f1::(x); } fn f2(x: &X) { @@ -22,8 +22,8 @@ fn f2(x: &X) { } // Bounded. -trait T for Sized? {} -fn f3(x: &X) { +trait T for ?Sized {} +fn f3(x: &X) { f3::(x); } fn f4(x: &X) { @@ -32,7 +32,7 @@ fn f4(x: &X) { } // Self type. -trait T2 for Sized? { +trait T2 for ?Sized { fn f() -> Box; } struct S; @@ -41,14 +41,14 @@ impl T2 for S { box S } } -fn f5(x: &X) { +fn f5(x: &X) { let _: Box = T2::f(); } fn f6(x: &X) { let _: Box = T2::f(); } -trait T3 for Sized? { +trait T3 for ?Sized { fn f() -> Box; } impl T3 for S { @@ -56,7 +56,7 @@ impl T3 for S { box S } } -fn f7(x: &X) { +fn f7(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 = T3::f(); @@ -66,7 +66,7 @@ trait T4 { fn m1(x: &T4); fn m2(x: &T5); } -trait T5 { +trait T5 { // not an error (for now) fn m1(x: &T4); fn m2(x: &T5); @@ -76,21 +76,21 @@ trait T6 { fn m1(x: &T4); fn m2(x: &T5); } -trait T7 { +trait T7 { // not an error (for now) fn m1(x: &T4); fn m2(x: &T5); } // The last field in a struct or variant may be unsized -struct S2 { +struct S2 { f: X, } -struct S3 { +struct S3 { f1: int, f2: X, } -enum E { +enum E { V1(X), V2{x: X}, V3(int, X),