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

derive(PartialEq): Add partial implementation (hehe) #3415

Merged
merged 9 commits into from
Feb 20, 2025

Conversation

CohenArthur
Copy link
Member

@CohenArthur CohenArthur commented Feb 4, 2025

Fixes #2992

This adds a base for deriving PartialEq and Eq but misses some more complex stuff like struct enum items, as we need to add more to our nameres and codegen to handle these rebinding patterns.

We also need to rework this part of the expansion pass as derive(Eq) and derive(PartialEq) should both create two impls: one of their trait, and one of the associated Structural* trait this is now done in this PR.

This is ready for reviewing and merging IMO as a first basic implementation of derive(PartialEq) even if it does not support all types of Rust enums

@CohenArthur CohenArthur force-pushed the derive-partialeq-eq branch 4 times, most recently from 7243ef7 to d50fc0c Compare February 4, 2025 15:14
@P-E-P P-E-P self-requested a review February 5, 2025 14:11
@CohenArthur CohenArthur force-pushed the derive-partialeq-eq branch 2 times, most recently from b9c5bdf to 741e633 Compare February 6, 2025 10:07
std::unique_ptr<Expr>
Builder::literal_bool (bool b) const
{
auto str = b ? "true" : "false";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use the keyword value from rust-keyword-values.h.

std::unique_ptr<AssociatedItem> &&fn, std::string name,
const std::vector<std::unique_ptr<GenericParam>> &type_generics)
{
auto eq = builder.type_path ({"core", "cmp", "Eq"}, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make this path (or individual segments) available globally like weak keywords ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's important here as this is only used when generating code, which isn't done too often. we rarely repeat paths, and making individual segments available doesn't really help a lot I feel

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also probably create two type paths here, one for creating eq_impl and one for creating eq_generics -- otherwise, two AST nodes sharing the same node id throws the 2.0 name resolver for a loop

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking it might be best to just ignore duplicate map_usage calls, as long as one usage is only ever mapped to one definition, in which case my previous suggestion can be ignored

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's probably cleaner to have different node IDs for different nodes even if it makes the derive code very slightly messier

// nothing to do as they contain no inner types
continue;
case EnumItem::Kind::Tuple: {
auto tuple = static_cast<EnumItemTuple &> (*variant);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to avoid the copy here auto &tuple = static_cast<EnumItemTuple &> (*variant);.

break;
}
case EnumItem::Kind::Struct: {
auto tuple = static_cast<EnumItemStruct &> (*variant);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise.

@@ -0,0 +1,313 @@
// Copyright (C) 2020-2024 Free Software Foundation, Inc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date range is incorrect, should be 2025 instead of 2020-2024.

DeriveEq::assert_param_is_eq ()
{
auto eq_bound = std::unique_ptr<TypeParamBound> (
new TraitBound (builder.type_path ({"core", "cmp", "Eq"}, true), loc));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a lang item path?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, Eq isn't a lang item in 1.49:

#[doc(alias = "==")]
#[doc(alias = "!=")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Eq: PartialEq<Self> {
    // this method is used solely by #[deriving] to assert
    // that every component of a type implements #[deriving]
    // itself, the current deriving infrastructure means doing this
    // assertion without using a method on this trait is nearly
    // impossible.
    //
    // This should never be implemented by hand.
    #[doc(hidden)]
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn assert_receiver_is_total_eq(&self) {}
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dang

issue-3402-1.rs
for-loop1.rs
for-loop2.rs
issue-3403.rs
derive-default1.rs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessary move

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, that's merge conflicts when rebasing - thanks for catching it, I'll fix it

gcc/rust/ChangeLog:

	* expand/rust-derive.cc (DeriveVisitor::derive): Call into DeriveEq.
	* expand/rust-derive-eq.cc: New file.
	* expand/rust-derive-eq.h: New file.
	* Make-lang.in: Compile them.

gcc/testsuite/ChangeLog:

	* rust/compile/derive-eq-invalid.rs: New test.
gcc/rust/ChangeLog:

	* ast/rust-ast-builder.cc (Builder::block): Change return type.
	(Builder::loop): Use new APIs.
	* ast/rust-ast-builder.h: Change return type of block functions.
gcc/rust/ChangeLog:

	* ast/rust-ast-builder.cc (Builder::literal_bool): New method.
	(Builder::comparison_expr): Likewise.
	(Builder::boolean_operation): Likewise.
	* ast/rust-ast-builder.h: Declare them.
gcc/rust/ChangeLog:

	* expand/rust-derive-clone.cc: Cleanup implementation, avoid repetitions.
	* expand/rust-derive-clone.h: Likewise.
We are still missing some deriving for enums, as part of our codegen and nameres for rebinding struct
field patterns is missing.

gcc/rust/ChangeLog:

	* expand/rust-derive-partial-eq.cc: New file.
	* expand/rust-derive-partial-eq.h: New file.
	* expand/rust-derive.cc (DeriveVisitor::derive): Call them.
	* Make-lang.in: Compile them.

gcc/testsuite/ChangeLog:

	* rust/compile/derive-eq-invalid.rs: Mark PartialEq def as a lang item.
	* rust/compile/derive-partialeq1.rs: New test.
	* rust/execute/torture/derive-partialeq1.rs: New test.
	* rust/compile/nr2/exclude: Exclude all of them.
gcc/rust/ChangeLog:

	* expand/rust-derive.cc (DeriveVisitor::derive): Return a vector of items.
	* expand/rust-derive.h: Change return type.
	* expand/rust-expand-visitor.cc: Insert all generated items into the AST.
gcc/rust/ChangeLog:

	* expand/rust-derive-partial-eq.cc: Adapt signatures to generate two impls.
	* expand/rust-derive-partial-eq.h: Likewise.
	* expand/rust-derive.cc (DeriveVisitor::derive): Adapt to multiple item generation.

gcc/testsuite/ChangeLog:

	* rust/compile/derive-eq-invalid.rs: Declare StructuralPartialEq.
	* rust/compile/derive-partialeq1.rs: Likewise.
	* rust/execute/torture/derive-partialeq1.rs: Likewise.
gcc/rust/ChangeLog:

	* expand/rust-derive-eq.cc: Adapt functions to return two generated impls.
	* expand/rust-derive-eq.h: Likewise.
	* expand/rust-derive.cc (DeriveVisitor::derive): Likewise.
gcc/rust/ChangeLog:

	* expand/rust-derive-eq.cc: Copy `Eq` typepath.
@CohenArthur CohenArthur added this pull request to the merge queue Feb 20, 2025
Merged via the queue into Rust-GCC:master with commit 35afe39 Feb 20, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Eq
3 participants