Change derive macro for Eq to not impl Eq trait fn#153125
Change derive macro for Eq to not impl Eq trait fn#153125KiChjang wants to merge 6 commits intorust-lang:mainfrom
Conversation
|
Changes to the code generated for builtin derived traits. cc @nnethercote |
This comment has been minimized.
This comment has been minimized.
|
A test case that seems like might break with this: trait Trait<T> {}
#[derive(PartialEq, Eq)]
struct Thing<T: Trait<Self>>(T); |
|
A less exotic test case: #[derive(PartialEq, Eq)]
struct Thing(Option<Box<Self>>); |
|
Nick, I would reassign to you (feel free to reroll) since @cyrgani is a triage member and can't approve compiler changes r? nnethercote |
Gah, because we're now generating a const item instead of a trait impl block, we'd need to rewrite the A better solution now would be to emit the following: impl<...> Type<...> {
const fn assert_fields_are_eq() {
let _: ::core::cmp::AssertParamIsEq<Option<Box<Self>>>;
}
}This would side-step the issue of rewriting |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Looks like CI is passing now, r? @nnethercote |
|
Requested reviewer is already assigned to this pull request. Please choose another assignee. |
|
You should be able to delete the |
|
Could you also add a test that something like fn main() {
X::assert_fields_are_eq();
}
#[derive(PartialEq, Eq)]
struct X(u8);will not compile? |
There was a problem hiding this comment.
This is now completely different to the original idea of using a const. I'm no lang expert, but injecting X::assert_fields_are_eq doesn't seem acceptable to me.
Beyond that, I've only skimmed the PR so far. I think the 8 commits should be squashed down to 1 or 2. I'm also surprised at how much extra code is required in eq.rs to generate a slight variation on what is currently generated.
This probably would still compile, since what I essentially did was move the trait method to be under an inherent impl instead, which is probably why it isn't desirable. Given so, I'd probably need to revert to the original idea of using a const item block, however the const fn would still have to stay the same because I'd still need to somehow bring all lifetime/type parameters into scope, and if we don't use an impl, then a fn is the minimal vehicle to do so. |
That's right. Currently we have a hidden method in |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Did you explore what I wrote briefly in #149978 (comment), to do something like:
#[derive(PartialEq, Eq)]
pub struct A<'a, T> {
field1: &'a [T],
field2: Option<Box<Self>>,
}
// Generates
const _: () = {
struct __AssertIsEq<'a, T: core::eq::Eq> {
field1: core::eq::AssertParamIsEq<&'a [T]>,
field2: core::eq::AssertParamIsEq<Option<Box<Self>>>,
}
impl<'a, T: core::eq::PartialEq> PartialEq for __AssertIsEq<'a, T> {
#[inline]
fn eq(&self, other: &Self) -> bool { unimplemented!() }
}
impl<'a, T: core::eq::Eq> Eq for __AssertIsEq<'a, T> {}
};Also, this is apparently perf-sensitive, please remember to do a perf-run before merging.
32d0739 to
c9cc7ea
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
c9cc7ea to
b5a6295
Compare
|
@bors try @rust-timer queue |
|
@KiChjang: 🔑 Insufficient privileges: not in try users |
|
Insufficient permissions to issue commands to rust-timer. |
This seems to emit quite a lot of boilerplate for the purpose of making sure that Would appreciate some help in putting this on the timer queue though as I don't have sufficient permissions. |
| impl ::core::cmp::Eq for PackedPoint { | ||
| #[inline] | ||
| impl ::core::cmp::Eq for PackedPoint { } | ||
| const { |
There was a problem hiding this comment.
This isn't even valid syntax, it should be const _: () = {.
There was a problem hiding this comment.
This is the code that gets generated when I tell the compiler to emit a ast::ItemKind::ConstBlock:
rust/compiler/rustc_ast/src/ast.rs
Lines 3955 to 3959 in 8d50bcc
There was a problem hiding this comment.
Weird. Maybe a pretty printing issue? Would be good to understand what's happening here.
This comment has been minimized.
This comment has been minimized.
c694584 to
602529d
Compare
602529d to
c70ca54
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| mut_visit::walk_ty(self, ty); | ||
| } | ||
| } | ||
| fn visit_expr(&mut self, expr: &mut ast::Expr) { |
There was a problem hiding this comment.
Please put blank lines between the methods, here and elsewhere.
| use crate::deriving::generic::*; | ||
| use crate::deriving::path_std; | ||
|
|
||
| struct ReplaceSelfTyVisitor(Box<ast::Ty>); |
There was a problem hiding this comment.
Blank line after the struct, and likewise below.
There was a problem hiding this comment.
Also, the three visitors need a brief comment explaining what they are doing and why.
| span, | ||
| }; | ||
|
|
||
| cx.item( |
There was a problem hiding this comment.
A brief example of the kind of code being generated would be helpful here.
| #[coverage(off)] | ||
| fn assert_fields_are_eq(&self) { | ||
| #[inline] | ||
| const fn assert_fields_are_eq(_: *const Point) { |
There was a problem hiding this comment.
I assume the parameter to assert_fields_are_eq is necessary in the generic case to make the trait bounds work? But could the parameter be avoided for non-generic functions like this one?
There was a problem hiding this comment.
Also, why is the parameter (when present) *const T? Could it just be T?
There was a problem hiding this comment.
Also, why is the parameter (when present)
*const T? Could it just beT?
Probably to work with ?Sized types?
There was a problem hiding this comment.
Another option to make it work properly with Self, while not doing an inherent method:
Add an extra trait with the method on it instead.
// `#[doc(hidden)]` trait (and unstable if we can?)
impl ::core::cmp::EqHelperTrait for $ty {
#[inline]
fn assert_fields_are_eq() {
let _: ::core::cmp::AssertParamIsEq<$param1>;
let _: ::core::cmp::AssertParamIsEq<$param2>;
// ...
}
}| const LEN: usize = 10; | ||
| } | ||
|
|
||
| // An empty enum. |
There was a problem hiding this comment.
Please add a test case like this:
macro_rules! get_self {
() => {
Self
};
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
struct SelfFromMacro {
this: Option<Box<get_self!()>>
}(I'm commenting this specifically because I think that any solution that matches on the token Self isn't gonna work).
View all comments
Fixes #152504.
r? @cyrgani