1
Fork 0

rollup merge of #20194: nick29581/dst-syntax

Part of #19607.

r? @nikomatsakis
This commit is contained in:
Alex Crichton 2014-12-29 16:35:59 -08:00
commit 2a8547783f
41 changed files with 242 additions and 222 deletions

View file

@ -1782,9 +1782,9 @@ impl LintPass for Stability {
if self.is_internal(cx, item.span) { return } if self.is_internal(cx, item.span) { return }
match item.node { match item.node {
ast::ItemTrait(_, _, _, ref supertraits, _) => { ast::ItemTrait(_, _, ref supertraits, _) => {
for t in supertraits.iter() { 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); let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref);
self.lint(cx, id, t.trait_ref.path.span); self.lint(cx, id, t.trait_ref.path.span);
} }

View file

@ -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); add_to_index(item, rbml_w, index);
rbml_w.start_tag(tag_items_data_item); rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id); encode_def_id(rbml_w, def_id);

View file

@ -1043,7 +1043,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
ident: ty_param.ident, ident: ty_param.ident,
id: ty_param.id, id: ty_param.id,
bounds: bounds, bounds: bounds,
unbound: ty_param.unbound.clone(),
default: ty_param.default.clone(), default: ty_param.default.clone(),
span: ty_param.span, span: ty_param.span,
} }
@ -1063,7 +1062,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
// be passing down a map. // be passing down a map.
ast::RegionTyParamBound(lt) ast::RegionTyParamBound(lt)
} }
&ast::TraitTyParamBound(ref poly_tr) => { &ast::TraitTyParamBound(ref poly_tr, modifier) => {
let tr = &poly_tr.trait_ref; let tr = &poly_tr.trait_ref;
let last_seg = tr.path.segments.last().unwrap(); let last_seg = tr.path.segments.last().unwrap();
let mut insert = Vec::new(); let mut insert = Vec::new();
@ -1087,7 +1086,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
path: new_path, path: new_path,
ref_id: tr.ref_id, ref_id: tr.ref_id,
} }
}) }, modifier)
} }
} }
}) })

View file

@ -122,7 +122,7 @@ impl<'v> Visitor<'v> for ParentVisitor {
// method to the root. In this case, if the trait is private, then // 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 // parent all the methods to the trait to indicate that they're
// private. // private.
ast::ItemTrait(_, _, _, _, ref methods) if item.vis != ast::Public => { ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
for m in methods.iter() { for m in methods.iter() {
match *m { match *m {
ast::ProvidedMethod(ref 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 // Default methods on traits are all public so long as the trait
// is public // is public
ast::ItemTrait(_, _, _, _, ref methods) if public_first => { ast::ItemTrait(_, _, _, ref methods) if public_first => {
for method in methods.iter() { for method in methods.iter() {
match *method { match *method {
ast::ProvidedMethod(ref m) => { 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() { for m in methods.iter() {
match *m { match *m {
ast::ProvidedMethod(ref m) => { ast::ProvidedMethod(ref m) => {
@ -1242,7 +1242,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
ast::ItemStruct(ref def, _) => check_struct(&**def), ast::ItemStruct(ref def, _) => check_struct(&**def),
ast::ItemTrait(_, _, _, _, ref methods) => { ast::ItemTrait(_, _, _, ref methods) => {
for m in methods.iter() { for m in methods.iter() {
match *m { match *m {
ast::RequiredMethod(..) => {} ast::RequiredMethod(..) => {}
@ -1306,7 +1306,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
fn check_ty_param_bound(&self, fn check_ty_param_bound(&self,
ty_param_bound: &ast::TyParamBound) { 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 && if !self.tcx.sess.features.borrow().visible_private_types &&
self.path_is_private_type(trait_ref.trait_ref.ref_id) { self.path_is_private_type(trait_ref.trait_ref.ref_id) {
let span = trait_ref.trait_ref.path.span; 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). // namespace (the contents have their own privacies).
ast::ItemForeignMod(_) => {} ast::ItemForeignMod(_) => {}
ast::ItemTrait(_, _, _, ref bounds, _) => { ast::ItemTrait(_, _, ref bounds, _) => {
if !self.trait_is_public(item.id) { if !self.trait_is_public(item.id) {
return return
} }

View file

@ -105,7 +105,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
ast::ItemTy(_, ref generics) | ast::ItemTy(_, ref generics) |
ast::ItemEnum(_, ref generics) | ast::ItemEnum(_, ref generics) |
ast::ItemStruct(_, ref generics) | ast::ItemStruct(_, ref generics) |
ast::ItemTrait(_, ref generics, _, _, _) | ast::ItemTrait(_, ref generics, _, _) |
ast::ItemImpl(_, ref generics, _, _, _) => { ast::ItemImpl(_, ref generics, _, _, _) => {
// These kinds of items have only early bound lifetime parameters. // These kinds of items have only early bound lifetime parameters.
let lifetimes = &generics.lifetimes; 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); debug!("visit_poly_trait_ref trait_ref={}", trait_ref);
self.with(LateScope(&trait_ref.bound_lifetimes, self.scope), |old_scope, this| { self.with(LateScope(&trait_ref.bound_lifetimes, self.scope), |old_scope, this| {

View file

@ -4740,7 +4740,7 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
match cx.map.find(id.node) { match cx.map.find(id.node) {
Some(ast_map::NodeItem(item)) => { Some(ast_map::NodeItem(item)) => {
match item.node { match item.node {
ItemTrait(_, _, _, _, ref ms) => { ItemTrait(_, _, _, ref ms) => {
let (_, p) = let (_, p) =
ast_util::split_trait_methods(ms[]); ast_util::split_trait_methods(ms[]);
p.iter() p.iter()

View file

@ -1493,7 +1493,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ItemImpl(_, _, Some(_), _, _) => parent, ItemImpl(_, _, Some(_), _, _) => parent,
ItemTrait(_, _, _, _, ref items) => { ItemTrait(_, _, _, ref items) => {
let name_bindings = let name_bindings =
self.add_child(name, self.add_child(name,
parent.clone(), parent.clone(),
@ -4093,7 +4093,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
impl_items[]); 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. // Create a new rib for the self type.
let mut self_type_rib = Rib::new(ItemRibKind); 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, this.resolve_type_parameter_bounds(item.id, bounds,
TraitDerivation); TraitDerivation);
match *unbound {
Some(ref tpb) => {
this.resolve_trait_reference(item.id, tpb, TraitDerivation);
}
None => {}
}
for trait_item in (*trait_items).iter() { for trait_item in (*trait_items).iter() {
// Create a new rib for the trait_item-specific type // Create a new rib for the trait_item-specific type
// parameters. // parameters.
@ -4368,12 +4361,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.resolve_type_parameter_bound(type_parameter.id, bound, self.resolve_type_parameter_bound(type_parameter.id, bound,
TraitBoundingTypeParameter); TraitBoundingTypeParameter);
} }
match &type_parameter.unbound {
&Some(ref unbound) =>
self.resolve_trait_reference(
type_parameter.id, unbound, TraitBoundingTypeParameter),
&None => {}
}
match type_parameter.default { match type_parameter.default {
Some(ref ty) => self.resolve_type(&**ty), Some(ref ty) => self.resolve_type(&**ty),
None => {} None => {}
@ -4395,7 +4382,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
type_parameter_bound: &TyParamBound, type_parameter_bound: &TyParamBound,
reference_type: TraitReferenceType) { reference_type: TraitReferenceType) {
match *type_parameter_bound { match *type_parameter_bound {
TraitTyParamBound(ref tref) => { TraitTyParamBound(ref tref, _) => {
self.resolve_poly_trait_reference(id, tref, reference_type) self.resolve_poly_trait_reference(id, tref, reference_type)
} }
RegionTyParamBound(..) => {} RegionTyParamBound(..) => {}

View file

@ -710,7 +710,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
// super-traits // super-traits
for super_bound in trait_refs.iter() { for super_bound in trait_refs.iter() {
let trait_ref = match *super_bound { let trait_ref = match *super_bound {
ast::TraitTyParamBound(ref trait_ref) => { ast::TraitTyParamBound(ref trait_ref, _) => {
trait_ref trait_ref
} }
ast::RegionTyParamBound(..) => { ast::RegionTyParamBound(..) => {
@ -1052,7 +1052,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
&**typ, &**typ,
impl_items) 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), self.process_trait(item, generics, trait_refs, methods),
ast::ItemMod(ref m) => self.process_mod(item, m), ast::ItemMod(ref m) => self.process_mod(item, m),
ast::ItemTy(ref ty, ref ty_params) => { 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) { fn visit_generics(&mut self, generics: &ast::Generics) {
for param in generics.ty_params.iter() { for param in generics.ty_params.iter() {
for bound in param.bounds.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); self.process_trait_ref(&trait_ref.trait_ref, None);
} }
} }

View file

@ -1626,7 +1626,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
let mut trait_def_ids = DefIdMap::new(); let mut trait_def_ids = DefIdMap::new();
for ast_bound in ast_bounds.iter() { for ast_bound in ast_bounds.iter() {
match *ast_bound { 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) { match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
def::DefTrait(trait_did) => { def::DefTrait(trait_did) => {
match trait_def_ids.get(&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); trait_bounds.push(b);
} }
ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {}
ast::RegionTyParamBound(ref l) => { ast::RegionTyParamBound(ref l) => {
region_bounds.push(l); region_bounds.push(l);
} }

View file

@ -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)); let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
for trait_method in trait_methods.iter() { for trait_method in trait_methods.iter() {
match *trait_method { match *trait_method {

View file

@ -259,7 +259,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
trait_def: &ty::TraitDef<'tcx>) { trait_def: &ty::TraitDef<'tcx>) {
let tcx = ccx.tcx; let tcx = ccx.tcx;
if let ast_map::NodeItem(item) = tcx.map.get(trait_id) { 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 // For each method, construct a suitable ty::Method and
// store it into the `tcx.impl_or_trait_items` table: // store it into the `tcx.impl_or_trait_items` table:
for trait_item in trait_items.iter() { for trait_item in trait_items.iter() {
@ -627,11 +627,6 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
ast::RegionTyParamBound(..) => { } ast::RegionTyParamBound(..) => { }
} }
} }
match ty_param.unbound {
Some(_) => { warn = true; }
None => { }
}
} }
if warn { if warn {
@ -1146,7 +1141,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
AllowEqConstraints::DontAllow); AllowEqConstraints::DontAllow);
} }
}, },
ast::ItemTrait(_, _, _, _, ref trait_methods) => { ast::ItemTrait(_, _, _, ref trait_methods) => {
let trait_def = trait_def_of_item(ccx, it); let trait_def = trait_def_of_item(ccx, it);
debug!("trait_def: ident={} trait_def={}", 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(); return def.clone();
} }
let (unsafety, generics, unbound, bounds, items) = match it.node { let (unsafety, generics, bounds, items) = match it.node {
ast::ItemTrait(unsafety, ast::ItemTrait(unsafety,
ref generics, ref generics,
ref unbound,
ref supertraits, ref supertraits,
ref items) => { ref items) => {
(unsafety, generics, unbound, supertraits, items.as_slice()) (unsafety, generics, supertraits, items.as_slice())
} }
ref s => { ref s => {
tcx.sess.span_bug( tcx.sess.span_bug(
@ -1367,7 +1361,6 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
token::SELF_KEYWORD_NAME, token::SELF_KEYWORD_NAME,
self_param_ty, self_param_ty,
bounds.as_slice(), bounds.as_slice(),
unbound,
it.span); it.span);
let substs = mk_item_substs(ccx, &ty_generics); 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) 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, fn add_unsized_bound<'tcx,AC>(this: &AC,
unbound: &Option<ast::TraitRef>,
bounds: &mut ty::BuiltinBounds, bounds: &mut ty::BuiltinBounds,
desc: &str, ast_bounds: &[ast::TyParamBound],
span: Span) span: Span)
where AC: AstConv<'tcx> { 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); let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
match unbound { match unbound {
&Some(ref tpb) => { Some(ref tpb) => {
// FIXME(#8559) currently requires the unbound to be built-in. // FIXME(#8559) currently requires the unbound to be built-in.
let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb); let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
match kind_id { match kind_id {
Ok(kind_id) if trait_def_id != kind_id => { Ok(kind_id) if trait_def_id != kind_id => {
this.tcx().sess.span_warn(span, this.tcx().sess.span_warn(span,
format!("default bound relaxed \ "default bound relaxed for a type parameter, but \
for a {}, but this \ this does nothing because the given bound is not \
does nothing because \ a default. Only `?Sized` is supported");
the given bound is not \
a default. \
Only `Sized?` is \
supported",
desc)[]);
ty::try_add_builtin_trait(this.tcx(), ty::try_add_builtin_trait(this.tcx(),
kind_id, kind_id,
bounds); bounds);
@ -1717,7 +1718,7 @@ fn add_unsized_bound<'tcx,AC>(this: &AC,
ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds); 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. // 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() { for bound in bound_pred.bounds.iter() {
match bound { match bound {
&ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref) => { &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
let trait_ref = astconv::instantiate_poly_trait_ref( let trait_ref = astconv::instantiate_poly_trait_ref(
this, this,
&ExplicitRscope, &ExplicitRscope,
@ -1880,7 +1881,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
for bound in param.bounds.iter() { for bound in param.bounds.iter() {
// In the above example, `ast_trait_ref` is `Iterator`. // In the above example, `ast_trait_ref` is `Iterator`.
let ast_trait_ref = match *bound { let ast_trait_ref = match *bound {
ast::TraitTyParamBound(ref r) => r, ast::TraitTyParamBound(ref r, _) => r,
ast::RegionTyParamBound(..) => { continue; } ast::RegionTyParamBound(..) => { continue; }
}; };
@ -1978,7 +1979,6 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
param.ident.name, param.ident.name,
param_ty, param_ty,
param.bounds[], param.bounds[],
&param.unbound,
param.span); param.span);
let default = match param.default { let default = match param.default {
None => None, None => None,
@ -2023,7 +2023,6 @@ fn compute_bounds<'tcx,AC>(this: &AC,
name_of_bounded_thing: ast::Name, name_of_bounded_thing: ast::Name,
param_ty: ty::ParamTy, param_ty: ty::ParamTy,
ast_bounds: &[ast::TyParamBound], ast_bounds: &[ast::TyParamBound],
unbound: &Option<ast::TraitRef>,
span: Span) span: Span)
-> ty::ParamBounds<'tcx> -> ty::ParamBounds<'tcx>
where AC: AstConv<'tcx> { where AC: AstConv<'tcx> {
@ -2032,11 +2031,9 @@ fn compute_bounds<'tcx,AC>(this: &AC,
param_ty, param_ty,
ast_bounds); ast_bounds);
add_unsized_bound(this, add_unsized_bound(this,
unbound,
&mut param_bounds.builtin_bounds, &mut param_bounds.builtin_bounds,
"type parameter", ast_bounds,
span); span);
check_bounds_compatible(this.tcx(), check_bounds_compatible(this.tcx(),

View file

@ -353,7 +353,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
match item.node { match item.node {
ast::ItemEnum(_, ref generics) | ast::ItemEnum(_, ref generics) |
ast::ItemStruct(_, ref generics) | ast::ItemStruct(_, ref generics) |
ast::ItemTrait(_, ref generics, _, _, _) => { ast::ItemTrait(_, ref generics, _, _) => {
for (i, p) in generics.lifetimes.iter().enumerate() { for (i, p) in generics.lifetimes.iter().enumerate() {
let id = p.lifetime.id; let id = p.lifetime.id;
self.add_inferred(item.id, RegionParam, TypeSpace, i, id); self.add_inferred(item.id, RegionParam, TypeSpace, i, id);

View file

@ -163,13 +163,12 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt,
} }
}); });
let trait_def = ty::lookup_trait_def(tcx, did); 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 { clean::Trait {
unsafety: def.unsafety, unsafety: def.unsafety,
generics: (&def.generics, subst::TypeSpace).clean(cx), generics: (&def.generics, subst::TypeSpace).clean(cx),
items: items.collect(), items: items.collect(),
bounds: bounds, 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()), derived: clean::detect_derived(attrs.as_slice()),
trait_: associated_trait.clean(cx).map(|bound| { trait_: associated_trait.clean(cx).map(|bound| {
match bound { match bound {
clean::TraitBound(polyt) => polyt.trait_, clean::TraitBound(polyt, _) => polyt.trait_,
clean::RegionBound(..) => unreachable!(), clean::RegionBound(..) => unreachable!(),
} }
}), }),

View file

@ -458,8 +458,6 @@ pub struct TyParam {
pub did: ast::DefId, pub did: ast::DefId,
pub bounds: Vec<TyParamBound>, pub bounds: Vec<TyParamBound>,
pub default: Option<Type>, pub default: Option<Type>,
/// An optional default bound on the parameter which is unbound, like `Sized?`
pub default_unbound: Option<Type>
} }
impl Clean<TyParam> for ast::TyParam { impl Clean<TyParam> for ast::TyParam {
@ -469,7 +467,6 @@ impl Clean<TyParam> for ast::TyParam {
did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id }, did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
bounds: self.bounds.clean(cx), bounds: self.bounds.clean(cx),
default: self.default.clean(cx), default: self.default.clean(cx),
default_unbound: self.unbound.clean(cx)
} }
} }
} }
@ -478,13 +475,12 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
fn clean(&self, cx: &DocContext) -> TyParam { fn clean(&self, cx: &DocContext) -> TyParam {
cx.external_typarams.borrow_mut().as_mut().unwrap() cx.external_typarams.borrow_mut().as_mut().unwrap()
.insert(self.def_id, self.name.clean(cx)); .insert(self.def_id, self.name.clean(cx));
let (bounds, default_unbound) = self.bounds.clean(cx); let bounds = self.bounds.clean(cx);
TyParam { TyParam {
name: self.name.clean(cx), name: self.name.clean(cx),
did: self.def_id, did: self.def_id,
bounds: bounds, bounds: bounds,
default: self.default.clean(cx), default: self.default.clean(cx),
default_unbound: default_unbound
} }
} }
} }
@ -492,14 +488,14 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)] #[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)]
pub enum TyParamBound { pub enum TyParamBound {
RegionBound(Lifetime), RegionBound(Lifetime),
TraitBound(PolyTrait) TraitBound(PolyTrait, ast::TraitBoundModifier)
} }
impl Clean<TyParamBound> for ast::TyParamBound { impl Clean<TyParamBound> for ast::TyParamBound {
fn clean(&self, cx: &DocContext) -> TyParamBound { fn clean(&self, cx: &DocContext) -> TyParamBound {
match *self { match *self {
ast::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)), 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<TyParamBound> for ty::BuiltinBound {
did: did, did: did,
}, },
lifetimes: vec![] lifetimes: vec![]
}) }, ast::TraitBoundModifier::None)
} }
} }
@ -648,37 +644,20 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
TraitBound(PolyTrait { TraitBound(PolyTrait {
trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, }, trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, },
lifetimes: late_bounds lifetimes: late_bounds
}) }, ast::TraitBoundModifier::None)
} }
} }
// Returns (bounds, default_unbound) impl<'tcx> Clean<Vec<TyParamBound>> for ty::ParamBounds<'tcx> {
impl<'tcx> Clean<(Vec<TyParamBound>, Option<Type>)> for ty::ParamBounds<'tcx> { fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Option<Type>) {
let mut v = Vec::new(); 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() { for t in self.trait_bounds.iter() {
v.push(t.clean(cx)); v.push(t.clean(cx));
} }
for r in self.region_bounds.iter().filter_map(|r| r.clean(cx)) { for r in self.region_bounds.iter().filter_map(|r| r.clean(cx)) {
v.push(RegionBound(r)); v.push(RegionBound(r));
} }
if has_sized_bound { v
(v, None)
} else {
let ty = match ty::BoundSized.clean(cx) {
TraitBound(polyt) => polyt.trait_,
_ => unreachable!()
};
(v, Some(ty))
}
} }
} }
@ -689,7 +668,7 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
v.extend(self.types.iter().map(|t| TraitBound(PolyTrait { v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
trait_: t.clean(cx), trait_: t.clean(cx),
lifetimes: vec![] lifetimes: vec![]
}))); }, ast::TraitBoundModifier::None)));
if v.len() > 0 {Some(v)} else {None} if v.len() > 0 {Some(v)} else {None}
} }
} }
@ -1047,8 +1026,6 @@ pub struct Trait {
pub items: Vec<TraitMethod>, pub items: Vec<TraitMethod>,
pub generics: Generics, pub generics: Generics,
pub bounds: Vec<TyParamBound>, pub bounds: Vec<TyParamBound>,
/// An optional default bound not required for `Self`, like `Sized?`
pub default_unbound: Option<Type>
} }
impl Clean<Item> for doctree::Trait { impl Clean<Item> for doctree::Trait {
@ -1065,7 +1042,6 @@ impl Clean<Item> for doctree::Trait {
items: self.items.clean(cx), items: self.items.clean(cx),
generics: self.generics.clean(cx), generics: self.generics.clean(cx),
bounds: self.bounds.clean(cx), bounds: self.bounds.clean(cx),
default_unbound: self.default_unbound.clean(cx)
}), }),
} }
} }
@ -2412,7 +2388,6 @@ impl Clean<Item> for ty::AssociatedType {
}, },
bounds: vec![], bounds: vec![],
default: None, default: None,
default_unbound: None
}), }),
visibility: None, visibility: None,
def_id: self.def_id, def_id: self.def_id,

View file

@ -178,7 +178,6 @@ pub struct Trait {
pub whence: Span, pub whence: Span,
pub vis: ast::Visibility, pub vis: ast::Visibility,
pub stab: Option<attr::Stability>, pub stab: Option<attr::Stability>,
pub default_unbound: Option<ast::TraitRef> // FIXME(tomjakubowski)
} }
pub struct Impl { pub struct Impl {

View file

@ -97,9 +97,6 @@ impl fmt::Show for clean::Generics {
if i > 0 { if i > 0 {
try!(f.write(", ".as_bytes())) try!(f.write(", ".as_bytes()))
} }
if let Some(ref unbound) = tp.default_unbound {
try!(write!(f, "{}? ", unbound));
};
try!(f.write(tp.name.as_bytes())); try!(f.write(tp.name.as_bytes()));
if tp.bounds.len() > 0 { if tp.bounds.len() > 0 {
@ -182,8 +179,12 @@ impl fmt::Show for clean::TyParamBound {
clean::RegionBound(ref lt) => { clean::RegionBound(ref lt) => {
write!(f, "{}", *lt) write!(f, "{}", *lt)
} }
clean::TraitBound(ref ty) => { clean::TraitBound(ref ty, modifier) => {
write!(f, "{}", *ty) 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() { for bound in decl.bounds.iter() {
match *bound { match *bound {
clean::RegionBound(..) => {} clean::RegionBound(..) => {}
clean::TraitBound(ref t) => { clean::TraitBound(ref t, modifier) => {
if ret.len() == 0 { if ret.len() == 0 {
ret.push_str(": "); ret.push_str(": ");
} else { } else {
ret.push_str(" + "); ret.push_str(" + ");
} }
if modifier == ast::TraitBoundModifier::Maybe {
ret.push_str("?");
}
ret.push_str(format!("{}", ret.push_str(format!("{}",
*t).as_slice()); *t).as_slice());
} }

View file

@ -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, fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
t: &clean::Trait) -> fmt::Result { t: &clean::Trait) -> fmt::Result {
let mut bounds = String::new(); 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 t.bounds.len() > 0 {
if bounds.len() > 0 { if bounds.len() > 0 {
bounds.push(' '); bounds.push(' ');

View file

@ -322,7 +322,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}; };
om.constants.push(s); 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 { let t = Trait {
unsafety: unsafety, unsafety: unsafety,
name: name, name: name,
@ -334,7 +334,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: item.span, whence: item.span,
vis: item.vis, vis: item.vis,
stab: self.stability(item.id), stab: self.stability(item.id),
default_unbound: def_ub.clone()
}; };
om.traits.push(t); om.traits.push(t);
}, },

View file

@ -371,10 +371,18 @@ pub const DUMMY_NODE_ID: NodeId = -1;
/// detects Copy, Send and Sync. /// detects Copy, Send and Sync.
#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub enum TyParamBound { pub enum TyParamBound {
TraitTyParamBound(PolyTraitRef), TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
RegionTyParamBound(Lifetime) 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>; pub type TyParamBounds = OwnedSlice<TyParamBound>;
#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
@ -382,7 +390,6 @@ pub struct TyParam {
pub ident: Ident, pub ident: Ident,
pub id: NodeId, pub id: NodeId,
pub bounds: TyParamBounds, pub bounds: TyParamBounds,
pub unbound: Option<TraitRef>,
pub default: Option<P<Ty>>, pub default: Option<P<Ty>>,
pub span: Span pub span: Span
} }
@ -1488,7 +1495,7 @@ pub struct PolyTraitRef {
pub bound_lifetimes: Vec<LifetimeDef>, pub bound_lifetimes: Vec<LifetimeDef>,
/// The `Foo<&'a T>` in `<'a> Foo<&'a T>` /// 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)] #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
@ -1577,8 +1584,6 @@ pub enum Item_ {
/// Represents a Trait Declaration /// Represents a Trait Declaration
ItemTrait(Unsafety, ItemTrait(Unsafety,
Generics, Generics,
Option<TraitRef>, // (optional) default bound not required for Self.
// Currently, only Sized makes sense here.
TyParamBounds, TyParamBounds,
Vec<TraitItem>), Vec<TraitItem>),
ItemImpl(Unsafety, ItemImpl(Unsafety,

View file

@ -780,9 +780,9 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
None => {} None => {}
} }
} }
ItemTrait(_, _, _, ref bounds, ref trait_items) => { ItemTrait(_, _, ref bounds, ref trait_items) => {
for b in bounds.iter() { 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)); self.insert(t.trait_ref.ref_id, NodeItem(i));
} }
} }

View file

@ -139,11 +139,11 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
.collect(); .collect();
ast::ItemImpl(u, a, b, c, impl_items) 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() let methods = methods.into_iter()
.filter(|m| trait_method_in_cfg(cx, m)) .filter(|m| trait_method_in_cfg(cx, m))
.collect(); .collect();
ast::ItemTrait(u, a, b, c, methods) ast::ItemTrait(u, a, b, methods)
} }
ast::ItemStruct(def, generics) => { ast::ItemStruct(def, generics) => {
ast::ItemStruct(fold_struct(cx, def), generics) ast::ItemStruct(fold_struct(cx, def), generics)

View file

@ -68,7 +68,6 @@ pub trait AstBuilder {
span: Span, span: Span,
id: ast::Ident, id: ast::Ident,
bounds: OwnedSlice<ast::TyParamBound>, bounds: OwnedSlice<ast::TyParamBound>,
unbound: Option<ast::TraitRef>,
default: Option<P<ast::Ty>>) -> ast::TyParam; default: Option<P<ast::Ty>>) -> ast::TyParam;
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef; fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
@ -414,13 +413,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
span: Span, span: Span,
id: ast::Ident, id: ast::Ident,
bounds: OwnedSlice<ast::TyParamBound>, bounds: OwnedSlice<ast::TyParamBound>,
unbound: Option<ast::TraitRef>,
default: Option<P<ast::Ty>>) -> ast::TyParam { default: Option<P<ast::Ty>>) -> ast::TyParam {
ast::TyParam { ast::TyParam {
ident: id, ident: id,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
bounds: bounds, bounds: bounds,
unbound: unbound,
default: default, default: default,
span: span span: span
} }
@ -455,7 +452,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
} }
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound { 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 { fn lifetime(&self, span: Span, name: ast::Name) -> ast::Lifetime {

View file

@ -58,10 +58,10 @@ fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: LifetimeBounds { generics: LifetimeBounds {
lifetimes: Vec::new(), lifetimes: Vec::new(),
bounds: vec!(("__D", None, vec!(Path::new_( bounds: vec!(("__D", vec!(Path::new_(
vec!(krate, "Decoder"), None, vec!(krate, "Decoder"), None,
vec!(box Literal(Path::new_local("__E"))), true))), vec!(box Literal(Path::new_local("__E"))), true))),
("__E", None, vec!())) ("__E", vec!()))
}, },
methods: vec!( methods: vec!(
MethodDef { MethodDef {

View file

@ -134,10 +134,10 @@ fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: LifetimeBounds { generics: LifetimeBounds {
lifetimes: Vec::new(), lifetimes: Vec::new(),
bounds: vec!(("__S", None, vec!(Path::new_( bounds: vec!(("__S", vec!(Path::new_(
vec!(krate, "Encoder"), None, vec!(krate, "Encoder"), None,
vec!(box Literal(Path::new_local("__E"))), true))), vec!(box Literal(Path::new_local("__E"))), true))),
("__E", None, vec!())) ("__E", vec!()))
}, },
methods: vec!( methods: vec!(
MethodDef { MethodDef {

View file

@ -417,7 +417,6 @@ impl<'a> TraitDef<'a> {
cx.typaram(self.span, cx.typaram(self.span,
ty_param.ident, ty_param.ident,
OwnedSlice::from_vec(bounds), OwnedSlice::from_vec(bounds),
ty_param.unbound.clone(),
None) None)
})); }));

View file

@ -189,15 +189,19 @@ impl<'a> Ty<'a> {
} }
fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, fn mk_ty_param(cx: &ExtCtxt,
bounds: &[Path], unbound: Option<ast::TraitRef>, span: Span,
self_ident: Ident, self_generics: &Generics) -> ast::TyParam { name: &str,
bounds: &[Path],
self_ident: Ident,
self_generics: &Generics)
-> ast::TyParam {
let bounds = let bounds =
bounds.iter().map(|b| { bounds.iter().map(|b| {
let path = b.to_path(cx, span, self_ident, self_generics); let path = b.to_path(cx, span, self_ident, self_generics);
cx.typarambound(path) cx.typarambound(path)
}).collect(); }).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>) 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)] #[deriving(Clone)]
pub struct LifetimeBounds<'a> { pub struct LifetimeBounds<'a> {
pub lifetimes: Vec<(&'a str, Vec<&'a str>)>, 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> { impl<'a> LifetimeBounds<'a> {
@ -239,12 +243,11 @@ impl<'a> LifetimeBounds<'a> {
}).collect(); }).collect();
let ty_params = self.bounds.iter().map(|t| { let ty_params = self.bounds.iter().map(|t| {
match t { match t {
&(ref name, ref unbound, ref bounds) => { &(ref name, ref bounds) => {
mk_ty_param(cx, mk_ty_param(cx,
span, span,
*name, *name,
bounds.as_slice(), bounds.as_slice(),
unbound.clone(),
self_ty, self_ty,
self_generics) self_generics)
} }

View file

@ -30,7 +30,7 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
vec!(box Literal(Path::new_local("__S"))), true), vec!(box Literal(Path::new_local("__S"))), true),
LifetimeBounds { LifetimeBounds {
lifetimes: Vec::new(), lifetimes: Vec::new(),
bounds: vec!(("__S", None, bounds: vec!(("__S",
vec!(Path::new(vec!("std", "hash", "Writer"))))), vec!(Path::new(vec!("std", "hash", "Writer"))))),
}, },
Path::new_local("__S")) Path::new_local("__S"))

View file

@ -36,7 +36,6 @@ pub fn expand_deriving_rand<F>(cx: &mut ExtCtxt,
generics: LifetimeBounds { generics: LifetimeBounds {
lifetimes: Vec::new(), lifetimes: Vec::new(),
bounds: vec!(("R", bounds: vec!(("R",
None,
vec!( Path::new(vec!("std", "rand", "Rng")) ))) vec!( Path::new(vec!("std", "rand", "Rng")) )))
}, },
explicit_self: None, explicit_self: None,

View file

@ -736,18 +736,17 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
-> TyParamBound -> TyParamBound
where T: Folder { where T: Folder {
match tpb { 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)), RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
} }
} }
pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam { 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 { TyParam {
id: fld.new_id(id), id: fld.new_id(id),
ident: ident, ident: ident,
bounds: fld.fold_bounds(bounds), bounds: fld.fold_bounds(bounds),
unbound: unbound.map(|x| fld.fold_trait_ref(x)),
default: default.map(|x| fld.fold_ty(x)), default: default.map(|x| fld.fold_ty(x)),
span: span span: span
} }
@ -1043,7 +1042,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
folder.fold_ty(ty), folder.fold_ty(ty),
new_impl_items) new_impl_items)
} }
ItemTrait(unsafety, generics, unbound, bounds, methods) => { ItemTrait(unsafety, generics, bounds, methods) => {
let bounds = folder.fold_bounds(bounds); let bounds = folder.fold_bounds(bounds);
let methods = methods.into_iter().flat_map(|method| { let methods = methods.into_iter().flat_map(|method| {
let r = match method { let r = match method {
@ -1073,7 +1072,6 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
}).collect(); }).collect();
ItemTrait(unsafety, ItemTrait(unsafety,
folder.fold_generics(generics), folder.fold_generics(generics),
unbound,
bounds, bounds,
methods) methods)
} }

View file

@ -15,7 +15,7 @@ use self::ItemOrViewItem::*;
use abi; use abi;
use ast::{AssociatedType, BareFnTy, ClosureTy}; use ast::{AssociatedType, BareFnTy, ClosureTy};
use ast::{RegionTyParamBound, TraitTyParamBound}; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
use ast::{ProvidedMethod, Public, Unsafety}; use ast::{ProvidedMethod, Public, Unsafety};
use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue}; use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, Block}; use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, Block};
@ -117,6 +117,13 @@ pub enum PathParsingMode {
LifetimeAndTypesWithColons, LifetimeAndTypesWithColons,
} }
/// How to parse a bound, whether to allow bound modifiers such as `?`.
#[deriving(Copy, PartialEq)]
pub enum BoundParsingMode {
Bare,
Modified,
}
enum ItemOrViewItem { enum ItemOrViewItem {
/// Indicates a failure to parse any kind of item. The attributes are /// Indicates a failure to parse any kind of item. The attributes are
/// returned. /// returned.
@ -1087,12 +1094,12 @@ impl<'a> Parser<'a> {
let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs, let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs,
trait_ref: trait_ref }; trait_ref: trait_ref };
let other_bounds = if self.eat(&token::BinOp(token::Plus)) { let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
self.parse_ty_param_bounds() self.parse_ty_param_bounds(BoundParsingMode::Bare)
} else { } else {
OwnedSlice::empty() OwnedSlice::empty()
}; };
let all_bounds = 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()) .chain(other_bounds.into_vec().into_iter())
.collect(); .collect();
ast::TyPolyTraitRef(all_bounds) ast::TyPolyTraitRef(all_bounds)
@ -1165,7 +1172,7 @@ impl<'a> Parser<'a> {
// To be helpful, parse the proc as ever // To be helpful, parse the proc as ever
let _ = self.parse_legacy_lifetime_defs(lifetime_defs); let _ = self.parse_legacy_lifetime_defs(lifetime_defs);
let _ = self.parse_fn_args(false, false); 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(); let _ = self.parse_ret_ty();
self.obsolete(proc_span, ObsoleteProcType); self.obsolete(proc_span, ObsoleteProcType);
@ -1255,7 +1262,7 @@ impl<'a> Parser<'a> {
inputs 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 output = self.parse_ret_ty();
let decl = P(FnDecl { let decl = P(FnDecl {
@ -1481,7 +1488,7 @@ impl<'a> Parser<'a> {
return lhs; 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, // In type grammar, `+` is treated like a binary operator,
// and hence both L and R side are required. // 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, // Parses a sequence of bounds if a `:` is found,
// otherwise returns empty list. // 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> -> OwnedSlice<TyParamBound>
{ {
if !self.eat(&token::Colon) { if !self.eat(&token::Colon) {
OwnedSlice::empty() OwnedSlice::empty()
} else { } 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 // where boundseq = ( polybound + boundseq ) | polybound
// and polybound = ( 'for' '<' 'region '>' )? bound // and polybound = ( 'for' '<' 'region '>' )? bound
// and bound = 'region | trait_ref // 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> -> OwnedSlice<TyParamBound>
{ {
let mut result = vec!(); let mut result = vec!();
loop { loop {
let question_span = self.span;
let ate_question = self.eat(&token::Question);
match self.token { match self.token {
token::Lifetime(lifetime) => { token::Lifetime(lifetime) => {
if ate_question {
self.span_err(question_span,
"`?` may only modify trait bounds, not lifetime bounds");
}
result.push(RegionTyParamBound(ast::Lifetime { result.push(RegionTyParamBound(ast::Lifetime {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: self.span, span: self.span,
@ -4060,7 +4074,18 @@ impl<'a> Parser<'a> {
} }
token::ModSep | token::Ident(..) => { token::ModSep | token::Ident(..) => {
let poly_trait_ref = self.parse_poly_trait_ref(); 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, _ => 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 { fn parse_ty_param(&mut self) -> TyParam {
// This is a bit hacky. Currently we are only interested in a single // 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 // unbound, and it may only be `Sized`. To avoid backtracking and other
// complications, we parse an ident, then check for `?`. If we find it, // 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 // 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 span = self.span;
let mut ident = self.parse_ident(); let mut ident = self.parse_ident();
let mut unbound = None; let mut unbound = None;
@ -4106,7 +4132,14 @@ impl<'a> Parser<'a> {
ident = self.parse_ident(); 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) { let default = if self.check(&token::Eq) {
self.bump(); self.bump();
@ -4118,7 +4151,6 @@ impl<'a> Parser<'a> {
ident: ident, ident: ident,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
bounds: bounds, bounds: bounds,
unbound: unbound,
default: default, default: default,
span: span, span: span,
} }
@ -4260,7 +4292,7 @@ impl<'a> Parser<'a> {
let bounded_ty = self.parse_ty(); let bounded_ty = self.parse_ty();
if self.eat(&token::Colon) { 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 hi = self.span.hi;
let span = mk_sp(lo, hi); let span = mk_sp(lo, hi);
@ -4747,15 +4779,23 @@ impl<'a> Parser<'a> {
fn parse_item_trait(&mut self, unsafety: Unsafety) -> ItemInfo { fn parse_item_trait(&mut self, unsafety: Unsafety) -> ItemInfo {
let ident = self.parse_ident(); let ident = self.parse_ident();
let mut tps = self.parse_generics(); let mut tps = self.parse_generics();
let sized = self.parse_for_sized(); let unbound = self.parse_for_sized();
// Parse supertrait bounds. // 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); self.parse_where_clause(&mut tps);
let meths = self.parse_trait_items(); 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>) { 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> { 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) { if self.eat_keyword(keywords::For) {
let span = self.span; let span = self.span;
let mut ate_question = false;
if self.eat(&token::Question) {
ate_question = true;
}
let ident = self.parse_ident(); 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, self.span_err(span,
"expected 'Sized?' after `for` in trait item"); "expected `?Sized` after `for` in trait item");
return None; return None;
} }
let tref = Parser::trait_ref_from_ident(ident, span); let tref = Parser::trait_ref_from_ident(ident, span);

View file

@ -13,7 +13,7 @@ pub use self::AnnNode::*;
use abi; use abi;
use ast::{mod, FnUnboxedClosureKind, FnMutUnboxedClosureKind}; use ast::{mod, FnUnboxedClosureKind, FnMutUnboxedClosureKind};
use ast::{FnOnceUnboxedClosureKind}; use ast::{FnOnceUnboxedClosureKind};
use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound}; use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem}; use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem};
use ast::{UnboxedClosureKind}; use ast::{UnboxedClosureKind};
use ast_util; use ast_util;
@ -958,20 +958,25 @@ impl<'a> State<'a> {
} }
try!(self.bclose(item.span)); 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.head(""));
try!(self.print_visibility(item.vis)); try!(self.print_visibility(item.vis));
try!(self.print_unsafety(unsafety)); try!(self.print_unsafety(unsafety));
try!(self.word_nbsp("trait")); try!(self.word_nbsp("trait"));
try!(self.print_ident(item.ident)); try!(self.print_ident(item.ident));
try!(self.print_generics(generics)); try!(self.print_generics(generics));
if let &Some(ref tref) = unbound { let bounds: Vec<_> = bounds.iter().map(|b| b.clone()).collect();
try!(space(&mut self.s)); let mut real_bounds = Vec::with_capacity(bounds.len());
try!(self.word_space("for")); for b in bounds.into_iter() {
try!(self.print_trait_ref(tref)); if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = b {
try!(word(&mut self.s, "?")); 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!(self.print_where_clause(generics));
try!(word(&mut self.s, " ")); try!(word(&mut self.s, " "));
try!(self.bopen()); try!(self.bopen());
@ -2345,7 +2350,11 @@ impl<'a> State<'a> {
} }
try!(match *bound { 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) self.print_poly_trait_ref(tref)
} }
RegionTyParamBound(ref lt) => { RegionTyParamBound(ref lt) => {
@ -2412,10 +2421,6 @@ impl<'a> State<'a> {
} }
pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> { 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_ident(param.ident));
try!(self.print_bounds(":", param.bounds[])); try!(self.print_bounds(":", param.bounds[]));
match param.default { match param.default {

View file

@ -85,8 +85,8 @@ pub trait Visitor<'v> {
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
walk_ty_param_bound(self, bounds) walk_ty_param_bound(self, bounds)
} }
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef) { fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
walk_poly_trait_ref(self, t) walk_poly_trait_ref(self, t, m)
} }
fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) { fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
walk_struct_def(self, s) 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 /// Like with walk_method_helper this doesn't correspond to a method
/// in Visitor, and so it gets a _helper suffix. /// in Visitor, and so it gets a _helper suffix.
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, 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> where V: Visitor<'v>
{ {
walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes); 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, generics,
item.id) item.id)
} }
ItemTrait(_, ref generics, _, ref bounds, ref methods) => { ItemTrait(_, ref generics, ref bounds, ref methods) => {
visitor.visit_generics(generics); visitor.visit_generics(generics);
walk_ty_param_bounds_helper(visitor, bounds); walk_ty_param_bounds_helper(visitor, bounds);
for method in methods.iter() { 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, pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
bound: &'v TyParamBound) { bound: &'v TyParamBound) {
match *bound { match *bound {
TraitTyParamBound(ref typ) => { TraitTyParamBound(ref typ, ref modifier) => {
visitor.visit_poly_trait_ref(typ); visitor.visit_poly_trait_ref(typ, modifier);
} }
RegionTyParamBound(ref lifetime) => { RegionTyParamBound(ref lifetime) => {
visitor.visit_lifetime_bound(lifetime); visitor.visit_lifetime_bound(lifetime);

View file

@ -23,7 +23,7 @@ impl Trait for A {
} }
} }
struct Foo<Sized? T> { struct Foo<T: ?Sized> {
f: T f: T
} }

View file

@ -10,7 +10,7 @@
// As dst-struct.rs, but the unsized field is the only field in the struct. // As dst-struct.rs, but the unsized field is the only field in the struct.
struct Fat<Sized? T> { struct Fat<T: ?Sized> {
ptr: T ptr: T
} }

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
struct Fat<Sized? T> { struct Fat<T: ?Sized> {
f1: int, f1: int,
f2: &'static str, f2: &'static str,
ptr: T ptr: T

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
struct Fat<Sized? T> { struct Fat<T: ?Sized> {
f1: int, f1: int,
f2: &'static str, f2: &'static str,
ptr: T ptr: T

View file

@ -22,7 +22,7 @@ struct IndirectBlah { x: Box<IndirectTraitWithSend> }
impl TraitWithSend for IndirectBlah {} impl TraitWithSend for IndirectBlah {}
impl IndirectTraitWithSend for IndirectBlah {} impl IndirectTraitWithSend for IndirectBlah {}
fn test_trait<Sized? T: Send>() { println!("got here!") } fn test_trait<T: Send + ?Sized>() { println!("got here!") }
fn main() { fn main() {
test_trait::<TraitWithSend>(); test_trait::<TraitWithSend>();

View file

@ -11,6 +11,6 @@
// Test that astconv doesn't forget about mutability of &mut str // Test that astconv doesn't forget about mutability of &mut str
fn main() { fn main() {
fn foo<Sized? T>(_: &mut T) {} fn foo<T: ?Sized>(_: &mut T) {}
let _f: fn(&mut str) = foo; let _f: fn(&mut str) = foo;
} }

View file

@ -16,7 +16,7 @@
use std::kinds::Sized; use std::kinds::Sized;
// Note: this must be generic for the problem to show up // Note: this must be generic for the problem to show up
trait Foo<A> for Sized? { trait Foo<A> for ?Sized {
fn foo(&self); fn foo(&self);
} }

View file

@ -10,21 +10,22 @@
// //
// ignore-lexer-test FIXME #15879 // ignore-lexer-test FIXME #15879
// Test syntax checks for `Sized?` syntax. // Test syntax checks for `?Sized` syntax.
trait T1 for Sized? {} trait T1 for ?Sized {}
pub trait T2 for Sized? {} pub trait T2 for ?Sized {}
trait T3<X: T1> for Sized?: T2 {} trait T3<X: T1> for ?Sized: T2 {}
trait T4<Sized? X> {} trait T4<X: ?Sized> {}
trait T5<Sized? X, Y> {} trait T5<X: ?Sized, Y> {}
trait T6<Y, Sized? X> {} trait T6<Y, X: ?Sized> {}
trait T7<Sized? X, Sized? Y> {} trait T7<X: ?Sized, Y: ?Sized> {}
trait T8<Sized? X: T2> {} trait T8<X: ?Sized+T2> {}
struct S1<Sized? X>; trait T9<X: T2 + ?Sized> {}
enum E<Sized? X> {} struct S1<X: ?Sized>;
impl <Sized? X> T1 for S1<X> {} enum E<X: ?Sized> {}
fn f<Sized? X>() {} impl <X: ?Sized> T1 for S1<X> {}
type TT<Sized? T> = T; fn f<X: ?Sized>() {}
type TT<T: ?Sized> = T;
pub fn main() { pub fn main() {
} }

View file

@ -13,7 +13,7 @@
// Test sized-ness checking in substitution. // Test sized-ness checking in substitution.
// Unbounded. // Unbounded.
fn f1<Sized? X>(x: &X) { fn f1<X: ?Sized>(x: &X) {
f1::<X>(x); f1::<X>(x);
} }
fn f2<X>(x: &X) { fn f2<X>(x: &X) {
@ -22,8 +22,8 @@ fn f2<X>(x: &X) {
} }
// Bounded. // Bounded.
trait T for Sized? {} trait T for ?Sized {}
fn f3<Sized? X: T>(x: &X) { fn f3<X: T+?Sized>(x: &X) {
f3::<X>(x); f3::<X>(x);
} }
fn f4<X: T>(x: &X) { fn f4<X: T>(x: &X) {
@ -32,7 +32,7 @@ fn f4<X: T>(x: &X) {
} }
// Self type. // Self type.
trait T2 for Sized? { trait T2 for ?Sized {
fn f() -> Box<Self>; fn f() -> Box<Self>;
} }
struct S; struct S;
@ -41,14 +41,14 @@ impl T2 for S {
box S box S
} }
} }
fn f5<Sized? X: T2>(x: &X) { fn f5<X: ?Sized+T2>(x: &X) {
let _: Box<X> = T2::f(); let _: Box<X> = T2::f();
} }
fn f6<X: T2>(x: &X) { fn f6<X: T2>(x: &X) {
let _: Box<X> = T2::f(); let _: Box<X> = T2::f();
} }
trait T3 for Sized? { trait T3 for ?Sized {
fn f() -> Box<Self>; fn f() -> Box<Self>;
} }
impl T3 for S { impl T3 for S {
@ -56,7 +56,7 @@ impl T3 for S {
box S box S
} }
} }
fn f7<Sized? X: T3>(x: &X) { fn f7<X: ?Sized+T3>(x: &X) {
// This is valid, but the unsized bound on X is irrelevant because any type // This is valid, but the unsized bound on X is irrelevant because any type
// which implements T3 must have statically known size. // which implements T3 must have statically known size.
let _: Box<X> = T3::f(); let _: Box<X> = T3::f();
@ -66,7 +66,7 @@ trait T4<X> {
fn m1(x: &T4<X>); fn m1(x: &T4<X>);
fn m2(x: &T5<X>); fn m2(x: &T5<X>);
} }
trait T5<Sized? X> { trait T5<X: ?Sized> {
// not an error (for now) // not an error (for now)
fn m1(x: &T4<X>); fn m1(x: &T4<X>);
fn m2(x: &T5<X>); fn m2(x: &T5<X>);
@ -76,21 +76,21 @@ trait T6<X: T> {
fn m1(x: &T4<X>); fn m1(x: &T4<X>);
fn m2(x: &T5<X>); fn m2(x: &T5<X>);
} }
trait T7<Sized? X: T> { trait T7<X: ?Sized+T> {
// not an error (for now) // not an error (for now)
fn m1(x: &T4<X>); fn m1(x: &T4<X>);
fn m2(x: &T5<X>); fn m2(x: &T5<X>);
} }
// The last field in a struct or variant may be unsized // The last field in a struct or variant may be unsized
struct S2<Sized? X> { struct S2<X: ?Sized> {
f: X, f: X,
} }
struct S3<Sized? X> { struct S3<X: ?Sized> {
f1: int, f1: int,
f2: X, f2: X,
} }
enum E<Sized? X> { enum E<X: ?Sized> {
V1(X), V1(X),
V2{x: X}, V2{x: X},
V3(int, X), V3(int, X),