diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-01-21 20:01:03 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-01-22 12:11:41 +0000 |
commit | ee794effe3b55d2aa8acc108fb36bd8d05672dfa (patch) | |
tree | 0ac934a218d9f65af25065aa4abe94976533cb4a /gcc/rust/backend/rust-compile-var-decl.h | |
parent | 6c9e57efa5474cfe5d0440e1022ee3c4a8400199 (diff) | |
download | gcc-ee794effe3b55d2aa8acc108fb36bd8d05672dfa.zip gcc-ee794effe3b55d2aa8acc108fb36bd8d05672dfa.tar.gz gcc-ee794effe3b55d2aa8acc108fb36bd8d05672dfa.tar.bz2 |
MethodResolution should respect the autoderef cycle
Autoderef includes calling into the deref operator overloads so for
example.
```rust
pub trait Deref {
type Target;
fn deref(&self) -> &Self::Target;
}
impl<T> Deref for &T {
type Target = T;
fn deref(&self) -> &T {
*self
}
}
struct Bar(i32);
impl Bar {
fn foobar(self) -> i32 {
self.0
}
}
struct Foo<T>(T);
impl<T> Deref for Foo<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn main() {
let bar = Bar(123);
let foo: Foo<&Bar> = Foo(&bar);
let foobar: i32 = foo.foobar();
}
```
So you can see here we have a nested structure of Foo<&Bar> and Foo is a
generic structure, and we have a method call of foo.foobar(). This is an
interesting case of method resolution showing how rust allows for multiple
dereference to find the apropriate method of foobar.
So in this method call expression foo is of type Foo<&Bar> the generic
structure is a covariant Reference Type (&) of the structure Bar. The
method foobar has a receiver type of a simple Bar being passed by value.
So in order for this function to be called the method resolution system
has an algorithm of:
- reciever = Foo<&Bar>
- Find all methods named foobar
- try and match the receiver (self) with this reciever
- so that means we have Foo<&Bar> vs Bar which does not match
- Go back to the start and try by taking an immutable refernece
- &Foo<&Bar> does not match Bar
- Go back to the start and try by taking a mutable reference
- &mut Foo<&Bar> does not match Bar
- Try and dereference the original receiver Foo<&Bar>
- Do we have the deref lang item defined
- if yes resolve the method by the same mechanism for Foo<&Bar> for deref
- Get the result type of this function which is &&Bar do the dereference
- Now we have &Bar and a new adjustment for the original receiver
- Try and match &Bar to the foobar method reciever of Bar
- Try taking an immutable reference &&Bar
- Try taking a mutable reference &mut &Bar
- Try and deref &Bar we have the generic implementation of deref for &T
- Call this derefernece like before to get down to Bar
- Now try Bar on the foobar reciever Bar and it matches
We have now resolved the method with two dereference adjustments so the
function call becomes:
```
void main ()
{
i32 D.110;
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};
}
}
```
Obviously GCC will optimize this with -O2 so that it does not require
function calls but the gimple will show us what is actually going on. As
far as I am aware rustc pre-optimizes this regardless of optimizations
being turned on or not, these lang item functions are easily inlineable
so it makes more sense to me to let GCC's middle-end take care of this for
us.
This is a big patch and very difficult to split up as it reimplements our
method resolution system.
Fixes #884
Diffstat (limited to 'gcc/rust/backend/rust-compile-var-decl.h')
-rw-r--r-- | gcc/rust/backend/rust-compile-var-decl.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 4b52dcd..51affe0 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -49,6 +49,7 @@ public: address_taken_context->lookup_addess_taken ( stmt.get_mappings ().get_hirid (), &address_taken); + translated_type = TyTyResolveCompile::compile (ctx, resolved_type); stmt.get_pattern ()->accept_vis (*this); } |