From a962bdb3daa45da703b8a25fd76e6eebeb97635e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 26 Jan 2015 14:39:58 -0500 Subject: [PATCH] Use `#[rustc_paren_sugar]` as a more extensible way of deciding when paren sugar is legal. --- src/liballoc/lib.rs | 1 + src/libcore/ops.rs | 3 +++ src/librustc/lint/builtin.rs | 1 + src/librustc/metadata/common.rs | 2 ++ src/librustc/metadata/decoder.rs | 7 +++++++ src/librustc/metadata/encoder.rs | 6 ++++++ src/librustc/middle/ty.rs | 6 ++++++ src/librustc_typeck/astconv.rs | 10 +++------- src/librustc_typeck/collect.rs | 12 ++++++++++++ 9 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index f807d8d12a6..8960667fdfa 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -70,6 +70,7 @@ #![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)] diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 55ff3eb4d06..80232764ed4 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -1166,6 +1166,7 @@ impl FnOnce for F #[unstable(feature = "core", reason = "uncertain about variadic generics, input versus associated types")] #[cfg(not(stage0))] +#[rustc_paren_sugar] pub trait Fn { type Output; @@ -1178,6 +1179,7 @@ pub trait Fn { #[unstable(feature = "core", reason = "uncertain about variadic generics, input versus associated types")] #[cfg(not(stage0))] +#[rustc_paren_sugar] pub trait FnMut { type Output; @@ -1190,6 +1192,7 @@ pub trait FnMut { #[unstable(feature = "core", reason = "uncertain about variadic generics, input versus associated types")] #[cfg(not(stage0))] +#[rustc_paren_sugar] pub trait FnOnce { type Output; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index f13814527cd..ee7c0ee894f 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -670,6 +670,7 @@ impl LintPass for UnusedAttributes { // 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] = &[ diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 6c1a8a6f54b..242ab630a20 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -265,3 +265,5 @@ pub const tag_polarity: uint = 0xb4; 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; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 933fd873aeb..93ca42e9a28 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -371,6 +371,11 @@ fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety { } } +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 { @@ -400,8 +405,10 @@ pub fn get_trait_def<'tcx>(cdata: Cmd, 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, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 13dc9397afc..6767f77de84 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1317,6 +1317,7 @@ fn encode_info_for_item(ecx: &EncodeContext, 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); @@ -1697,6 +1698,11 @@ fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) { 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() { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9958d015a8c..425acbae483 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2221,6 +2221,12 @@ pub struct TypeScheme<'tcx> { 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 diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a382cfca0bd..350227c6662 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -614,11 +614,9 @@ fn ast_path_to_trait_ref<'a,'tcx>( 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"); @@ -632,9 +630,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( 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"); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8158b8da86d..ed33ddd458a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -855,6 +855,17 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, } }; + 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, @@ -887,6 +898,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, }); let trait_def = Rc::new(ty::TraitDef { + paren_sugar: paren_sugar, unsafety: unsafety, generics: ty_generics, bounds: bounds,