about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/lint.rs41
-rw-r--r--src/librustc/middle/ty.rs1
-rw-r--r--src/test/compile-fail/lint-raw-ptr-deriving.rs35
3 files changed, 77 insertions, 0 deletions
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 8c20cf39b49..a0f52021b6e 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -115,6 +115,8 @@ pub enum Lint {
     DeprecatedOwnedVector,
 
     Warnings,
+
+    RawPointerDeriving,
 }
 
 pub fn level_to_str(lv: level) -> &'static str {
@@ -406,6 +408,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
         desc: "use of a `~[T]` vector",
         default: allow,
     }),
+
+    ("raw_pointer_deriving",
+     LintSpec {
+        lint: RawPointerDeriving,
+        desc: "uses of #[deriving] with raw pointers are rarely correct",
+        default: warn,
+    }),
 ];
 
 /*
@@ -959,6 +968,37 @@ fn check_heap_item(cx: &Context, it: &ast::Item) {
     }
 }
 
+struct RawPtrDerivingVisitor<'a> {
+    cx: &'a Context<'a>
+}
+
+impl<'a> Visitor<()> for RawPtrDerivingVisitor<'a> {
+    fn visit_ty(&mut self, ty: &ast::Ty, _: ()) {
+        static MSG: &'static str = "use of `#[deriving]` with a raw pointer";
+        match ty.node {
+            ast::TyPtr(..) => self.cx.span_lint(RawPointerDeriving, ty.span, MSG),
+            _ => {}
+        }
+        visit::walk_ty(self, ty, ());
+    }
+    // explicit override to a no-op to reduce code bloat
+    fn visit_expr(&mut self, _: &ast::Expr, _: ()) {}
+    fn visit_block(&mut self, _: &ast::Block, _: ()) {}
+}
+
+fn check_raw_ptr_deriving(cx: &Context, item: &ast::Item) {
+    if !attr::contains_name(item.attrs.as_slice(), "deriving") {
+        return
+    }
+    match item.node {
+        ast::ItemStruct(..) | ast::ItemEnum(..) => {
+            let mut visitor = RawPtrDerivingVisitor { cx: cx };
+            visit::walk_item(&mut visitor, item, ());
+        }
+        _ => {}
+    }
+}
+
 static crate_attrs: &'static [&'static str] = &[
     "crate_type", "feature", "no_start", "no_main", "no_std", "crate_id",
     "desc", "comment", "license", "copyright", // not used in rustc now
@@ -1585,6 +1625,7 @@ impl<'a> Visitor<()> for Context<'a> {
             check_heap_item(cx, it);
             check_missing_doc_item(cx, it);
             check_attrs_usage(cx, it.attrs.as_slice());
+            check_raw_ptr_deriving(cx, it);
 
             cx.visit_ids(|v| v.visit_item(it, ()));
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index cdc74f37327..7d6f44494cb 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -384,6 +384,7 @@ pub struct t_box_ {
 // alive, and using ty::get is unsafe when the ctxt is no longer alive.
 enum t_opaque {}
 
+#[allow(raw_pointer_deriving)]
 #[deriving(Clone, Eq, TotalEq, Hash)]
 pub struct t { priv inner: *t_opaque }
 
diff --git a/src/test/compile-fail/lint-raw-ptr-deriving.rs b/src/test/compile-fail/lint-raw-ptr-deriving.rs
new file mode 100644
index 00000000000..f58ccf2d498
--- /dev/null
+++ b/src/test/compile-fail/lint-raw-ptr-deriving.rs
@@ -0,0 +1,35 @@
+// Copyright 2013 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.
+
+#[feature(struct_variant)];
+#[allow(dead_code)];
+#[deny(raw_pointer_deriving)];
+
+#[deriving(Clone)]
+struct Foo {
+    x: *int //~ ERROR use of `#[deriving]` with a raw pointer
+}
+
+#[deriving(Clone)]
+struct Bar(*mut int); //~ ERROR use of `#[deriving]` with a raw pointer
+
+#[deriving(Clone)]
+enum Baz {
+    A(*int), //~ ERROR use of `#[deriving]` with a raw pointer
+    B { x: *mut int } //~ ERROR use of `#[deriving]` with a raw pointer
+}
+
+#[deriving(Clone)]
+struct Buzz {
+    x: (*int, //~ ERROR use of `#[deriving]` with a raw pointer
+        *uint) //~ ERROR use of `#[deriving]` with a raw pointer
+}
+
+fn main() {}