diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-09-13 15:31:19 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-09-14 13:23:56 +0100 |
commit | 002313b343746f8c72b62522e48e04fa0953b2d0 (patch) | |
tree | d393eecd5333696158e868e907ae93f7530de8ec /gcc/rust/backend | |
parent | c644ee4c4351e3590f5396e94ec24ad7b828a954 (diff) | |
download | gcc-002313b343746f8c72b62522e48e04fa0953b2d0.zip gcc-002313b343746f8c72b62522e48e04fa0953b2d0.tar.gz gcc-002313b343746f8c72b62522e48e04fa0953b2d0.tar.bz2 |
Initial autoderef support for method calls
There is compiler magic for method calls the self parameter can be of
several forms:
- specified type (self: Type)
- immutable Self (self)
- mutable Self (mut self)
- immutable reference (&self)
- mutable reference (&mut self)
This updates our HIR lowering to actually lower this correctly and apply
the apropriate Self type to the TyTy::FnDef. The code used to just default
to plain Self ignoring any modifiers.
Rust also allows something called the autoderef cycle to coerce the
receiver to the correct type for the function such as:
```rust
struct Foo(i32);
impl Foo {
fn bar(&self) { }
}
fn main() {
let a = Foo(123);
a.bar();
}
```
In this example the method call is expected to apply an implict reference
to variable 'a' such that the method call becomes:
```
Foo::bar(&a);
```
The algorithm is detailed here:
https://doc.rust-lang.org/nightly/nomicon/dot-operator.html
1. Try to match Self
2. Apply an immutable Reference and Try again
3. Apply an mutable Reference and Try again
4. Can we dereference ? [deref and go back to 1] else [quit]
This is not 100% complete since we do not yet support operator overloading
so we wil require an update to support the Deref operator overload for
more complex types.
Fixes: #241
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index ef2c16a..5214b1d 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -277,6 +277,32 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) // method receiver Bexpression *self = CompileExpr::Compile (expr.get_receiver ().get (), ctx); rust_assert (self != nullptr); + + // lookup the autoderef mappings + std::vector<Resolver::Adjustment> *adjustments = nullptr; + ok = ctx->get_tyctx ()->lookup_autoderef_mappings ( + 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: + Btype *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; + } + } args.push_back (self); // normal args |