diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2016-03-11 13:27:42 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2016-03-25 06:44:14 -0400 |
| commit | 99c2a6b335d953eca64e631f3e9946b1cc6643e1 (patch) | |
| tree | 9d1ef76571e5375395b451cb543349b602008758 | |
| parent | 5bc286806023ef4d63bceec4ba703399ba9ee2f7 (diff) | |
| download | rust-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.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/mod.rs | 48 | ||||
| -rw-r--r-- | src/libsyntax_ext/lib.rs | 1 |
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; |
