Skip to content

Commit 31ee925

Browse files
committed
gccrs: Add check for super traits being implemented by Self
We need to recursively check the super traits of the predicate the Self type is trying to implement. Otherwise its cannot implement it. Fixes #3553 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::resolve_impl_block_substitutions): Track the polarity * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::validate_type_implements_this): new validator * typecheck/rust-tyty.h: new prototypes gcc/testsuite/ChangeLog: * rust/compile/issue-3553.rs: New test. Signed-off-by: Philip Herron <[email protected]>
1 parent 23097f8 commit 31ee925

File tree

4 files changed

+95
-3
lines changed

4 files changed

+95
-3
lines changed

gcc/rust/typecheck/rust-hir-type-check-item.cc

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -725,11 +725,11 @@ TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
725725

726726
// we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
727727
// for example
728-
specified_bound = get_predicate_from_bound (ref, impl_block.get_type ());
728+
specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
729+
impl_block.get_polarity ());
729730
}
730731

731732
TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ());
732-
733733
if (self->is<TyTy::ErrorType> ())
734734
{
735735
// we cannot check for unconstrained type arguments when the Self type is
@@ -771,7 +771,14 @@ TypeCheckItem::validate_trait_impl_block (
771771

772772
// we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
773773
// for example
774-
specified_bound = get_predicate_from_bound (ref, impl_block.get_type ());
774+
specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
775+
impl_block.get_polarity ());
776+
777+
// need to check that if this specified bound has super traits does this
778+
// Self
779+
// implement them?
780+
specified_bound.validate_type_implements_super_traits (
781+
*self, impl_block.get_type (), impl_block.get_trait_ref ());
775782
}
776783

777784
bool is_trait_impl_block = !trait_reference->is_error ();

gcc/rust/typecheck/rust-tyty-bounds.cc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,65 @@ TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
828828
return true;
829829
}
830830

831+
bool
832+
TypeBoundPredicate::validate_type_implements_super_traits (
833+
TyTy::BaseType &self, HIR::Type &impl_type, HIR::Type &trait) const
834+
{
835+
if (get_polarity () != BoundPolarity::RegularBound)
836+
return true;
837+
838+
auto &ptref = *get ();
839+
for (auto &super : super_traits)
840+
{
841+
if (super.get_polarity () != BoundPolarity::RegularBound)
842+
continue;
843+
844+
if (!super.validate_type_implements_this (self, impl_type, trait))
845+
{
846+
auto &sptref = *super.get ();
847+
848+
// emit error
849+
std::string fixit1
850+
= "required by this bound in: " + ptref.get_name ();
851+
std::string fixit2 = "the trait " + sptref.get_name ()
852+
+ " is not implemented for "
853+
+ impl_type.as_string ();
854+
855+
rich_location r (line_table, trait.get_locus ());
856+
r.add_fixit_insert_after (super.get_locus (), fixit1.c_str ());
857+
r.add_fixit_insert_after (trait.get_locus (), fixit2.c_str ());
858+
rust_error_at (r, ErrorCode::E0277,
859+
"the trait bound %<%s: %s%> is not satisfied",
860+
impl_type.as_string ().c_str (),
861+
sptref.get_name ().c_str ());
862+
863+
return false;
864+
}
865+
866+
if (!super.validate_type_implements_super_traits (self, impl_type, trait))
867+
return false;
868+
}
869+
870+
return true;
871+
}
872+
873+
bool
874+
TypeBoundPredicate::validate_type_implements_this (TyTy::BaseType &self,
875+
HIR::Type &impl_type,
876+
HIR::Type &trait) const
877+
{
878+
const auto &ptref = *get ();
879+
auto probed_bounds = Resolver::TypeBoundsProbe::Probe (&self);
880+
for (auto &elem : probed_bounds)
881+
{
882+
auto &tref = *(elem.first);
883+
if (ptref.is_equal (tref))
884+
return true;
885+
}
886+
887+
return false;
888+
}
889+
831890
// trait item reference
832891

833892
const Resolver::TraitItemReference *

gcc/rust/typecheck/rust-tyty.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,14 @@ class TypeBoundPredicate : public SubstitutionRef
578578

579579
bool is_equal (const TypeBoundPredicate &other) const;
580580

581+
bool validate_type_implements_super_traits (TyTy::BaseType &self,
582+
HIR::Type &impl_type,
583+
HIR::Type &trait) const;
584+
585+
bool validate_type_implements_this (TyTy::BaseType &self,
586+
HIR::Type &impl_type,
587+
HIR::Type &trait) const;
588+
581589
private:
582590
struct mark_is_error
583591
{
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
trait Foo {
2+
fn f(&self) -> isize;
3+
}
4+
5+
trait Bar: Foo {
6+
fn g(&self) -> isize;
7+
}
8+
9+
struct A {
10+
x: isize,
11+
}
12+
13+
impl Bar for A {
14+
// { dg-error "the trait bound .A: Foo. is not satisfied .E0277." "" { target *-*-* } .-1 }
15+
fn g(&self) -> isize {
16+
self.f()
17+
}
18+
}

0 commit comments

Comments
 (0)