diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-01-22 13:07:05 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-22 13:07:05 +0000 |
commit | 2cce6b8919ce16acd37a7a203049a52925a7e295 (patch) | |
tree | 0ac934a218d9f65af25065aa4abe94976533cb4a /gcc/rust/backend/rust-compile-expr.cc | |
parent | 6c9e57efa5474cfe5d0440e1022ee3c4a8400199 (diff) | |
parent | ee794effe3b55d2aa8acc108fb36bd8d05672dfa (diff) | |
download | gcc-2cce6b8919ce16acd37a7a203049a52925a7e295.zip gcc-2cce6b8919ce16acd37a7a203049a52925a7e295.tar.gz gcc-2cce6b8919ce16acd37a7a203049a52925a7e295.tar.bz2 |
Merge #873
873: Method resolution should respect deref lang-items r=philberty a=philberty
Method resolution in rust must respect the autoderef cycle by calling into the deref lang items as required. This
allows for method resolution behind boxing for example. See below for an example gimple dump of two levels
of deref operator overloads. The commit message ee794effe3b55d2aa8acc108fb36bd8d05672dfa holds much
more detail on the changes in this patch.
```
void main ()
{
const struct bar;
const struct foo;
const i32 foobar;
try
{
bar.0 = 123;
foo.0 = &bar;
RUSTTMP.3 = <Foo as Deref>::deref<&Bar> (&foo);
RUSTTMP.5 = <&T as Deref>::deref<Bar> (RUSTTMP.3);
foobar = Bar::foobar (*RUSTTMP.5);
}
finally
{
bar = {CLOBBER};
foo = {CLOBBER};
}
}
```
Fixes #884
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.cc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 249 |
1 files changed, 91 insertions, 158 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 33237e5..c58d29d 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -23,7 +23,6 @@ #include "rust-hir-trait-resolve.h" #include "rust-hir-path-probe.h" #include "rust-hir-type-bounds.h" -#include "rust-hir-dot-operator.h" #include "rust-compile-pattern.h" #include "rust-constexpr.h" @@ -574,25 +573,9 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) expr.get_mappings ().get_hirid (), &adjustments); rust_assert (ok); - for (auto &adjustment : *adjustments) - { - switch (adjustment.get_type ()) - { - case Resolver::Adjustment::AdjustmentType::IMM_REF: - case Resolver::Adjustment::AdjustmentType::MUT_REF: - self = ctx->get_backend ()->address_expression ( - self, expr.get_receiver ()->get_locus ()); - break; - - case Resolver::Adjustment::AdjustmentType::DEREF_REF: - tree expected_type - = TyTyResolveCompile::compile (ctx, adjustment.get_expected ()); - self = ctx->get_backend ()->indirect_expression ( - expected_type, self, true, /* known_valid*/ - expr.get_receiver ()->get_locus ()); - break; - } - } + // apply adjustments for the fn call + self = resolve_adjustements (*adjustments, self, + expr.get_receiver ()->get_locus ()); std::vector<tree> args; args.push_back (self); // adjusted self @@ -737,11 +720,10 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref, if (resolved_item != nullptr) { if (!fntype->has_subsititions_defined ()) - return CompileInherentImplItem::Compile (receiver, resolved_item, ctx, - true); + return CompileInherentImplItem::Compile (resolved_item, ctx, true); - return CompileInherentImplItem::Compile (receiver, resolved_item, ctx, - true, fntype); + return CompileInherentImplItem::Compile (resolved_item, ctx, true, + fntype); } // it might be resolved to a trait item @@ -785,24 +767,20 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref, } else { - std::vector<Resolver::Adjustment> adjustments; - Resolver::PathProbeCandidate *candidate - = Resolver::MethodResolution::Select (candidates, root, adjustments); - // FIXME this will be a case to return error_mark_node, there is // an error scenario where a Trait Foo has a method Bar, but this // receiver does not implement this trait or has an incompatible // implementation and we should just return error_mark_node - rust_assert (candidate != nullptr); - rust_assert (candidate->is_impl_candidate ()); - HIR::ImplItem *impl_item = candidate->item.impl.impl_item; + rust_assert (candidates.size () == 1); + auto &candidate = candidates.at (0); + rust_assert (candidate.is_impl_candidate ()); + + HIR::ImplItem *impl_item = candidate.item.impl.impl_item; if (!fntype->has_subsititions_defined ()) - return CompileInherentImplItem::Compile (receiver, impl_item, ctx, - true); + return CompileInherentImplItem::Compile (impl_item, ctx, true); - return CompileInherentImplItem::Compile (receiver, impl_item, ctx, true, - fntype); + return CompileInherentImplItem::Compile (impl_item, ctx, true, fntype); } } @@ -868,29 +846,8 @@ CompileExpr::resolve_operator_overload ( expr.get_mappings ().get_hirid (), &adjustments); rust_assert (ok); - // FIXME refactor this out - tree self = lhs; - for (auto &adjustment : *adjustments) - { - switch (adjustment.get_type ()) - { - case Resolver::Adjustment::AdjustmentType::IMM_REF: - case Resolver::Adjustment::AdjustmentType::MUT_REF: - self - = ctx->get_backend ()->address_expression (self, - lhs_expr->get_locus ()); - break; - - case Resolver::Adjustment::AdjustmentType::DEREF_REF: - tree expected_type - = TyTyResolveCompile::compile (ctx, adjustment.get_expected ()); - self - = ctx->get_backend ()->indirect_expression (expected_type, self, - true, /* known_valid*/ - lhs_expr->get_locus ()); - break; - } - } + // apply adjustments for the fn call + tree self = resolve_adjustements (*adjustments, lhs, lhs_expr->get_locus ()); std::vector<tree> args; args.push_back (self); // adjusted self @@ -1221,106 +1178,82 @@ CompileExpr::array_copied_expr (Location expr_locus, expr_locus); } -// tree -// CompileExpr::array_copied_expr (Location expr_locus, tree array_type, -// HIR::ArrayElemsCopied &elems) -// { -// // create tmp for the result -// fncontext fnctx = ctx->peek_fn (); -// Location start_location = expr_locus; -// Location end_location = expr_locus; -// tree fndecl = fnctx.fndecl; -// tree enclosing_scope = ctx->peek_enclosing_scope (); - -// bool is_address_taken = false; -// tree result_var_stmt = nullptr; -// Bvariable *result -// = ctx->get_backend ()->temporary_variable (fnctx.fndecl, -// enclosing_scope, -// array_type, NULL, -// is_address_taken, expr_locus, -// &result_var_stmt); -// ctx->add_statement (result_var_stmt); - -// // get the compiled value -// tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), -// ctx); - -// // lets assign each index in the array -// TyTy::BaseType *capacity_tyty = nullptr; -// HirId capacity_ty_id -// = elems.get_num_copies_expr ()->get_mappings ().get_hirid (); -// bool ok = ctx->get_tyctx ()->lookup_type (capacity_ty_id, -// &capacity_tyty); rust_assert (ok); tree capacity_type = -// TyTyResolveCompile::compile (ctx, capacity_tyty); tree capacity_expr = -// CompileExpr::Compile (elems.get_num_copies_expr (), ctx); - -// // create a loop for this with assignments to array_index exprs -// tree index_type = capacity_type; -// Bvariable *idx -// = ctx->get_backend ()->temporary_variable (fnctx.fndecl, -// enclosing_scope, -// index_type, NULL, -// is_address_taken, expr_locus, -// &result_var_stmt); -// ctx->add_statement (result_var_stmt); - -// // set index to zero -// tree index_lvalue = error_mark_node; -// tree zero = build_int_cst (index_type, 0); -// tree index_assignment -// = ctx->get_backend ()->assignment_statement (fnctx.fndecl, -// index_lvalue, -// zero, expr_locus); -// ctx->add_statement (index_assignment); - -// // BEGIN loop block -// tree loop_body = ctx->get_backend ()->block (fndecl, enclosing_scope, {}, -// start_location, end_location); -// ctx->push_block (loop_body); - -// // loop predicate -// tree loop_predicate -// = fold_build2_loc (expr_locus.gcc_location (), GE_EXPR, -// boolean_type_node, -// ctx->get_backend ()->var_expression (idx, expr_locus), -// capacity_expr); -// tree exit_expr = fold_build1_loc (expr_locus.gcc_location (), EXIT_EXPR, -// void_type_node, loop_predicate); -// tree break_stmt -// = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr); -// ctx->add_statement (break_stmt); - -// // increment index -// tree increment -// = fold_build2_loc (expr_locus.gcc_location (), POSTINCREMENT_EXPR, -// index_type, -// ctx->get_backend ()->var_expression (idx, expr_locus), -// build_int_cst (index_type, 1)); - -// // create index_assess -// tree index_access = ctx->get_backend ()->array_index_expression ( -// ctx->get_backend ()->var_expression (result, expr_locus), increment, -// expr_locus); - -// // create assignment to index_access -// tree array_assignment -// = ctx->get_backend ()->assignment_statement (fnctx.fndecl, -// index_access, -// translated_expr, expr_locus); -// ctx->add_statement (array_assignment); - -// // END loop block -// ctx->pop_block (); - -// tree loop_expr = ctx->get_backend ()->loop_expression (loop_body, -// expr_locus); tree loop_stmt -// = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr); -// ctx->add_statement (loop_stmt); - -// // result is the tmp -// return ctx->get_backend ()->var_expression (result, expr_locus); -// } +tree +HIRCompileBase::resolve_adjustements ( + std::vector<Resolver::Adjustment> &adjustments, tree expression, + Location locus) +{ + tree e = expression; + for (auto &adjustment : adjustments) + { + switch (adjustment.get_type ()) + { + case Resolver::Adjustment::AdjustmentType::ERROR: + return error_mark_node; + + case Resolver::Adjustment::AdjustmentType::IMM_REF: + case Resolver::Adjustment::AdjustmentType::MUT_REF: + e = ctx->get_backend ()->address_expression (e, locus); + break; + + case Resolver::Adjustment::AdjustmentType::DEREF_REF: + e = resolve_deref_adjustment (adjustment, e, locus); + break; + } + } + + return e; +} + +tree +HIRCompileBase::resolve_deref_adjustment (Resolver::Adjustment &adjustment, + tree expression, Location locus) +{ + rust_assert (adjustment.is_deref_adjustment ()); + + tree expected_type + = TyTyResolveCompile::compile (ctx, adjustment.get_expected ()); + if (!adjustment.has_operator_overload ()) + { + return ctx->get_backend ()->indirect_expression (expected_type, + expression, + true, /* known_valid*/ + locus); + } + + TyTy::FnType *lookup = adjustment.get_deref_operator_fn (); + HIR::ImplItem *resolved_item = adjustment.get_deref_hir_item (); + + tree fn_address = error_mark_node; + if (!lookup->has_subsititions_defined ()) + fn_address = CompileInherentImplItem::Compile (resolved_item, ctx, true, + nullptr, true, locus); + else + fn_address = CompileInherentImplItem::Compile (resolved_item, ctx, true, + lookup, true, locus); + + // does it need a reference to call + tree adjusted_argument = expression; + bool needs_borrow = adjustment.get_deref_adjustment_type () + != Resolver::Adjustment::AdjustmentType::ERROR; + if (needs_borrow) + { + adjusted_argument + = ctx->get_backend ()->address_expression (expression, locus); + } + + // make the call + auto fncontext = ctx->peek_fn (); + tree deref_call + = ctx->get_backend ()->call_expression (fncontext.fndecl, fn_address, + {adjusted_argument}, nullptr, + locus); + + // do the indirect expression + return ctx->get_backend ()->indirect_expression (expected_type, deref_call, + true, /* known_valid*/ + locus); +} } // namespace Compile } // namespace Rust |