about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-03-25 10:02:56 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-03-25 10:02:56 -0400
commit93e44432e1055a529c4923709a6533114bb7820f (patch)
tree23a62a5b51aae69e272ad041507c4874f232a72a
parent7f661ec417616ea7036f0cc4aefc7034592a3647 (diff)
downloadrust-93e44432e1055a529c4923709a6533114bb7820f.tar.gz
rust-93e44432e1055a529c4923709a6533114bb7820f.zip
check for both partialeq and eq
-rw-r--r--src/librustc/lint/builtin.rs2
-rw-r--r--src/librustc/middle/const_eval.rs2
-rw-r--r--src/libsyntax_ext/deriving/mod.rs81
-rw-r--r--src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs35
4 files changed, 82 insertions, 38 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 5d257fc7b2f..879b8945620 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -146,7 +146,7 @@ declare_lint! {
     pub ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
     Deny,
     "constants of struct or enum type can only be used in a pattern if \
-     the struct or enum has `#[derive(Eq)]`"
+     the struct or enum has `#[derive(PartialEq, Eq)]`"
 }
 
 declare_lint! {
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index dfeb5a5e3f1..c102822e8c1 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -345,7 +345,7 @@ pub fn const_expr_to_pat(tcx: &ty::TyCtxt, expr: &Expr, pat_id: ast::NodeId, spa
                     span,
                     format!("to use a constant of type `{}` \
                              in a pattern, \
-                             `{}` must be annotated with `#[derive(Eq)]`",
+                             `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
                             tcx.item_path_str(adt_def.did),
                             tcx.item_path_str(adt_def.did)));
             }
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index dbd3cbd4fba..1774167e830 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -92,6 +92,9 @@ fn expand_derive(cx: &mut ExtCtxt,
                 cx.span_warn(mitem.span, "empty trait list in `derive`");
             }
 
+            let mut found_partial_eq = false;
+            let mut found_eq = false;
+
             for titem in traits.iter().rev() {
                 let tname = match titem.node {
                     MetaItemKind::Word(ref tname) => tname,
@@ -110,43 +113,10 @@ fn expand_derive(cx: &mut ExtCtxt,
                     continue;
                 }
 
-                // RFC #1445. `#[derive(Eq)]` adds a (trusted)
-                // `#[structural_match]` attribute.
                 if &tname[..] == "Eq" {
-                    // This span is **very** sensitive and crucial to
-                    // getting the stability behavior we want. What we
-                    // are doing is marking `#[structural_match]` with
-                    // the span of the `#[deriving(Eq)]` attribute
-                    // (the entire attribute, not just the `Eq` part),
-                    // but with the current backtrace. The current
-                    // backtrace will contain a topmost entry that IS
-                    // this `#[deriving(Eq)]` attribute and with the
-                    // "allow-unstable" flag set to true.
-                    //
-                    // Note that we do NOT use the span of the `Eq`
-                    // text itself.  You might think this is
-                    // equivalent, because the `Eq` appears within the
-                    // `#[deriving(Eq)]` attribute, and hence we would
-                    // inherit the "allows unstable" from the
-                    // backtrace.  But in fact this is not always the
-                    // case. The actual source text that led to
-                    // deriving can be `#[$attr]`, for example, where
-                    // `$attr == deriving(Eq)`. In that case, the
-                    // "#[structural_match]" would be considered to
-                    // originate not from the deriving call but from
-                    // text outside the deriving call, and hence would
-                    // be forbidden from using unstable
-                    // content.
-                    //
-                    // See tests src/run-pass/rfc1445 for
-                    // examples. --nmatsakis
-                    let span = Span { expn_id: cx.backtrace(), .. span };
-                    assert!(cx.parse_sess.codemap().span_allows_unstable(span));
-                    debug!("inserting structural_match with span {:?}", span);
-                    let structural_match = intern_and_get_ident("structural_match");
-                    item.attrs.push(cx.attribute(span,
-                                                 cx.meta_word(span,
-                                                              structural_match)));
+                    found_eq = true;
+                } else if &tname[..] == "PartialEq" {
+                    found_partial_eq = true;
                 }
 
                 // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
@@ -154,6 +124,45 @@ fn expand_derive(cx: &mut ExtCtxt,
                     intern_and_get_ident(&format!("derive_{}", tname)))));
             }
 
+            // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
+            // `#[structural_match]` attribute.
+            if found_partial_eq && found_eq {
+                // This span is **very** sensitive and crucial to
+                // getting the stability behavior we want. What we are
+                // doing is marking `#[structural_match]` with the
+                // span of the `#[deriving(...)]` attribute (the
+                // entire attribute, not just the `PartialEq` or `Eq`
+                // part), but with the current backtrace. The current
+                // backtrace will contain a topmost entry that IS this
+                // `#[deriving(...)]` attribute and with the
+                // "allow-unstable" flag set to true.
+                //
+                // Note that we do NOT use the span of the `Eq`
+                // text itself. You might think this is
+                // equivalent, because the `Eq` appears within the
+                // `#[deriving(Eq)]` attribute, and hence we would
+                // inherit the "allows unstable" from the
+                // backtrace.  But in fact this is not always the
+                // case. The actual source text that led to
+                // deriving can be `#[$attr]`, for example, where
+                // `$attr == deriving(Eq)`. In that case, the
+                // "#[structural_match]" would be considered to
+                // originate not from the deriving call but from
+                // text outside the deriving call, and hence would
+                // be forbidden from using unstable
+                // content.
+                //
+                // See tests src/run-pass/rfc1445 for
+                // examples. --nmatsakis
+                let span = Span { expn_id: cx.backtrace(), .. span };
+                assert!(cx.parse_sess.codemap().span_allows_unstable(span));
+                debug!("inserting structural_match with span {:?}", span);
+                let structural_match = intern_and_get_ident("structural_match");
+                item.attrs.push(cx.attribute(span,
+                                             cx.meta_word(span,
+                                                          structural_match)));
+            }
+
             item
         })
     }, |a| {
diff --git a/src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs b/src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs
new file mode 100644
index 00000000000..029df08ebc3
--- /dev/null
+++ b/src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs
@@ -0,0 +1,35 @@
+// Copyright 2012 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)]
+#![deny(future_incompatible)]
+
+#[derive(Eq)]
+struct Foo {
+    x: u32
+}
+
+impl PartialEq for Foo {
+    fn eq(&self, _: &Foo) -> bool {
+        false // ha ha sucker!
+    }
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+    let y = Foo { x: 1 };
+    match y {
+        FOO => { }
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| WARNING will become a hard error
+        _ => { }
+    }
+}