about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-03-11 13:27:42 -0500
committerNiko Matsakis <niko@alum.mit.edu>2016-03-25 06:44:14 -0400
commit99c2a6b335d953eca64e631f3e9946b1cc6643e1 (patch)
tree9d1ef76571e5375395b451cb543349b602008758
parent5bc286806023ef4d63bceec4ba703399ba9ee2f7 (diff)
downloadrust-99c2a6b335d953eca64e631f3e9946b1cc6643e1.tar.gz
rust-99c2a6b335d953eca64e631f3e9946b1cc6643e1.zip
modify #[deriving(Eq)] to emit #[structural_match]
to careful use of the span from deriving, we
can permit it in stable code if it derives from
deriving (not-even-a-pun intended)
-rw-r--r--src/libsyntax/feature_gate.rs9
-rw-r--r--src/libsyntax_ext/deriving/mod.rs48
-rw-r--r--src/libsyntax_ext/lib.rs1
3 files changed, 55 insertions, 3 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 299b7d8b9ba..8e7f4876ee2 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -109,6 +109,8 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
     // to bootstrap fix for #5723.
     ("issue_5723_bootstrap", "1.0.0", None, Accepted),
 
+    ("structural_match", "1.8.0", Some(31434), Active),
+
     // A way to temporarily opt out of opt in copy. This will *never* be accepted.
     ("opt_out_copy", "1.0.0", None, Removed),
 
@@ -304,6 +306,11 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
     ("link_args", Normal, Ungated),
     ("macro_escape", Normal, Ungated),
 
+    // RFC #1445.
+    ("structural_match", Whitelisted, Gated("structural_match",
+                                            "the semantics of constant patterns is \
+                                             not yet settled")),
+
     // Not used any more, but we can't feature gate it
     ("no_stack_check", Normal, Ungated),
 
@@ -676,7 +683,7 @@ impl<'a> Context<'a> {
     fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
         let has_feature = self.has_feature(feature);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", feature, span, has_feature);
-        if !has_feature {
+        if !has_feature && !self.cm.span_allows_unstable(span) {
             emit_feature_err(self.span_handler, feature, span, GateIssue::Language, explain);
         }
     }
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 75de5c56ea1..dbd3cbd4fba 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -78,7 +78,10 @@ fn expand_derive(cx: &mut ExtCtxt,
                  mitem: &MetaItem,
                  annotatable: Annotatable)
                  -> Annotatable {
-    annotatable.map_item_or(|item| {
+    debug!("expand_derive: span = {:?}", span);
+    debug!("expand_derive: mitem = {:?}", mitem);
+    debug!("expand_derive: annotatable input  = {:?}", annotatable);
+    let annot = annotatable.map_item_or(|item| {
         item.map(|mut item| {
             if mitem.value_str().is_some() {
                 cx.span_err(mitem.span, "unexpected value in `derive`");
@@ -107,6 +110,45 @@ fn expand_derive(cx: &mut ExtCtxt,
                     continue;
                 }
 
+                // RFC #1445. `#[derive(Eq)]` adds a (trusted)
+                // `#[structural_match]` attribute.
+                if &tname[..] == "Eq" {
+                    // This span is **very** sensitive and crucial to
+                    // getting the stability behavior we want. What we
+                    // are doing is marking `#[structural_match]` with
+                    // the span of the `#[deriving(Eq)]` attribute
+                    // (the entire attribute, not just the `Eq` part),
+                    // but with the current backtrace. The current
+                    // backtrace will contain a topmost entry that IS
+                    // this `#[deriving(Eq)]` attribute and with the
+                    // "allow-unstable" flag set to true.
+                    //
+                    // Note that we do NOT use the span of the `Eq`
+                    // text itself.  You might think this is
+                    // equivalent, because the `Eq` appears within the
+                    // `#[deriving(Eq)]` attribute, and hence we would
+                    // inherit the "allows unstable" from the
+                    // backtrace.  But in fact this is not always the
+                    // case. The actual source text that led to
+                    // deriving can be `#[$attr]`, for example, where
+                    // `$attr == deriving(Eq)`. In that case, the
+                    // "#[structural_match]" would be considered to
+                    // originate not from the deriving call but from
+                    // text outside the deriving call, and hence would
+                    // be forbidden from using unstable
+                    // content.
+                    //
+                    // See tests src/run-pass/rfc1445 for
+                    // examples. --nmatsakis
+                    let span = Span { expn_id: cx.backtrace(), .. span };
+                    assert!(cx.parse_sess.codemap().span_allows_unstable(span));
+                    debug!("inserting structural_match with span {:?}", span);
+                    let structural_match = intern_and_get_ident("structural_match");
+                    item.attrs.push(cx.attribute(span,
+                                                 cx.meta_word(span,
+                                                              structural_match)));
+                }
+
                 // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
                 item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span,
                     intern_and_get_ident(&format!("derive_{}", tname)))));
@@ -117,7 +159,9 @@ fn expand_derive(cx: &mut ExtCtxt,
     }, |a| {
         cx.span_err(span, "`derive` can only be applied to items");
         a
-    })
+    });
+    debug!("expand_derive: annotatable output = {:?}", annot);
+    annot
 }
 
 macro_rules! derive_traits {
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 97531d4279d..f214ecdc336 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -24,6 +24,7 @@
 #![feature(str_char)]
 
 extern crate fmt_macros;
+#[macro_use] extern crate log;
 #[macro_use]
 extern crate syntax;