From 1a157cdd26044f767b7fe0f09ffbf40fade97a8f Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Sat, 9 Mar 2024 18:30:27 +0530 Subject: [PATCH] borrowck: Resolve HIR::MethodCallExpr to BIR::CallExpr gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Implementation of resolving HIR::MethodCallExpr to BIR::CallExpr. (ExprStmtBuilder::visit_and_adjust): Function to visit `self` parameter and apply the required adjustments. * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Header for new helper function. * checks/errors/borrowck/rust-bir-builder-internal.h: New method for borrowing `self` parameter. gcc/testsuite/ChangeLog: * rust/borrowck/methods.rs: New test. Signed-off-by: Kushal Pal --- .../borrowck/rust-bir-builder-expr-stmt.cc | 61 ++++++++++++++++++- .../borrowck/rust-bir-builder-expr-stmt.h | 4 ++ .../borrowck/rust-bir-builder-internal.h | 12 ++++ gcc/testsuite/rust/borrowck/methods.rs | 38 ++++++++++++ 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/borrowck/methods.rs diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc index 81fa2ea7b043..4654219de0cf 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc @@ -21,6 +21,8 @@ #include "rust-bir-builder-lazyboolexpr.h" #include "rust-bir-builder-pattern.h" #include "rust-bir-builder-struct.h" +#include "rust-hir-path-probe.h" +#include "rust-type-util.h" namespace Rust { namespace BIR { @@ -281,7 +283,23 @@ ExprStmtBuilder::visit (HIR::CallExpr &expr) void ExprStmtBuilder::visit (HIR::MethodCallExpr &expr) -{} +{ + PlaceId self = visit_and_adjust (*expr.get_receiver ()); + auto *method_ty = lookup_type (expr.get_method_name ())->as (); + + std::vector arguments = visit_list (expr.get_arguments ()); + arguments.insert (arguments.begin (), self); + + // skip the first parameter (self) + for (size_t i = 1; i < method_ty->get_num_params (); ++i) + coercion_site (arguments[i], method_ty->get_param_type_at (i)); + + move_all (arguments); + + return_expr (new CallExpr (ctx.place_db.get_constant (method_ty), + std::move (arguments)), + lookup_type (expr), true); +} void ExprStmtBuilder::visit (HIR::FieldAccessExpr &expr) @@ -679,5 +697,46 @@ ExprStmtBuilder::visit (HIR::ExprStmt &stmt) if (result != INVALID_PLACE) push_tmp_assignment (result); } + +PlaceId +ExprStmtBuilder::visit_and_adjust (HIR::Expr &expr) +{ + PlaceId adjusted = visit_expr (expr); + + std::vector *adjustments = nullptr; + bool ok + = ctx.tyctx.lookup_autoderef_mappings (expr.get_mappings ().get_hirid (), + &adjustments); + rust_assert (ok); + + for (const auto &adjustment : *adjustments) + { + auto ty = ctx.place_db[adjusted].tyty; + + adjusted = [&] () { + using AdjustmentType = Resolver::Adjustment::AdjustmentType; + + switch (adjustment.get_type ()) + { + case AdjustmentType::IMM_REF: + return borrow_place (adjusted, Mutability::Imm); + case AdjustmentType::MUT_REF: + return borrow_place (adjusted, Mutability::Mut); + case AdjustmentType::DEREF: + case AdjustmentType::DEREF_MUT: + return ctx.place_db.lookup_or_add_path (Place::DEREF, ty, adjusted); + case AdjustmentType::ERROR: + case AdjustmentType::INDIRECTION: + case AdjustmentType::UNSIZE: + // FIXME: Are these adjustments needed for borrowchecker + return adjusted; + default: + rust_unreachable (); + } + }(); + } + return adjusted; +} + } // namespace BIR } // namespace Rust diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h index 1597ff291b01..72f9ee70fc40 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h @@ -54,6 +54,10 @@ class ExprStmtBuilder final : public AbstractExprBuilder, return result; } + // helper functions for method resolution + PlaceId + visit_and_adjust (HIR::Expr &expr); + /** Common infrastructure for loops. */ BuilderContext::LoopAndLabelCtx &setup_loop (HIR::BaseLoopExpr &expr); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index 2e2a7e2970a9..3fb01f52fb8f 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -311,6 +311,15 @@ class AbstractBuilder return translated; } + PlaceId borrow_place (PlaceId place_id, Mutability mutability) + { + auto ty = ctx.place_db[place_id].tyty; + return borrow_place (place_id, + new TyTy::ReferenceType (ty->get_ref (), + TyTy::TyVar (ty->get_ref ()), + mutability)); + } + PlaceId move_place (PlaceId arg) { auto &place = ctx.place_db[arg]; @@ -384,6 +393,9 @@ class AbstractBuilder bool ok = ctx.tyctx.lookup_type (hirid, &type); rust_assert (ok); rust_assert (type != nullptr); + if (auto param_ty = type->try_as ()) + type = param_ty->resolve (); + rust_assert (type != nullptr); return type; } diff --git a/gcc/testsuite/rust/borrowck/methods.rs b/gcc/testsuite/rust/borrowck/methods.rs new file mode 100644 index 000000000000..0fd7f1a129f6 --- /dev/null +++ b/gcc/testsuite/rust/borrowck/methods.rs @@ -0,0 +1,38 @@ +// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck" } + +#[lang = "sized"] +pub trait Sized {} + +struct A { + x: i32, +} + +impl A { + fn get(&self) -> &i32 { + &self.x + } +} + +trait B { + fn get(&self) -> &i32; + fn set(&mut self, x: i32); +} + +impl B for A { + fn get(&self) -> &i32 { + &self.x + } + + fn set(&mut self, x: i32) { + self.x = x; + } +} + +fn main() { + let a = A { x: 0 }; + let b = a.get(); + + let c: dyn B = A { x: 0 }; + let d = c.get(); + c.set(1); +} \ No newline at end of file