about summary refs log tree commit diff
path: root/src/libsyntax_ext
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-09-11 15:12:27 -0700
committerGitHub <noreply@github.com>2016-09-11 15:12:27 -0700
commit0be88eb794949d27331ec45c300a40369b541001 (patch)
treef57f3c24d72a7e1af6b75c471eb43ef362f5bfb0 /src/libsyntax_ext
parent4812cf392f1fa2258033356dd872fbee58a5406e (diff)
parentfe41520fceb00427e797cc0b42f449f54967b104 (diff)
downloadrust-0be88eb794949d27331ec45c300a40369b541001.tar.gz
rust-0be88eb794949d27331ec45c300a40369b541001.zip
Auto merge of #36308 - dtolnay:inputitem, r=alexcrichton
Point macros 1.1 errors to the input item

Moved from https://github.com/alexcrichton/rust/pull/6 to continue discussion. Fixes #36218.

Before:

```rust
error[E0106]: missing lifetime specifier
  --> src/main.rs:10:10
   |
10 | #[derive(Serialize, Deserialize)]
   |          ^ expected lifetime parameter

error[E0038]: the trait `T` cannot be made into an object
  --> src/main.rs:15:15
   |
15 | #[derive(Serialize, Deserialize)]
   |          ^^^^^^^^^^ the trait `T` cannot be made into an object
```

After:

```rust
error[E0106]: missing lifetime specifier
  --> src/main.rs:11:1
   |
11 | struct A {
   | ^ expected lifetime parameter

error[E0038]: the trait `T` cannot be made into an object
  --> src/main.rs:16:1
   |
16 | struct B<'a> {
   | ^ the trait `T` cannot be made into an object
```
Diffstat (limited to 'src/libsyntax_ext')
-rw-r--r--src/libsyntax_ext/deriving/custom.rs23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
index 1f9c24a0dcd..465fc0016e5 100644
--- a/src/libsyntax_ext/deriving/custom.rs
+++ b/src/libsyntax_ext/deriving/custom.rs
@@ -10,12 +10,14 @@
 
 use std::panic;
 
+use errors::FatalError;
 use rustc_macro::{TokenStream, __internal};
 use syntax::ast::{self, ItemKind};
-use syntax::codemap::Span;
+use syntax::codemap::{ExpnInfo, MacroAttribute, NameAndSpan, Span};
 use syntax::ext::base::*;
 use syntax::fold::{self, Folder};
-use errors::FatalError;
+use syntax::parse::token::intern;
+use syntax::print::pprust;
 
 pub struct CustomDerive {
     inner: fn(TokenStream) -> TokenStream,
@@ -31,7 +33,7 @@ impl MultiItemModifier for CustomDerive {
     fn expand(&self,
               ecx: &mut ExtCtxt,
               span: Span,
-              _meta_item: &ast::MetaItem,
+              meta_item: &ast::MetaItem,
               item: Annotatable)
               -> Vec<Annotatable> {
         let item = match item {
@@ -53,6 +55,17 @@ impl MultiItemModifier for CustomDerive {
             }
         }
 
+        let input_span = Span {
+            expn_id: ecx.codemap().record_expansion(ExpnInfo {
+                call_site: span,
+                callee: NameAndSpan {
+                    format: MacroAttribute(intern(&pprust::meta_item_to_string(meta_item))),
+                    span: Some(span),
+                    allow_internal_unstable: true,
+                },
+            }),
+            ..item.span
+        };
         let input = __internal::new_token_stream(item);
         let res = __internal::set_parse_sess(&ecx.parse_sess, || {
             let inner = self.inner;
@@ -77,9 +90,9 @@ impl MultiItemModifier for CustomDerive {
 
         // Right now we have no knowledge of spans at all in custom derive
         // macros, everything is just parsed as a string. Reassign all spans to
-        // the #[derive] attribute for better errors here.
+        // the input `item` for better errors here.
         item.into_iter().flat_map(|item| {
-            ChangeSpan { span: span }.fold_item(item)
+            ChangeSpan { span: input_span }.fold_item(item)
         }).map(Annotatable::Item).collect()
     }
 }