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)
This commit is contained in:
Niko Matsakis 2016-03-11 13:27:42 -05:00
parent 5bc2868060
commit 99c2a6b335
3 changed files with 55 additions and 3 deletions

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -24,6 +24,7 @@
#![feature(str_char)]
extern crate fmt_macros;
#[macro_use] extern crate log;
#[macro_use]
extern crate syntax;