diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-09-05 00:29:33 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-09-05 00:42:24 +0100 |
commit | 0798add3d3c1bf4b20ecc1b4fa1047ba4ba19759 (patch) | |
tree | c89214f404834153a72ac89311d7625cc322a8a8 /gcc/rust/backend/rust-compile-context.h | |
parent | 07b354c31d2d17ba3a6759a76663d038912b682c (diff) | |
download | gcc-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.h | 5 |
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 { |