aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc34
-rw-r--r--gcc/rust/typecheck/rust-tyty.h57
-rw-r--r--gcc/testsuite/rust/compile/traits6.rs15
3 files changed, 102 insertions, 4 deletions
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index a2ae4fa..3238631 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -27,6 +27,8 @@
#include "rust-tyty-cast.h"
#include "rust-hir-map.h"
#include "rust-substitution-mapper.h"
+#include "rust-hir-trait-ref.h"
+#include "rust-hir-type-bounds.h"
extern ::Backend *
rust_get_backend ();
@@ -34,6 +36,32 @@ rust_get_backend ();
namespace Rust {
namespace TyTy {
+bool
+BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
+{
+ const Resolver::TraitReference *query = predicate.get ();
+ for (auto &bound : specified_bounds)
+ {
+ const Resolver::TraitReference *item = bound.get ();
+ bool found = item->get_mappings ().get_defid ()
+ == query->get_mappings ().get_defid ();
+ if (found)
+ return true;
+ }
+
+ std::vector<std::reference_wrapper<Resolver::TraitReference>> probed
+ = Resolver::TypeBoundsProbe::Probe (this);
+ for (const Resolver::TraitReference &bound : probed)
+ {
+ bool found = bound.get_mappings ().get_defid ()
+ == query->get_mappings ().get_defid ();
+ if (found)
+ return true;
+ }
+
+ return false;
+}
+
TyVar::TyVar (HirId ref) : ref (ref)
{
// ensure this reference is defined within the context
@@ -556,7 +584,7 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
bool ok
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
if (ok)
- sub.fill_param_ty (arg.get_tyty ());
+ sub.fill_param_ty (arg.get_tyty (), subst_mappings.get_locus ());
}
adt->iterate_fields ([&] (StructFieldType *field) mutable -> bool {
@@ -811,7 +839,7 @@ FnType::is_equal (const BaseType &other) const
BaseType *
FnType::clone () const
{
- std::vector<std::pair<HIR::Pattern *, BaseType *> > cloned_params;
+ std::vector<std::pair<HIR::Pattern *, BaseType *>> cloned_params;
for (auto &p : params)
cloned_params.push_back (
std::pair<HIR::Pattern *, BaseType *> (p.first, p.second->clone ()));
@@ -836,7 +864,7 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
bool ok
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
if (ok)
- sub.fill_param_ty (arg.get_tyty ());
+ sub.fill_param_ty (arg.get_tyty (), subst_mappings.get_locus ());
}
auto fty = fn->get_return_type ();
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 13bab90..6fe67c7 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -172,7 +172,21 @@ public:
return specified_bounds;
}
+ std::string bounds_as_string () const
+ {
+ std::string buf;
+ for (auto &b : specified_bounds)
+ buf += b.as_string () + ", ";
+
+ return "bounds:[" + buf + "]";
+ }
+
protected:
+ void add_bound (TypeBoundPredicate predicate)
+ {
+ specified_bounds.push_back (predicate);
+ }
+
std::vector<TypeBoundPredicate> specified_bounds;
};
@@ -237,6 +251,37 @@ public:
return get_kind () == other.get_kind ();
}
+ bool satisfies_bound (const TypeBoundPredicate &predicate) const;
+
+ bool bounds_compatible (const BaseType &other, Location locus) const
+ {
+ std::vector<std::reference_wrapper<const TypeBoundPredicate>>
+ unsatisfied_bounds;
+ for (auto &bound : get_specified_bounds ())
+ {
+ if (!other.satisfies_bound (bound))
+ unsatisfied_bounds.push_back (bound);
+ }
+
+ if (unsatisfied_bounds.size () > 0)
+ {
+ RichLocation r (locus);
+ rust_error_at (r, "bounds not satisfied for %s",
+ other.as_string ().c_str ());
+ return false;
+ }
+
+ return unsatisfied_bounds.size () == 0;
+ }
+
+ void inherit_bounds (const BaseType &other)
+ {
+ for (auto &bound : other.get_specified_bounds ())
+ {
+ add_bound (bound);
+ }
+ }
+
virtual bool is_unit () const { return false; }
virtual bool is_concrete () const { return true; }
@@ -575,8 +620,18 @@ public:
std::string as_string () const { return param->as_string (); }
- void fill_param_ty (BaseType *type)
+ void fill_param_ty (BaseType *type, Location locus)
{
+ if (type->get_kind () == TyTy::TypeKind::INFER)
+ {
+ type->inherit_bounds (*param);
+ }
+ else
+ {
+ if (!param->bounds_compatible (*type, locus))
+ return;
+ }
+
if (type->get_kind () == TypeKind::PARAM)
{
delete param;
diff --git a/gcc/testsuite/rust/compile/traits6.rs b/gcc/testsuite/rust/compile/traits6.rs
new file mode 100644
index 0000000..3579b5a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits6.rs
@@ -0,0 +1,15 @@
+trait Foo {
+ fn default() -> i32;
+}
+
+struct Bar(i32);
+
+fn type_bound_test<T: Foo>() -> i32 {
+ T::default()
+}
+
+fn main() {
+ let a;
+ a = type_bound_test::<Bar>();
+ // { dg-error "bounds not satisfied for Bar" "" { target *-*-* } .-1 }
+}