Skip to content

Commit 3517686

Browse files
committed
only set non-ADT derive error once per attribute, not per trait
A slight eccentricity of this change is that now non-ADT-derive errors prevent derive-macro-not-found errors from surfacing (see changes to the gating-of-derive compile-fail tests). Resolves #43927.
1 parent 17f56c5 commit 3517686

File tree

6 files changed

+52
-30
lines changed

6 files changed

+52
-30
lines changed

Diff for: src/libsyntax/ext/expand.rs

+18
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,24 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
282282
let expansion = self.expand_invoc(invoc, ext);
283283
self.collect_invocations(expansion, &[])
284284
} else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
285+
let derive_allowed = match item {
286+
Annotatable::Item(ref item) => match item.node {
287+
ast::ItemKind::Struct(..) |
288+
ast::ItemKind::Enum(..) |
289+
ast::ItemKind::Union(..) => true,
290+
_ => false,
291+
},
292+
_ => false,
293+
};
294+
if !derive_allowed {
295+
let span = item.attrs().iter()
296+
.find(|attr| attr.check_name("derive"))
297+
.expect("`derive` attribute should exist").span;
298+
self.cx.span_err(span,
299+
"`derive` may only be applied to structs, enums \
300+
and unions");
301+
}
302+
285303
let item = item
286304
.map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
287305
let item_with_markers =

Diff for: src/libsyntax_ext/deriving/generic/mod.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,9 @@ impl<'a> TraitDef<'a> {
428428
}
429429
}
430430
_ => {
431-
cx.span_err(mitem.span,
432-
"`derive` may only be applied to structs, enums and unions");
431+
// Non-ADT derive is an error, but it should have been
432+
// set earlier; see
433+
// libsyntax/ext/expand.rs:MacroExpander::expand()
433434
return;
434435
}
435436
};
@@ -448,8 +449,10 @@ impl<'a> TraitDef<'a> {
448449
push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
449450
}
450451
_ => {
451-
cx.span_err(mitem.span,
452-
"`derive` may only be applied to structs and enums");
452+
// Non-Item derive is an error, but it should have been
453+
// set earlier; see
454+
// libsyntax/ext/expand.rs:MacroExpander::expand()
455+
return;
453456
}
454457
}
455458
}

Diff for: src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs

+1-23
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// `#![derive]` is interpreted (and raises errors) when it occurs at
12-
// contexts other than ADT definitions. This test checks cases where
13-
// the derive-macro does not exist.
11+
// This test checks cases where the derive-macro does not exist.
1412

15-
#![derive(x3300)]
16-
//~^ ERROR cannot find derive macro `x3300` in this scope
17-
18-
#[derive(x3300)]
19-
//~^ ERROR cannot find derive macro `x3300` in this scope
2013
mod derive {
21-
mod inner { #![derive(x3300)] }
22-
//~^ ERROR cannot find derive macro `x3300` in this scope
23-
24-
#[derive(x3300)]
25-
//~^ ERROR cannot find derive macro `x3300` in this scope
26-
fn derive() { }
27-
2814
#[derive(x3300)]
2915
//~^ ERROR cannot find derive macro `x3300` in this scope
3016
union U { f: i32 }
@@ -36,12 +22,4 @@ mod derive {
3622
#[derive(x3300)]
3723
//~^ ERROR cannot find derive macro `x3300` in this scope
3824
struct S;
39-
40-
#[derive(x3300)]
41-
//~^ ERROR cannot find derive macro `x3300` in this scope
42-
type T = S;
43-
44-
#[derive(x3300)]
45-
//~^ ERROR cannot find derive macro `x3300` in this scope
46-
impl S { }
4725
}

Diff for: src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// `#![derive]` is interpreted (and raises errors) when it occurs at
12-
// contexts other than ADT definitions. This test checks cases where
13-
// the derive-macro exists.
11+
// `#![derive]` raises errors when it occurs at contexts other than ADT
12+
// definitions.
1413

1514
#![derive(Debug)]
1615
//~^ ERROR `derive` may only be applied to structs, enums and unions

Diff for: src/test/ui/span/issue-43927-non-ADT-derive.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2017 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+
#![allow(dead_code)]
12+
13+
#![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
14+
struct DerivedOn;
15+
16+
fn main() {}

Diff for: src/test/ui/span/issue-43927-non-ADT-derive.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: `derive` may only be applied to structs, enums and unions
2+
--> $DIR/issue-43927-non-ADT-derive.rs:13:1
3+
|
4+
13 | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)