]> git.lizzy.rs Git - rust.git/commitdiff
Disallow `derive` on items with type macros
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Fri, 24 Jun 2016 03:23:44 +0000 (03:23 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Wed, 29 Jun 2016 01:25:36 +0000 (01:25 +0000)
src/libsyntax_ext/deriving/generic/mod.rs
src/test/compile-fail/issue-32950.rs

index 647e414a7fd2736cf6443e36ed8ce7be8b36458d..e01f4ed1f9bd233a932762ebf3cd110078703805 100644 (file)
@@ -345,15 +345,18 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
 /// This method helps to extract all the type parameters referenced from a
 /// type. For a type parameter `<T>`, it looks for either a `TyPath` that
 /// is not global and starts with `T`, or a `TyQPath`.
-fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast::Ty>> {
+fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name], span: Span, cx: &ExtCtxt)
+                        -> Vec<P<ast::Ty>> {
     use syntax::visit;
 
-    struct Visitor<'a> {
+    struct Visitor<'a, 'b: 'a> {
+        cx: &'a ExtCtxt<'b>,
+        span: Span,
         ty_param_names: &'a [ast::Name],
         types: Vec<P<ast::Ty>>,
     }
 
-    impl<'a> visit::Visitor for Visitor<'a> {
+    impl<'a, 'b> visit::Visitor for Visitor<'a, 'b> {
         fn visit_ty(&mut self, ty: &ast::Ty) {
             match ty.node {
                 ast::TyKind::Path(_, ref path) if !path.global => {
@@ -371,11 +374,18 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
 
             visit::walk_ty(self, ty)
         }
+
+        fn visit_mac(&mut self, mac: &ast::Mac) {
+            let span = Span { expn_id: self.span.expn_id, ..mac.span };
+            self.cx.span_err(span, "`derive` cannot be used on items with type macros");
+        }
     }
 
     let mut visitor = Visitor {
         ty_param_names: ty_param_names,
         types: Vec::new(),
+        span: span,
+        cx: cx,
     };
 
     visit::Visitor::visit_ty(&mut visitor, ty);
@@ -556,7 +566,7 @@ fn create_derived_impl(&self,
 
             let mut processed_field_types = HashSet::new();
             for field_ty in field_tys {
-                let tys = find_type_parameters(&field_ty, &ty_param_names);
+                let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx);
 
                 for ty in tys {
                     // if we have already handled this type, skip it
index e47ebdd6a6938c2613350e36e0163523c97fc102..e8ca1c1fa98ff4a99c755f274b3a7d3aa2c8f799 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(type_macros, concat_idents, rustc_attrs)]
-#![allow(unused)]
+#![feature(type_macros, concat_idents)]
 
-#[derive(Debug)] struct FooBar;
-#[derive(Debug)] struct Baz<T>(T, concat_idents!(Foo, Bar));
+#[derive(Debug)] //~ NOTE in this expansion
+struct Baz<T>(
+    concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros
+);
 
-#[rustc_error]
-fn main() {} //~ ERROR compilation successful
+fn main() {}