Skip to content
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

Implement Eq for Cell and RefCell. #25744

Merged
merged 1 commit into from
May 28, 2015
Merged

Conversation

SimonSapin
Copy link
Contributor

core::cell::Cell<T> and core::cell::RefCell<T> currently implement PartialEq when T does, and just defer to comparing T values. There is no reason the same shouldn’t apply to Eq.

This enables #[derive(Eq, PartialEq)] on e.g. structs that have a RefCell field.

r? @alexcrichton

I’m unsure what to do with #[stable] attributes on impls. impls generated by #[derive] don’t have them.

`core::cell::Cell<T>` and `core::cell::RefCell<T>` currently implement
`PartialEq` when `T` does, and just defer to comparing `T` values.
There is no reason the same shouldn’t apply to `Eq`.

This enables `#[derive(Eq, PartialEq)]` on e.g.
structs that have a `RefCell` field.
@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. The way Github handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see CONTRIBUTING.md for more information.

@tbu-
Copy link
Contributor

tbu- commented May 25, 2015

There might be a reason why RefCell does not implement Eq, namely that x == x may panic instead of returning true.

@SimonSapin
Copy link
Contributor Author

@tbu- I don’t understand how that’s more of a problem for Eq than for PartialEq.

@tbu-
Copy link
Contributor

tbu- commented May 25, 2015

@SimonSapin Eq guarantees that x == x returns true, which is not true in all cases for RefCell.

@SimonSapin
Copy link
Contributor Author

It’s not clear to me that “don’t panic” is a promise that Eq makes.

@tbu-
Copy link
Contributor

tbu- commented May 25, 2015

Well, it'd be useful for HashMaps. Maybe Eq needs to be clarified.

@SimonSapin
Copy link
Contributor Author

Anyway, here is how I came to this:

  • I tried using assert_eq! in some tests, which failed because one of my structs was not comparable.
  • I went to add #[derive(PartialEq)] on my struct, and while I was at it also added Eq because I didn’t see a reason not to.
  • This failed because my struct contains a RefCell, which does not implement Eq
  • I didn’t see a reason for me not to other than maybe no one thought of it yet, so I sent this PR.

If there is a good reason not to implement Eq, feel free to close this PR. I don’t really need it, PartialEq is enough for assert_eq!.

@alexcrichton
Copy link
Member

I think that the Cell implementation of Eq is fine (just forgotten), but I agree with @tbu- that the implementation for RefCell gives me a moment of pause. I definitely don't consider it a part of the contract of Eq, however, that the implementation does not panic (this isn't mentioned at all in the documentation for one), so in that sense I think that this is fine. I feel that this is such a core primitive type that we need to make it as ergonomic as possible to use, which entails implementing all of these core traits (including those that may panic).

cc @rust-lang/libs, do others have a strong opinion one way or another about this?

@alexcrichton alexcrichton added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label May 26, 2015
@BurntSushi
Copy link
Member

I'm looking over the existing impls for Eq, and I don't think I see any that could cause panics. So setting a precedent also gives me pause. That said, panic'ing is not part of the contract for either PartialEq or Eq, so I'd be fine with it.

@Kimundi
Copy link
Member

Kimundi commented May 26, 2015

I remember that RefCell did not implement any traits that require it to borrow its content at some point due to the panic issue. But if it already implements PartialEq, then that ship has probably sailed and we should go for feature parity with other libstd types.

@shepmaster
Copy link
Member

See also #16714, #19388

@sfackler
Copy link
Member

The PartialEq impl has existed since the introduction of RefCell in #10514 (oops).

We could either treat it as "this should have never existed, and we're not going to add any more delegating trait implementations", or decide that it's fine, in which case we should probably add on impls of PartialOrd, Ord etc in addition to Eq. I'd kind of lean towards the former personally.

@aturon
Copy link
Member

aturon commented May 28, 2015

I consider the Eq contract to be that x == x should never return false, but panicking seems like fair game. Similarly with Ord, the main point here is to avoid getting results that can screw up data structure invariants, but a panic isn't likely to do that (though it may raise exception safety issues, but these are mainly a concern for unsafe code and have to be considered regardless.)

So, I'm +1 for adding these impls.

@alexcrichton
Copy link
Member

@sfackler in the past we've found that omitting implementations of core traits from core types (e.g. Debug from Path) ended up causing more pain than it was worth, so I'm curious, could you elaborate more on why you think we shouldn't do this?

@sfackler
Copy link
Member

I'm a bit leery in general of invisible sources of panics.

@alexcrichton
Copy link
Member

True, although technically this PR introduces 0 extra panics because Eq has no methods internally (e.g. the panics only come from RefCell::eq)

@Gankra
Copy link
Contributor

Gankra commented May 28, 2015

fwiw unsafe code already needs to guard against this sort of thing because "you never know". As such adding this is basically a "no-lose" scenario to me.

@tbu-
Copy link
Contributor

tbu- commented May 28, 2015

@gankro I don't think @sfackler ment this as part of unsafe code, invisible panics are always bad for program correctness.

@alexcrichton
Copy link
Member

@bors: r+ bbf8ba7

@bors
Copy link
Contributor

bors commented May 28, 2015

⌛ Testing commit bbf8ba7 with merge 53941be...

bors added a commit that referenced this pull request May 28, 2015
`core::cell::Cell<T>` and `core::cell::RefCell<T>` currently implement `PartialEq` when `T` does, and just defer to comparing `T` values. There is no reason the same shouldn’t apply to `Eq`.

This enables `#[derive(Eq, PartialEq)]` on e.g. structs that have a `RefCell` field.

r? @alexcrichton 

I’m unsure what to do with `#[stable]` attributes on `impl`s. `impl`s generated by `#[derive]` don’t have them.
@bors bors merged commit bbf8ba7 into rust-lang:master May 28, 2015
@SimonSapin SimonSapin deleted the cell-eq branch June 5, 2015 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.