Skip to content

Deriving options #8258

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/librustc/, \

LIBSYNTAX_CRATE := $(S)src/libsyntax/syntax.rs
LIBSYNTAX_INPUTS := $(wildcard $(addprefix $(S)src/libsyntax/, \
*.rs */*.rs */*/*.rs))
*.rs */*.rs */*/*.rs */*/*/*.rs))

DRIVER_CRATE := $(S)src/driver/driver.rs

Expand Down
34 changes: 34 additions & 0 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -1667,6 +1667,40 @@ Supported traits for `deriving` are:
each constituent field of the type must also implement `ToStr` and will have
`field.to_str()` invoked to build up the result.

#### Derived comparison options

The `deriving` instances of `Eq`, `TotalEq`, `Ord`, `TotalOrd` all
support some options that allow control of their behaviour when used
on structs. These are specified as follows:

~~~
#[deriving(Eq(test_order(d, c), ignore(b)),
TotalEq(test_order(c)),
Ord(reverse(a, c)),
TotalOrd(reverse(a, c)))]
struct Options {
a: float,
b: int,
c: uint,
d: uint
}
~~~

* `test_order` prioritizes the fields listed, testing them first, in
the order in which they are listed. That is, the `Eq` instance for
`Options` will test `d`, and then `c`, and then the remaining fields
(subject to `ignore`). All four traits support this.
* `ignore` excludes the given field from the comparison, so `Options {
.., b: 1, ..}` and `Options {.., b: 2, .. }` are equal if the rest
of the fields are equal (that is, despite `b` being different). Only
`Eq` and `Ord` support `ignore`.
* `reverse` flips the ordering used for that field, so `Options { a:
10.0, ... } < Options { a: 0.0, .. }`. Only `Ord` and `TotalOrd`
support `reverse`.

Using an option not listed here is an error. These options are only
supported on normal structs, not on tuple-structs or enums.

# Statements and expressions

Rust is _primarily_ an expression language. This means that most forms of
Expand Down
12 changes: 12 additions & 0 deletions src/libstd/borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,15 @@ impl<'self, T: Ord> Ord for &'self T {
*(*self) > *(*other)
}
}

#[cfg(not(test))]
impl<'self, T: TotalOrd> TotalOrd for &'self T {
#[inline]
fn cmp(&self, other: & &'self T) -> Ordering { (**self).cmp(*other) }
}

#[cfg(not(test))]
impl<'self, T: TotalEq> TotalEq for &'self T {
#[inline]
fn equals(&self, other: & &'self T) -> bool { (**self).equals(*other) }
}
1 change: 0 additions & 1 deletion src/libstd/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ pub fn cmp2<A:TotalOrd,B:TotalOrd>(
Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the
lexical ordering on a type `(int, int)`.
*/
// used in deriving code in libsyntax
#[inline]
pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
match o1 {
Expand Down
25 changes: 24 additions & 1 deletion src/libstd/managed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

use ptr::to_unsafe_ptr;

#[cfg(not(test))] use cmp::{Eq, Ord};
#[cfg(not(test))] use cmp::*;

pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
pub static RC_IMMORTAL : uint = 0x77777777;
Expand Down Expand Up @@ -71,6 +71,29 @@ impl<T:Ord> Ord for @mut T {
fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) }
}

#[cfg(not(test))]
impl<T: TotalOrd> TotalOrd for @T {
#[inline]
fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) }
}

#[cfg(not(test))]
impl<T: TotalOrd> TotalOrd for @mut T {
#[inline]
fn cmp(&self, other: &@mut T) -> Ordering { (**self).cmp(*other) }
}

#[cfg(not(test))]
impl<T: TotalEq> TotalEq for @T {
#[inline]
fn equals(&self, other: &@T) -> bool { (**self).equals(*other) }
}

#[cfg(not(test))]
impl<T: TotalEq> TotalEq for @mut T {
#[inline]
fn equals(&self, other: &@mut T) -> bool { (**self).equals(*other) }
}
#[test]
fn test() {
let x = @3;
Expand Down
14 changes: 13 additions & 1 deletion src/libstd/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

//! Operations on unique pointer types

#[cfg(not(test))] use cmp::{Eq, Ord};
#[cfg(not(test))] use cmp::*;

#[cfg(not(test))]
impl<T:Eq> Eq for ~T {
Expand All @@ -31,3 +31,15 @@ impl<T:Ord> Ord for ~T {
#[inline]
fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) }
}

#[cfg(not(test))]
impl<T: TotalOrd> TotalOrd for ~T {
#[inline]
fn cmp(&self, other: &~T) -> Ordering { (**self).cmp(*other) }
}

#[cfg(not(test))]
impl<T: TotalEq> TotalEq for ~T {
#[inline]
fn equals(&self, other: &~T) -> bool { (**self).equals(*other) }
}
4 changes: 4 additions & 0 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@ impl ExtCtxt {
self.print_backtrace();
self.parse_sess.span_diagnostic.span_warn(sp, msg);
}
pub fn span_note(&self, sp: span, msg: &str) {
self.print_backtrace();
self.parse_sess.span_diagnostic.span_note(sp, msg);
}
pub fn span_unimpl(&self, sp: span, msg: &str) -> ! {
self.print_backtrace();
self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
Expand Down
7 changes: 7 additions & 0 deletions src/libsyntax/ext/deriving/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ use codemap::span;
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
use ext::deriving::DerivingOptions;

pub fn expand_deriving_clone(cx: @ExtCtxt,
span: span,
options: DerivingOptions,
mitem: @MetaItem,
in_items: ~[@item])
-> ~[@item] {
options.unused_options_maybe_error(cx, span, "Clone");

let trait_def = TraitDef {
path: Path::new(~["std", "clone", "Clone"]),
additional_bounds: ~[],
Expand All @@ -41,9 +45,12 @@ pub fn expand_deriving_clone(cx: @ExtCtxt,

pub fn expand_deriving_deep_clone(cx: @ExtCtxt,
span: span,
options: DerivingOptions,
mitem: @MetaItem,
in_items: ~[@item])
-> ~[@item] {
options.unused_options_maybe_error(cx, span, "DeepClone");

let trait_def = TraitDef {
path: Path::new(~["std", "clone", "DeepClone"]),
additional_bounds: ~[],
Expand Down
20 changes: 15 additions & 5 deletions src/libsyntax/ext/deriving/cmp/eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,44 @@ use codemap::span;
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
use ext::deriving::DerivingOptions;
use ext::deriving::cmp::CmpOptions;

pub fn expand_deriving_eq(cx: @ExtCtxt,
span: span,
options: DerivingOptions,
mitem: @MetaItem,
in_items: ~[@item]) -> ~[@item] {
let mut options = match CmpOptions::parse(cx, span, "Eq", options, true, false) {
Some(o) => o,
None => return in_items
};

// structures are equal if all fields are equal, and non equal, if
// any fields are not equal or if the enum variants are different
fn cs_eq(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
cs_and(|cx, span, _, _| cx.expr_bool(span, false),
cx, span, substr)
cx, span, substr)
}
fn cs_ne(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
cs_or(|cx, span, _, _| cx.expr_bool(span, true),
cx, span, substr)
}

macro_rules! md (
($name:expr, $f:ident) => {
($name:expr, $f:ident) => {{
MethodDef {
name: $name,
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: ~[borrowed_self()],
ret_ty: Literal(Path::new(~["bool"])),
const_nonmatching: true,
combine_substructure: $f
},
}
combine_substructure: |cx, span, substr| {
options.call_substructure(cx, span, substr, $f)
}
}
}}
);

let trait_def = TraitDef {
Expand Down
Loading