diff options
author | Philip Herron <herron.philip@googlemail.com> | 2024-12-19 16:43:49 +0000 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2025-03-21 12:56:55 +0100 |
commit | ef4028cd8472edd3b898dc5a2ac353b82c6303f4 (patch) | |
tree | 2faa0162ab48ce84b2fda24bf471d85d5ae6bf0b /gcc/rust | |
parent | a362f8a7d78da919d3e8ad5d924109a3c1521131 (diff) | |
download | gcc-ef4028cd8472edd3b898dc5a2ac353b82c6303f4.zip gcc-ef4028cd8472edd3b898dc5a2ac353b82c6303f4.tar.gz gcc-ef4028cd8472edd3b898dc5a2ac353b82c6303f4.tar.bz2 |
gccrs: add support for lang_item eq and PartialEq trait
The Eq and Partial Ord are very similar to the operator overloads
we support for add/sub/etc... but they differ in that usually the
function call name matches the name of the lang item. This time
we need to have support to send in a new path for the method call
on the lang item we want instead of just the name of the lang item.
NOTE: this test case doesnt work correctly yet we need to support
the derive of partial eq on enums to generate the correct comparison
code for that.
Fixes Rust-GCC#3302
gcc/rust/ChangeLog:
* backend/rust-compile-expr.cc (CompileExpr::visit): handle partial_eq possible call
* backend/rust-compile-expr.h: handle case where lang item calls differ from name
* hir/tree/rust-hir-expr.cc (OperatorExprMeta::OperatorExprMeta): new helper
* hir/tree/rust-hir-expr.h: likewise
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): handle partial_eq
(TypeCheckExpr::resolve_operator_overload): likewise
* typecheck/rust-hir-type-check-expr.h: likewise
* util/rust-lang-item.cc (LangItem::ComparisonToLangItem): map comparison to lang item
(LangItem::ComparisonToSegment): likewise
* util/rust-lang-item.h: new lang items PartialOrd and Eq
* util/rust-operators.h (enum class): likewise
gcc/testsuite/ChangeLog:
* rust/compile/nr2/exclude: nr2 cant handle this
* rust/compile/cmp1.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 28 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 4 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.cc | 6 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.cc | 27 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 4 | ||||
-rw-r--r-- | gcc/rust/util/rust-lang-item.cc | 44 | ||||
-rw-r--r-- | gcc/rust/util/rust-lang-item.h | 5 | ||||
-rw-r--r-- | gcc/rust/util/rust-operators.h | 8 |
9 files changed, 115 insertions, 13 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index e0fb1da..900e080 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -279,6 +279,26 @@ CompileExpr::visit (HIR::ComparisonExpr &expr) auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); auto location = expr.get_locus (); + // this might be an operator overload situation lets check + TyTy::FnType *fntype; + bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( + expr.get_mappings ().get_hirid (), &fntype); + if (is_op_overload) + { + auto seg_name = LangItem::ComparisonToSegment (expr.get_expr_type ()); + auto segment = HIR::PathIdentSegment (seg_name); + auto lang_item_type + = LangItem::ComparisonToLangItem (expr.get_expr_type ()); + + rhs = address_expression (rhs, EXPR_LOCATION (rhs)); + + translated = resolve_operator_overload ( + lang_item_type, expr, lhs, rhs, expr.get_lhs (), + tl::optional<std::reference_wrapper<HIR::Expr>> (expr.get_rhs ()), + segment); + return; + } + translated = Backend::comparison_expression (op, lhs, rhs, location); } @@ -1478,7 +1498,8 @@ CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn, tree CompileExpr::resolve_operator_overload ( LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, tree lhs, tree rhs, - HIR::Expr &lhs_expr, tl::optional<std::reference_wrapper<HIR::Expr>> rhs_expr) + HIR::Expr &lhs_expr, tl::optional<std::reference_wrapper<HIR::Expr>> rhs_expr, + HIR::PathIdentSegment specified_segment) { TyTy::FnType *fntype; bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( @@ -1499,7 +1520,10 @@ CompileExpr::resolve_operator_overload ( } // lookup compiled functions since it may have already been compiled - HIR::PathIdentSegment segment_name (LangItem::ToString (lang_item_type)); + HIR::PathIdentSegment segment_name + = specified_segment.is_error () + ? HIR::PathIdentSegment (LangItem::ToString (lang_item_type)) + : specified_segment; tree fn_expr = resolve_method_address (fntype, receiver, expr.get_locus ()); // lookup the autoderef mappings diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index b8c4220..dc78dee 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -99,7 +99,9 @@ protected: tree resolve_operator_overload ( LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, tree lhs, tree rhs, HIR::Expr &lhs_expr, - tl::optional<std::reference_wrapper<HIR::Expr>> rhs_expr); + tl::optional<std::reference_wrapper<HIR::Expr>> rhs_expr, + HIR::PathIdentSegment specified_segment + = HIR::PathIdentSegment::create_error ()); tree compile_bool_literal (const HIR::LiteralExpr &expr, const TyTy::BaseType *tyty); diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc index 4a902c6..2ded789 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.cc +++ b/gcc/rust/hir/tree/rust-hir-expr.cc @@ -1298,6 +1298,12 @@ OperatorExprMeta::OperatorExprMeta (HIR::ArrayIndexExpr &expr) locus (expr.get_locus ()) {} +OperatorExprMeta::OperatorExprMeta (HIR::ComparisonExpr &expr) + : node_mappings (expr.get_mappings ()), + lvalue_mappings (expr.get_expr ().get_mappings ()), + locus (expr.get_locus ()) +{} + AnonConst::AnonConst (NodeId id, std::unique_ptr<Expr> expr) : id (id), expr (std::move (expr)) { diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 1273466..f8f2128 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2816,6 +2816,8 @@ public: OperatorExprMeta (HIR::ArrayIndexExpr &expr); + OperatorExprMeta (HIR::ComparisonExpr &expr); + const Analysis::NodeMapping &get_mappings () const { return node_mappings; } const Analysis::NodeMapping &get_lvalue_mappings () const diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 2ea8b41..7899b1a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -344,6 +344,21 @@ TypeCheckExpr::visit (HIR::ComparisonExpr &expr) auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto borrowed_rhs + = new TyTy::ReferenceType (mappings.get_next_hir_id (), + TyTy::TyVar (rhs->get_ref ()), Mutability::Imm); + context->insert_implicit_type (borrowed_rhs->get_ref (), borrowed_rhs); + + auto seg_name = LangItem::ComparisonToSegment (expr.get_expr_type ()); + auto segment = HIR::PathIdentSegment (seg_name); + auto lang_item_type = LangItem::ComparisonToLangItem (expr.get_expr_type ()); + + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, lhs, borrowed_rhs, + segment); + if (operator_overloaded) + return; + unify_site (expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()), TyTy::TyWithLocation (rhs, expr.get_rhs ().get_locus ()), @@ -1640,10 +1655,10 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr) } bool -TypeCheckExpr::resolve_operator_overload (LangItem::Kind lang_item_type, - HIR::OperatorExprMeta expr, - TyTy::BaseType *lhs, - TyTy::BaseType *rhs) +TypeCheckExpr::resolve_operator_overload ( + LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, + TyTy::BaseType *lhs, TyTy::BaseType *rhs, + HIR::PathIdentSegment specified_segment) { // look up lang item for arithmetic type std::string associated_item_name = LangItem::ToString (lang_item_type); @@ -1661,7 +1676,9 @@ TypeCheckExpr::resolve_operator_overload (LangItem::Kind lang_item_type, current_context = context->peek_context (); } - auto segment = HIR::PathIdentSegment (associated_item_name); + auto segment = specified_segment.is_error () + ? HIR::PathIdentSegment (associated_item_name) + : specified_segment; auto candidates = MethodResolver::Probe (lhs, segment); // remove any recursive candidates diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 82f421e..2a0022c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -97,7 +97,9 @@ public: protected: bool resolve_operator_overload (LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, - TyTy::BaseType *lhs, TyTy::BaseType *rhs); + TyTy::BaseType *lhs, TyTy::BaseType *rhs, + HIR::PathIdentSegment specified_segment + = HIR::PathIdentSegment::create_error ()); bool resolve_fn_trait_call (HIR::CallExpr &expr, TyTy::BaseType *function_tyty, diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc index c4c1d1c..4a60909 100644 --- a/gcc/rust/util/rust-lang-item.cc +++ b/gcc/rust/util/rust-lang-item.cc @@ -98,6 +98,9 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{ {"into_iter", Kind::INTOITER_INTOITER}, {"next", Kind::ITERATOR_NEXT}, + + {"eq", Kind::EQ}, + {"partial_ord", Kind::PARTIAL_ORD}, }}; tl::optional<LangItem::Kind> @@ -146,6 +149,47 @@ LangItem::OperatorToLangItem (ArithmeticOrLogicalOperator op) } LangItem::Kind +LangItem::ComparisonToLangItem (ComparisonOperator op) +{ + switch (op) + { + case ComparisonOperator::NOT_EQUAL: + case ComparisonOperator::EQUAL: + return LangItem::Kind::EQ; + + case ComparisonOperator::GREATER_THAN: + case ComparisonOperator::LESS_THAN: + case ComparisonOperator::GREATER_OR_EQUAL: + case ComparisonOperator::LESS_OR_EQUAL: + return LangItem::Kind::PARTIAL_ORD; + } + + rust_unreachable (); +} + +std::string +LangItem::ComparisonToSegment (ComparisonOperator op) +{ + switch (op) + { + case ComparisonOperator::NOT_EQUAL: + return "ne"; + case ComparisonOperator::EQUAL: + return "eq"; + case ComparisonOperator::GREATER_THAN: + return "gt"; + case ComparisonOperator::LESS_THAN: + return "lt"; + case ComparisonOperator::GREATER_OR_EQUAL: + return "ge"; + case ComparisonOperator::LESS_OR_EQUAL: + return "le"; + } + + rust_unreachable (); +} + +LangItem::Kind LangItem::CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op) { switch (op) diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h index 9e432e2..62b15d7 100644 --- a/gcc/rust/util/rust-lang-item.h +++ b/gcc/rust/util/rust-lang-item.h @@ -45,6 +45,8 @@ public: NEGATION, NOT, + EQ, + PARTIAL_ORD, ADD_ASSIGN, SUB_ASSIGN, @@ -136,6 +138,9 @@ public: static Kind CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op); static Kind NegationOperatorToLangItem (NegationOperator op); + static Kind ComparisonToLangItem (ComparisonOperator op); + + static std::string ComparisonToSegment (ComparisonOperator op); }; } // namespace Rust diff --git a/gcc/rust/util/rust-operators.h b/gcc/rust/util/rust-operators.h index 608e771..02b1820 100644 --- a/gcc/rust/util/rust-operators.h +++ b/gcc/rust/util/rust-operators.h @@ -43,10 +43,10 @@ enum class ComparisonOperator { EQUAL, // std::cmp::PartialEq::eq NOT_EQUAL, // std::cmp::PartialEq::ne - GREATER_THAN, // std::cmp::PartialEq::gt - LESS_THAN, // std::cmp::PartialEq::lt - GREATER_OR_EQUAL, // std::cmp::PartialEq::ge - LESS_OR_EQUAL // std::cmp::PartialEq::le + GREATER_THAN, // std::cmp::PartialOrd::gt + LESS_THAN, // std::cmp::PartialOrd::lt + GREATER_OR_EQUAL, // std::cmp::PartialOrd::ge + LESS_OR_EQUAL // std::cmp::PartialOrd::le }; enum class LazyBooleanOperator |