diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2016-03-25 10:02:56 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2016-03-25 10:02:56 -0400 |
| commit | 93e44432e1055a529c4923709a6533114bb7820f (patch) | |
| tree | 23a62a5b51aae69e272ad041507c4874f232a72a | |
| parent | 7f661ec417616ea7036f0cc4aefc7034592a3647 (diff) | |
| download | rust-93e44432e1055a529c4923709a6533114bb7820f.tar.gz rust-93e44432e1055a529c4923709a6533114bb7820f.zip | |
check for both partialeq and eq
| -rw-r--r-- | src/librustc/lint/builtin.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/const_eval.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/mod.rs | 81 | ||||
| -rw-r--r-- | src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs | 35 |
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 + _ => { } + } +} |
