diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-09-10 12:14:33 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-09-10 13:47:51 +0100 |
commit | a1c87bfea6c5e2fd6b2d23b12b563fcaf5ec09a1 (patch) | |
tree | 1294bbc35cc86fffd2ef15e66f3b9fbce55eee06 /gcc | |
parent | e68a772a4a3010b62dae7231b1d841654dbb66d3 (diff) | |
download | gcc-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.h | 36 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 9 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/traits16.rs | 20 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/traits17.rs | 23 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/trait3.rs | 43 |
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 +} |