Skip to content

Commit

Permalink
borrowck: Resolve HIR::MethodCallExpr to BIR::CallExpr
Browse files Browse the repository at this point in the history
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 <kushalpal109@gmail.com>
  • Loading branch information
braw-lee committed May 13, 2024
1 parent 8a72566 commit 1a157cd
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
61 changes: 60 additions & 1 deletion gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<TyTy::FnType> ();

std::vector<PlaceId> 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)
Expand Down Expand Up @@ -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<Resolver::Adjustment> *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
4 changes: 4 additions & 0 deletions gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
12 changes: 12 additions & 0 deletions gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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<TyTy::ParamType> ())
type = param_ty->resolve ();
rust_assert (type != nullptr);
return type;
}

Expand Down
38 changes: 38 additions & 0 deletions gcc/testsuite/rust/borrowck/methods.rs
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 1a157cd

Please sign in to comment.