aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-var-decl.h
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-01-21 20:01:03 +0000
committerPhilip Herron <philip.herron@embecosm.com>2022-01-22 12:11:41 +0000
commitee794effe3b55d2aa8acc108fb36bd8d05672dfa (patch)
tree0ac934a218d9f65af25065aa4abe94976533cb4a /gcc/rust/backend/rust-compile-var-decl.h
parent6c9e57efa5474cfe5d0440e1022ee3c4a8400199 (diff)
downloadgcc-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.h1
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);
}