From ef4028cd8472edd3b898dc5a2ac353b82c6303f4 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 19 Dec 2024 16:43:49 +0000 Subject: 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 --- gcc/rust/backend/rust-compile-expr.cc | 28 ++++++++++++++-- gcc/rust/backend/rust-compile-expr.h | 4 ++- gcc/rust/hir/tree/rust-hir-expr.cc | 6 ++++ gcc/rust/hir/tree/rust-hir-expr.h | 2 ++ gcc/rust/typecheck/rust-hir-type-check-expr.cc | 27 +++++++++++++--- gcc/rust/typecheck/rust-hir-type-check-expr.h | 4 ++- gcc/rust/util/rust-lang-item.cc | 44 ++++++++++++++++++++++++++ gcc/rust/util/rust-lang-item.h | 5 +++ gcc/rust/util/rust-operators.h | 8 ++--- 9 files changed, 115 insertions(+), 13 deletions(-) (limited to 'gcc/rust') 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> (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> rhs_expr) + HIR::Expr &lhs_expr, tl::optional> 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> rhs_expr); + tl::optional> 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) : 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 Rust::LangItem::lang_items = {{ {"into_iter", Kind::INTOITER_INTOITER}, {"next", Kind::ITERATOR_NEXT}, + + {"eq", Kind::EQ}, + {"partial_ord", Kind::PARTIAL_ORD}, }}; tl::optional @@ -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 -- cgit v1.1