aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-09-10 12:14:33 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-09-10 13:47:51 +0100
commita1c87bfea6c5e2fd6b2d23b12b563fcaf5ec09a1 (patch)
tree1294bbc35cc86fffd2ef15e66f3b9fbce55eee06 /gcc
parente68a772a4a3010b62dae7231b1d841654dbb66d3 (diff)
downloadgcc-a1c87bfea6c5e2fd6b2d23b12b563fcaf5ec09a1.zip
gcc-a1c87bfea6c5e2fd6b2d23b12b563fcaf5ec09a1.tar.gz
gcc-a1c87bfea6c5e2fd6b2d23b12b563fcaf5ec09a1.tar.bz2
Add initial support to specify Super Traits
Super Traits are simply TraitBounds upon the implict Self TypeParameter, such that a trait with a super trait bound almost ends up looking like this trait A : B { } -> trait A where Self: B { }
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h36
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc9
-rw-r--r--gcc/rust/typecheck/rust-tyty.h3
-rw-r--r--gcc/testsuite/rust/compile/torture/traits16.rs20
-rw-r--r--gcc/testsuite/rust/compile/torture/traits17.rs23
-rw-r--r--gcc/testsuite/rust/execute/torture/trait3.rs43
6 files changed, 129 insertions, 5 deletions
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index 49aa2fa..b0e2c0d 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -113,10 +113,6 @@ private:
return tref;
}
- // Check if there is a super-trait, and apply this bound to the Self
- // TypeParam
- // FIXME
-
TyTy::BaseType *self = nullptr;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
for (auto &generic_param : trait_reference->get_generic_params ())
@@ -147,6 +143,38 @@ private:
rust_assert (self != nullptr);
+ // Check if there is a super-trait, and apply this bound to the Self
+ // TypeParam
+ std::vector<TyTy::TypeBoundPredicate> specified_bounds;
+
+ // They also inherit themselves as a bound this enables a trait item to
+ // reference other Self::trait_items
+ specified_bounds.push_back (
+ TyTy::TypeBoundPredicate (trait_reference->get_mappings ().get_defid (),
+ trait_reference->get_locus ()));
+
+ if (trait_reference->has_type_param_bounds ())
+ {
+ for (auto &bound : trait_reference->get_type_param_bounds ())
+ {
+ if (bound->get_bound_type ()
+ == HIR::TypeParamBound::BoundType::TRAITBOUND)
+ {
+ HIR::TraitBound *b
+ = static_cast<HIR::TraitBound *> (bound.get ());
+
+ // FIXME this might be recursive we need a check for that
+
+ TraitReference *trait = resolve_trait_path (b->get_path ());
+ TyTy::TypeBoundPredicate predicate (
+ trait->get_mappings ().get_defid (), bound->get_locus ());
+
+ specified_bounds.push_back (std::move (predicate));
+ }
+ }
+ }
+ self->inherit_bounds (specified_bounds);
+
std::vector<TraitItemReference> item_refs;
for (auto &item : trait_reference->get_trait_items ())
{
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 899ad59..398b531 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -99,7 +99,14 @@ BaseType::bounds_compatible (const BaseType &other, Location locus) const
void
BaseType::inherit_bounds (const BaseType &other)
{
- for (auto &bound : other.get_specified_bounds ())
+ inherit_bounds (other.get_specified_bounds ());
+}
+
+void
+BaseType::inherit_bounds (
+ const std::vector<TyTy::TypeBoundPredicate> &specified_bounds)
+{
+ for (auto &bound : specified_bounds)
{
add_bound (bound);
}
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 7f149a9..867dc37 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -257,6 +257,9 @@ public:
void inherit_bounds (const BaseType &other);
+ void inherit_bounds (
+ const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
+
virtual bool is_unit () const { return false; }
virtual bool is_concrete () const { return true; }
diff --git a/gcc/testsuite/rust/compile/torture/traits16.rs b/gcc/testsuite/rust/compile/torture/traits16.rs
new file mode 100644
index 0000000..afc4a86
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits16.rs
@@ -0,0 +1,20 @@
+trait A {
+ fn a() -> i32 {
+ 123
+ }
+
+ fn b() -> i32 {
+ Self::a() + 456
+ }
+}
+
+struct S;
+impl A for S {}
+
+fn main() {
+ let a;
+ a = S::a();
+
+ let b;
+ b = S::b();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits17.rs b/gcc/testsuite/rust/compile/torture/traits17.rs
new file mode 100644
index 0000000..6da8bcb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits17.rs
@@ -0,0 +1,23 @@
+trait A {
+ fn a() -> i32 {
+ 123
+ }
+}
+
+trait B: A {
+ fn b() -> i32 {
+ Self::a() + 456
+ }
+}
+
+struct S;
+impl A for S {}
+impl B for S {}
+
+fn main() {
+ let a;
+ a = S::a();
+
+ let b;
+ b = S::b();
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait3.rs b/gcc/testsuite/rust/execute/torture/trait3.rs
new file mode 100644
index 0000000..accfa9d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait3.rs
@@ -0,0 +1,43 @@
+/* { dg-output "123, 777" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+trait A {
+ fn a() -> i32 {
+ 123
+ }
+}
+
+trait B: A {
+ fn b() -> i32 {
+ <T as A>::a() + 456
+ }
+}
+
+struct T;
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl A for T {
+ fn a() -> i32 {
+ 321
+ }
+}
+
+struct S;
+impl A for S {}
+impl B for S {}
+
+fn main() -> i32 {
+ let aa = S::a();
+ let bb = S::b();
+
+ unsafe {
+ let a = "%i, %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, aa, bb);
+ }
+ 0
+}