paren sugar is legal.
#![feature(lang_items, unsafe_destructor)]
#![feature(box_syntax)]
#![feature(optin_builtin_traits)]
+#![feature(unboxed_closures)]
#![allow(unknown_features)] #![feature(int_uint)]
#![feature(core)]
#![feature(hash)]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
+#[rustc_paren_sugar]
pub trait Fn<Args> {
type Output;
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
+#[rustc_paren_sugar]
pub trait FnMut<Args> {
type Output;
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
+#[rustc_paren_sugar]
pub trait FnOnce<Args> {
type Output;
// FIXME: #19470 this shouldn't be needed forever
"old_orphan_check",
"old_impl_check",
+ "rustc_paren_sugar", // FIXME: #18101 temporary unboxed closure hack
];
static CRATE_ATTRS: &'static [&'static str] = &[
pub const tag_macro_defs: uint = 0xb5;
pub const tag_macro_def: uint = 0xb6;
pub const tag_macro_def_body: uint = 0xb7;
+
+pub const tag_paren_sugar: uint = 0xb8;
}
}
+fn parse_paren_sugar(item_doc: rbml::Doc) -> bool {
+ let paren_sugar_doc = reader::get_doc(item_doc, tag_paren_sugar);
+ reader::doc_as_u8(paren_sugar_doc) != 0
+}
+
fn parse_polarity(item_doc: rbml::Doc) -> ast::ImplPolarity {
let polarity_doc = reader::get_doc(item_doc, tag_polarity);
if reader::doc_as_u8(polarity_doc) != 0 {
let bounds = trait_def_bounds(item_doc, tcx, cdata);
let unsafety = parse_unsafety(item_doc);
let associated_type_names = parse_associated_type_names(item_doc);
+ let paren_sugar = parse_paren_sugar(item_doc);
ty::TraitDef {
+ paren_sugar: paren_sugar,
unsafety: unsafety,
generics: generics,
bounds: bounds,
encode_item_variances(rbml_w, ecx, item.id);
let trait_def = ty::lookup_trait_def(tcx, def_id);
encode_unsafety(rbml_w, trait_def.unsafety);
+ encode_paren_sugar(rbml_w, trait_def.paren_sugar);
encode_associated_type_names(rbml_w, trait_def.associated_type_names.as_slice());
encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
rbml_w.wr_tagged_u8(tag_unsafety, byte);
}
+fn encode_paren_sugar(rbml_w: &mut Encoder, paren_sugar: bool) {
+ let byte: u8 = if paren_sugar {1} else {0};
+ rbml_w.wr_tagged_u8(tag_paren_sugar, byte);
+}
+
fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
rbml_w.start_tag(tag_associated_type_names);
for &name in names.iter() {
pub struct TraitDef<'tcx> {
pub unsafety: ast::Unsafety,
+ /// If `true`, then this trait had the `#[rustc_paren_sugar]`
+ /// attribute, indicating that it should be used with `Foo()`
+ /// sugar. This is a temporary thing -- eventually any trait wil
+ /// be usable with the sugar (or without it).
+ pub paren_sugar: bool,
+
/// Generic type definitions. Note that `Self` is listed in here
/// as having a single bound, the trait itself (e.g., in the trait
/// `Eq`, there is a single bound `Self : Eq`). This is so that
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
ast::AngleBracketedParameters(ref data) => {
- // For now, require that parenthetical notation be used
+ // For now, require that parenthetical5D notation be used
// only with `Fn()` etc.
- if !this.tcx().sess.features.borrow().unboxed_closures &&
- this.tcx().lang_items.fn_trait_kind(trait_def_id).is_some()
- {
+ if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
span_err!(this.tcx().sess, path.span, E0215,
"angle-bracket notation is not stable when \
used with the `Fn` family of traits, use parentheses");
ast::ParenthesizedParameters(ref data) => {
// For now, require that parenthetical notation be used
// only with `Fn()` etc.
- if !this.tcx().sess.features.borrow().unboxed_closures &&
- this.tcx().lang_items.fn_trait_kind(trait_def_id).is_none()
- {
+ if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
span_err!(this.tcx().sess, path.span, E0216,
"parenthetical notation is only stable when \
used with the `Fn` family of traits");
}
};
+ let paren_sugar = ty::has_attr(tcx, def_id, "rustc_paren_sugar");
+ if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
+ ccx.tcx.sess.span_err(
+ it.span,
+ "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
+ which traits can use parenthetical notation");
+ span_help!(ccx.tcx.sess, it.span,
+ "add `#![feature(unboxed_closures)]` to \
+ the crate attributes to use it");
+ }
+
let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
let ty_generics = ty_generics_for_trait(ccx,
});
let trait_def = Rc::new(ty::TraitDef {
+ paren_sugar: paren_sugar,
unsafety: unsafety,
generics: ty_generics,
bounds: bounds,