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.
This commit is contained in:
parent
17f56c549c
commit
35176867f6
6 changed files with 52 additions and 30 deletions
|
@ -282,6 +282,24 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
let expansion = self.expand_invoc(invoc, ext);
|
let expansion = self.expand_invoc(invoc, ext);
|
||||||
self.collect_invocations(expansion, &[])
|
self.collect_invocations(expansion, &[])
|
||||||
} else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
|
} else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
|
||||||
|
let derive_allowed = match item {
|
||||||
|
Annotatable::Item(ref item) => match item.node {
|
||||||
|
ast::ItemKind::Struct(..) |
|
||||||
|
ast::ItemKind::Enum(..) |
|
||||||
|
ast::ItemKind::Union(..) => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if !derive_allowed {
|
||||||
|
let span = item.attrs().iter()
|
||||||
|
.find(|attr| attr.check_name("derive"))
|
||||||
|
.expect("`derive` attribute should exist").span;
|
||||||
|
self.cx.span_err(span,
|
||||||
|
"`derive` may only be applied to structs, enums \
|
||||||
|
and unions");
|
||||||
|
}
|
||||||
|
|
||||||
let item = item
|
let item = item
|
||||||
.map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
|
.map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
|
||||||
let item_with_markers =
|
let item_with_markers =
|
||||||
|
|
|
@ -428,8 +428,9 @@ impl<'a> TraitDef<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
cx.span_err(mitem.span,
|
// Non-ADT derive is an error, but it should have been
|
||||||
"`derive` may only be applied to structs, enums and unions");
|
// set earlier; see
|
||||||
|
// libsyntax/ext/expand.rs:MacroExpander::expand()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -448,8 +449,10 @@ impl<'a> TraitDef<'a> {
|
||||||
push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
|
push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
cx.span_err(mitem.span,
|
// Non-Item derive is an error, but it should have been
|
||||||
"`derive` may only be applied to structs and enums");
|
// set earlier; see
|
||||||
|
// libsyntax/ext/expand.rs:MacroExpander::expand()
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,23 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// `#![derive]` is interpreted (and raises errors) when it occurs at
|
// This test checks cases where the derive-macro does not exist.
|
||||||
// contexts other than ADT definitions. This test checks cases where
|
|
||||||
// the derive-macro does not exist.
|
|
||||||
|
|
||||||
#![derive(x3300)]
|
|
||||||
//~^ ERROR cannot find derive macro `x3300` in this scope
|
|
||||||
|
|
||||||
#[derive(x3300)]
|
|
||||||
//~^ ERROR cannot find derive macro `x3300` in this scope
|
|
||||||
mod derive {
|
mod derive {
|
||||||
mod inner { #![derive(x3300)] }
|
|
||||||
//~^ ERROR cannot find derive macro `x3300` in this scope
|
|
||||||
|
|
||||||
#[derive(x3300)]
|
|
||||||
//~^ ERROR cannot find derive macro `x3300` in this scope
|
|
||||||
fn derive() { }
|
|
||||||
|
|
||||||
#[derive(x3300)]
|
#[derive(x3300)]
|
||||||
//~^ ERROR cannot find derive macro `x3300` in this scope
|
//~^ ERROR cannot find derive macro `x3300` in this scope
|
||||||
union U { f: i32 }
|
union U { f: i32 }
|
||||||
|
@ -36,12 +22,4 @@ mod derive {
|
||||||
#[derive(x3300)]
|
#[derive(x3300)]
|
||||||
//~^ ERROR cannot find derive macro `x3300` in this scope
|
//~^ ERROR cannot find derive macro `x3300` in this scope
|
||||||
struct S;
|
struct S;
|
||||||
|
|
||||||
#[derive(x3300)]
|
|
||||||
//~^ ERROR cannot find derive macro `x3300` in this scope
|
|
||||||
type T = S;
|
|
||||||
|
|
||||||
#[derive(x3300)]
|
|
||||||
//~^ ERROR cannot find derive macro `x3300` in this scope
|
|
||||||
impl S { }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// `#![derive]` is interpreted (and raises errors) when it occurs at
|
// `#![derive]` raises errors when it occurs at contexts other than ADT
|
||||||
// contexts other than ADT definitions. This test checks cases where
|
// definitions.
|
||||||
// the derive-macro exists.
|
|
||||||
|
|
||||||
#![derive(Debug)]
|
#![derive(Debug)]
|
||||||
//~^ ERROR `derive` may only be applied to structs, enums and unions
|
//~^ ERROR `derive` may only be applied to structs, enums and unions
|
||||||
|
|
16
src/test/ui/span/issue-43927-non-ADT-derive.rs
Normal file
16
src/test/ui/span/issue-43927-non-ADT-derive.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
#![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
|
||||||
|
struct DerivedOn;
|
||||||
|
|
||||||
|
fn main() {}
|
8
src/test/ui/span/issue-43927-non-ADT-derive.stderr
Normal file
8
src/test/ui/span/issue-43927-non-ADT-derive.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
error: `derive` may only be applied to structs, enums and unions
|
||||||
|
--> $DIR/issue-43927-non-ADT-derive.rs:13:1
|
||||||
|
|
|
||||||
|
13 | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue