aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-context.h
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-09-05 00:29:33 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-09-05 00:42:24 +0100
commit0798add3d3c1bf4b20ecc1b4fa1047ba4ba19759 (patch)
treec89214f404834153a72ac89311d7625cc322a8a8 /gcc/rust/backend/rust-compile-context.h
parent07b354c31d2d17ba3a6759a76663d038912b682c (diff)
downloadgcc-0798add3d3c1bf4b20ecc1b4fa1047ba4ba19759.zip
gcc-0798add3d3c1bf4b20ecc1b4fa1047ba4ba19759.tar.gz
gcc-0798add3d3c1bf4b20ecc1b4fa1047ba4ba19759.tar.bz2
Support Generic Traits in qualified paths
This extends the ProjectionType which represents an implemented associated type with its own substitution mappings. The problem is a TypePath to a trait does not represent a single TyTy primitive type, the type system handles generics in an interesting way. Take for instance the case of a generic impl block: impl<T> Foo<T> { fn Bar<Y>(self, a:T, b:Y) {} } The compiler treats an impl block as the parent so that all items inherit from this, which is why rustc calls these inherent-impl-blocks. So in order to handle generic arguments we need to "bind" them, and in rust only some types actually support generic argument binding, at the moment for gccrs it is, ADTTypes, FnTypes and Projections. Going back to the example the TyTy for this function turns into: fn Bar<T,Y>(Foo<T>, T, Y) So when it comes to the generic traits its a similar process but the difference is that traits contain associated types, these must be able to bind the generic arguments such that we can substitute any covariant types fully. But there is a layer of complexity and indirection here consider the following example: trait Foo<T> { type A; fn test(a: T, b: Self::A) -> (T, Self::A) { (a, b) } } struct Bar<T>(T); impl<T> Foo<T> for Bar<T> { type A = T; } When we deal with a trait with an optional trait function that uses the associated types what actually happens here is that the type A in this trait context is considered just a simple PlaceHolder which gets setup within relation to its relevant impl block, so when we setup the associated types it turns into: Placeholder(A) -> Projection<T>(Bar<T> as Foo<T>) -> T So it forms an recursive chain that must be substituted in relation to what the paticular query is.
Diffstat (limited to 'gcc/rust/backend/rust-compile-context.h')
-rw-r--r--gcc/rust/backend/rust-compile-context.h5
1 files changed, 4 insertions, 1 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 66d037d..bffe97c 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -336,7 +336,10 @@ public:
void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
+ void visit (TyTy::ProjectionType &type) override
+ {
+ type.get ()->accept_vis (*this);
+ }
void visit (TyTy::PlaceholderType &type) override
{