Skip to content

Commit 2b5724f

Browse files
committed
Rollup merge of rust-lang#33926 - jseyfried:fix_derive_span, r=nrc
Fix the span of generated `#[derive_*]` attributes Fixes rust-lang#33571. r? @nrc
2 parents 653ce3e + a0e606c commit 2b5724f

File tree

3 files changed

+38
-60
lines changed

3 files changed

+38
-60
lines changed

src/libsyntax_ext/deriving/generic/mod.rs

+3-21
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ use syntax::codemap::{self, respan, DUMMY_SP};
201201
use syntax::codemap::Span;
202202
use syntax::errors::Handler;
203203
use syntax::util::move_map::MoveMap;
204-
use syntax::parse::token::{intern, keywords, InternedString};
204+
use syntax::parse::token::{keywords, InternedString};
205205
use syntax::ptr::P;
206206

207207
use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
@@ -1420,31 +1420,13 @@ impl<'a> MethodDef<'a> {
14201420

14211421
// general helper methods.
14221422
impl<'a> TraitDef<'a> {
1423-
fn set_expn_info(&self,
1424-
cx: &mut ExtCtxt,
1425-
mut to_set: Span) -> Span {
1426-
let trait_name = match self.path.path.last() {
1427-
None => cx.span_bug(self.span, "trait with empty path in generic `derive`"),
1428-
Some(name) => *name
1429-
};
1430-
to_set.expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
1431-
call_site: to_set,
1432-
callee: codemap::NameAndSpan {
1433-
format: codemap::MacroAttribute(intern(&format!("derive({})", trait_name))),
1434-
span: Some(self.span),
1435-
allow_internal_unstable: false,
1436-
}
1437-
});
1438-
to_set
1439-
}
1440-
14411423
fn summarise_struct(&self,
14421424
cx: &mut ExtCtxt,
14431425
struct_def: &VariantData) -> StaticFields {
14441426
let mut named_idents = Vec::new();
14451427
let mut just_spans = Vec::new();
14461428
for field in struct_def.fields(){
1447-
let sp = self.set_expn_info(cx, field.span);
1429+
let sp = Span { expn_id: self.span.expn_id, ..field.span };
14481430
match field.ident {
14491431
Some(ident) => named_idents.push((ident, sp)),
14501432
_ => just_spans.push(sp),
@@ -1486,7 +1468,7 @@ impl<'a> TraitDef<'a> {
14861468
let mut paths = Vec::new();
14871469
let mut ident_exprs = Vec::new();
14881470
for (i, struct_field) in struct_def.fields().iter().enumerate() {
1489-
let sp = self.set_expn_info(cx, struct_field.span);
1471+
let sp = Span { expn_id: self.span.expn_id, ..struct_field.span };
14901472
let ident = cx.ident_of(&format!("{}_{}", prefix, i));
14911473
paths.push(codemap::Spanned{span: sp, node: ident});
14921474
let val = cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)));

src/libsyntax_ext/deriving/mod.rs

+21-39
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use syntax::ext::base::{ExtCtxt, SyntaxEnv, Annotatable};
1616
use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
1717
use syntax::ext::build::AstBuilder;
1818
use syntax::feature_gate;
19-
use syntax::codemap::Span;
19+
use syntax::codemap::{self, Span};
2020
use syntax::parse::token::{intern, intern_and_get_ident};
2121
use syntax::ptr::P;
2222

@@ -94,37 +94,7 @@ fn expand_derive(cx: &mut ExtCtxt,
9494
}
9595

9696
let mut found_partial_eq = false;
97-
let mut found_eq = false;
98-
99-
// This span is **very** sensitive and crucial to
100-
// getting the stability behavior we want. What we are
101-
// doing is marking the generated `#[derive_*]` with the
102-
// span of the `#[deriving(...)]` attribute (the
103-
// entire attribute, not just the `PartialEq` or `Eq`
104-
// part), but with the current backtrace. The current
105-
// backtrace will contain a topmost entry that IS this
106-
// `#[deriving(...)]` attribute and with the
107-
// "allow-unstable" flag set to true.
108-
//
109-
// Note that we do NOT use the span of the `Eq`
110-
// text itself. You might think this is
111-
// equivalent, because the `Eq` appears within the
112-
// `#[deriving(Eq)]` attribute, and hence we would
113-
// inherit the "allows unstable" from the
114-
// backtrace. But in fact this is not always the
115-
// case. The actual source text that led to
116-
// deriving can be `#[$attr]`, for example, where
117-
// `$attr == deriving(Eq)`. In that case, the
118-
// "#[derive_*]" would be considered to
119-
// originate not from the deriving call but from
120-
// text outside the deriving call, and hence would
121-
// be forbidden from using unstable
122-
// content.
123-
//
124-
// See tests src/run-pass/rfc1445 for
125-
// examples. --nmatsakis
126-
let span = Span { expn_id: cx.backtrace(), .. span };
127-
assert!(cx.parse_sess.codemap().span_allows_unstable(span));
97+
let mut eq_span = None;
12898

12999
for titem in traits.iter().rev() {
130100
let tname = match titem.node {
@@ -144,8 +114,19 @@ fn expand_derive(cx: &mut ExtCtxt,
144114
continue;
145115
}
146116

117+
let span = Span {
118+
expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
119+
call_site: titem.span,
120+
callee: codemap::NameAndSpan {
121+
format: codemap::MacroAttribute(intern(&format!("derive({})", tname))),
122+
span: Some(titem.span),
123+
allow_internal_unstable: true,
124+
},
125+
}), ..titem.span
126+
};
127+
147128
if &tname[..] == "Eq" {
148-
found_eq = true;
129+
eq_span = Some(span);
149130
} else if &tname[..] == "PartialEq" {
150131
found_partial_eq = true;
151132
}
@@ -157,12 +138,13 @@ fn expand_derive(cx: &mut ExtCtxt,
157138

158139
// RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
159140
// `#[structural_match]` attribute.
160-
if found_partial_eq && found_eq {
161-
debug!("inserting structural_match with span {:?}", span);
162-
let structural_match = intern_and_get_ident("structural_match");
163-
item.attrs.push(cx.attribute(span,
164-
cx.meta_word(span,
165-
structural_match)));
141+
if let Some(eq_span) = eq_span {
142+
if found_partial_eq {
143+
let structural_match = intern_and_get_ident("structural_match");
144+
item.attrs.push(cx.attribute(eq_span,
145+
cx.meta_word(eq_span,
146+
structural_match)));
147+
}
166148
}
167149

168150
item

src/test/compile-fail/issue-33571.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[derive(Clone,
12+
Sync, //~ ERROR this unsafe trait should be implemented explicitly
13+
Copy)]
14+
enum Foo {}

0 commit comments

Comments
 (0)