aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-08-08 22:22:21 +0000
committerGitHub <noreply@github.com>2021-08-08 22:22:21 +0000
commit5e723d0b7a85d109f01196b264a25823e77496e1 (patch)
tree33b8a34539ea3121c5f27ba1e44640f552f52a64 /gcc
parentfa2aec10e60592348e1640b5bda0507b1324f235 (diff)
parent72483b1ca912dca78543f5cc2a7e9d1380ef5784 (diff)
downloadgcc-5e723d0b7a85d109f01196b264a25823e77496e1.zip
gcc-5e723d0b7a85d109f01196b264a25823e77496e1.tar.gz
gcc-5e723d0b7a85d109f01196b264a25823e77496e1.tar.bz2
Merge #611
611: Add check for TypeBounds on argument substitutions r=philberty a=philberty TypeParameters contain specified bounds, when we substitute them we need to ensure that the argument satisfies those bounds otherwise... it fails the contract. Addreses #440 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc6
-rw-r--r--gcc/rust/backend/rust-compile.cc6
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h50
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h26
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h4
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h14
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc26
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc77
-rw-r--r--gcc/rust/typecheck/rust-tyty.h53
-rw-r--r--gcc/rust/util/rust-hir-map.cc7
-rw-r--r--gcc/rust/util/rust-hir-map.h14
-rw-r--r--gcc/testsuite/rust/compile/traits6.rs15
-rw-r--r--gcc/testsuite/rust/compile/traits7.rs24
18 files changed, 258 insertions, 96 deletions
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index c87b477..5f07a2a 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -107,10 +107,10 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
= ctx->get_mappings ()->lookup_trait_item_mapping (
trait_item->get_mappings ().get_hirid ());
- Resolver::TraitReference &trait_ref
- = Resolver::TraitResolver::error_node ();
+ Resolver::TraitReference *trait_ref
+ = &Resolver::TraitReference::error_node ();
bool ok = ctx->get_tyctx ()->lookup_trait_reference (
- trait->get_mappings ().get_defid (), trait_ref);
+ trait->get_mappings ().get_defid (), &trait_ref);
rust_assert (ok);
TyTy::BaseType *receiver = nullptr;
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index f422572..3c6a188 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -150,10 +150,10 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping (
trait_item->get_mappings ().get_hirid ());
- Resolver::TraitReference &trait_ref
- = Resolver::TraitResolver::error_node ();
+ Resolver::TraitReference *trait_ref
+ = &Resolver::TraitReference::error_node ();
bool ok = ctx->get_tyctx ()->lookup_trait_reference (
- trait->get_mappings ().get_defid (), trait_ref);
+ trait->get_mappings ().get_defid (), &trait_ref);
rust_assert (ok);
TyTy::BaseType *receiver = nullptr;
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 8e3ca31..87c9662 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -49,8 +49,8 @@ struct PathProbeCandidate
struct TraitItemCandidate
{
- const TraitReference &trait_ref;
- const TraitItemReference &item_ref;
+ const TraitReference *trait_ref;
+ const TraitItemReference *item_ref;
};
CandidateType type;
@@ -128,18 +128,18 @@ public:
if (!probe_bounds)
return probe.candidates;
- std::vector<std::reference_wrapper<TraitReference>> probed_bounds
+ std::vector<TraitReference *> probed_bounds
= TypeBoundsProbe::Probe (receiver);
- std::vector<std::reference_wrapper<const TraitReference>> specified_bounds;
+ std::vector<const TraitReference *> specified_bounds;
for (const TyTy::TypeBoundPredicate &predicate :
receiver->get_specified_bounds ())
{
const TraitReference *trait_item = predicate.get ();
- specified_bounds.push_back (*trait_item);
+ specified_bounds.push_back (trait_item);
}
- std::vector<std::reference_wrapper<const TraitReference>> union_type_bounds
+ std::vector<const TraitReference *> union_type_bounds
= probe.union_bounds (probed_bounds, specified_bounds);
probe.process_traits_for_candidates (union_type_bounds,
ignore_mandatory_trait_items);
@@ -230,22 +230,22 @@ private:
}
void process_traits_for_candidates (
- const std::vector<std::reference_wrapper<const TraitReference>> traits,
+ const std::vector<const TraitReference *> traits,
bool ignore_mandatory_trait_items)
{
- for (const TraitReference &trait_ref : traits)
+ for (const TraitReference *trait_ref : traits)
{
- const TraitItemReference &trait_item_ref
- = trait_ref.lookup_trait_item (search.as_string ());
- if (trait_item_ref.is_error ())
+ const TraitItemReference *trait_item_ref = nullptr;
+ if (!trait_ref->lookup_trait_item (search.as_string (),
+ &trait_item_ref))
continue;
- bool trait_item_needs_implementation = !trait_item_ref.is_optional ();
+ bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
if (ignore_mandatory_trait_items && trait_item_needs_implementation)
continue;
PathProbeCandidate::CandidateType candidate_type;
- switch (trait_item_ref.get_trait_item_type ())
+ switch (trait_item_ref->get_trait_item_type ())
{
case TraitItemReference::TraitItemType::FN:
candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
@@ -264,7 +264,7 @@ private:
break;
}
- TyTy::BaseType *trait_item_tyty = trait_item_ref.get_tyty ();
+ TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
// we can substitute the Self with the receiver here
if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
@@ -298,7 +298,7 @@ private:
trait_ref, trait_item_ref};
PathProbeCandidate candidate{candidate_type,
trait_item_tyty,
- trait_ref.get_locus (),
+ trait_ref->get_locus (),
{trait_item_candidate}};
candidates.push_back (std::move (candidate));
}
@@ -311,21 +311,21 @@ private:
current_impl (nullptr)
{}
- std::vector<std::reference_wrapper<const TraitReference>> union_bounds (
- const std::vector<std::reference_wrapper</*const*/ TraitReference>> a,
- const std::vector<std::reference_wrapper<const TraitReference>> b) const
+ std::vector<const TraitReference *>
+ union_bounds (const std::vector</*const*/ TraitReference *> a,
+ const std::vector<const TraitReference *> b) const
{
- std::map<DefId, std::reference_wrapper<const TraitReference>> mapper;
- for (const TraitReference &ref : a)
+ std::map<DefId, const TraitReference *> mapper;
+ for (const TraitReference *ref : a)
{
- mapper.insert ({ref.get_mappings ().get_defid (), ref});
+ mapper.insert ({ref->get_mappings ().get_defid (), ref});
}
- for (const TraitReference &ref : b)
+ for (const TraitReference *ref : b)
{
- mapper.insert ({ref.get_mappings ().get_defid (), ref});
+ mapper.insert ({ref->get_mappings ().get_defid (), ref});
}
- std::vector<std::reference_wrapper<const TraitReference>> union_set;
+ std::vector<const TraitReference *> union_set;
for (auto it = mapper.begin (); it != mapper.end (); it++)
{
union_set.push_back (it->second);
@@ -362,7 +362,7 @@ public:
case PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST:
case PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS:
case PathProbeCandidate::CandidateType::TRAIT_FUNC:
- r.add_range (c.item.trait.item_ref.get_locus ());
+ r.add_range (c.item.trait.item_ref->get_locus ());
break;
}
}
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
index b19c38a..21a8beb 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-ref.h
@@ -199,6 +199,12 @@ public:
bool is_error () const { return hir_trait_ref == nullptr; }
+ static TraitReference &error_node ()
+ {
+ static TraitReference trait_error_node = TraitReference::error ();
+ return trait_error_node;
+ }
+
Location get_locus () const { return hir_trait_ref->get_locus (); }
std::string get_name () const
@@ -227,14 +233,18 @@ public:
return hir_trait_ref->get_mappings ();
}
- const TraitItemReference &lookup_trait_item (const std::string &ident) const
+ bool lookup_trait_item (const std::string &ident,
+ const TraitItemReference **ref) const
{
for (auto &item : item_refs)
{
if (ident.compare (item.get_identifier ()) == 0)
- return item;
+ {
+ *ref = &item;
+ return true;
+ }
}
- return TraitItemReference::error_node ();
+ return false;
}
const TraitItemReference &
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index 6d7c864..1669a37 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -100,29 +100,23 @@ class TraitResolver : public TypeCheckBase
using Rust::Resolver::TypeCheckBase::visit;
public:
- static TraitReference &Resolve (HIR::TypePath &path)
+ static TraitReference *Resolve (HIR::TypePath &path)
{
TraitResolver resolver;
return resolver.go (path);
}
- static TraitReference &error_node ()
- {
- static TraitReference trait_error_node = TraitReference::error ();
- return trait_error_node;
- }
-
private:
TraitResolver () : TypeCheckBase () {}
- TraitReference &go (HIR::TypePath &path)
+ TraitReference *go (HIR::TypePath &path)
{
NodeId ref;
if (!resolver->lookup_resolved_type (path.get_mappings ().get_nodeid (),
&ref))
{
rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
- return error_node ();
+ return &TraitReference::error_node ();
}
HirId hir_node = UNKNOWN_HIRID;
@@ -130,7 +124,7 @@ private:
&hir_node))
{
rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
- return error_node ();
+ return &TraitReference::error_node ();
}
HIR::Item *resolved_item
@@ -140,9 +134,9 @@ private:
resolved_item->accept_vis (*this);
rust_assert (trait_reference != nullptr);
- TraitReference &tref = error_node ();
+ TraitReference *tref = &TraitReference::error_node ();
if (context->lookup_trait_reference (
- trait_reference->get_mappings ().get_defid (), tref))
+ trait_reference->get_mappings ().get_defid (), &tref))
{
return tref;
}
@@ -185,13 +179,13 @@ private:
item_refs.push_back (std::move (trait_item_ref));
}
- tref = TraitReference (trait_reference, item_refs);
+ TraitReference trait_object (trait_reference, item_refs);
context->insert_trait_reference (
- trait_reference->get_mappings ().get_defid (), std::move (tref));
+ trait_reference->get_mappings ().get_defid (), std::move (trait_object));
- tref = error_node ();
+ tref = &TraitReference::error_node ();
bool ok = context->lookup_trait_reference (
- trait_reference->get_mappings ().get_defid (), tref);
+ trait_reference->get_mappings ().get_defid (), &tref);
rust_assert (ok);
return tref;
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
index d97c0f5..ce694da 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -31,8 +31,7 @@ class TypeBoundsProbe : public TypeCheckBase
using Rust::Resolver::TypeCheckBase::visit;
public:
- static std::vector<std::reference_wrapper<TraitReference>>
- Probe (const TyTy::BaseType *receiver)
+ static std::vector<TraitReference *> Probe (const TyTy::BaseType *receiver)
{
TypeBoundsProbe probe (receiver);
probe.scan ();
@@ -48,7 +47,7 @@ private:
{}
const TyTy::BaseType *receiver;
- std::vector<std::reference_wrapper<TraitReference>> trait_references;
+ std::vector<TraitReference *> trait_references;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index f05ab86..3dd0a19 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -202,7 +202,7 @@ protected:
context (TypeCheckContext::get ())
{}
- TraitReference &resolve_trait_path (HIR::TypePath &);
+ TraitReference *resolve_trait_path (HIR::TypePath &);
Analysis::Mappings *mappings;
Resolver *resolver;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 7f1a83d..6743c8b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -244,7 +244,7 @@ public:
= resolved_candidate.is_impl_candidate ()
? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
.get_nodeid ()
- : resolved_candidate.item.trait.item_ref.get_mappings ()
+ : resolved_candidate.item.trait.item_ref->get_mappings ()
.get_nodeid ();
if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
@@ -994,7 +994,7 @@ public:
else
{
resolved_node_id
- = candidate.item.trait.item_ref.get_mappings ().get_nodeid ();
+ = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
}
if (seg.has_generic_args ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 8d770f0..8775502 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -43,12 +43,12 @@ public:
void visit (HIR::ImplBlock &impl_block) override
{
- TraitReference &trait_reference = TraitResolver::error_node ();
+ TraitReference *trait_reference = &TraitReference::error_node ();
if (impl_block.has_trait_ref ())
{
std::unique_ptr<HIR::TypePath> &ref = impl_block.get_trait_ref ();
trait_reference = TraitResolver::Resolve (*ref.get ());
- rust_assert (!trait_reference.is_error ());
+ rust_assert (!trait_reference->is_error ());
}
TyTy::BaseType *self = nullptr;
@@ -60,7 +60,7 @@ public:
return;
}
- bool is_trait_impl_block = !trait_reference.is_error ();
+ bool is_trait_impl_block = !trait_reference->is_error ();
std::vector<std::reference_wrapper<const TraitItemReference>>
trait_item_refs;
@@ -72,20 +72,20 @@ public:
{
auto &trait_item_ref
= TypeCheckImplItemWithTrait::Resolve (impl_item.get (), self,
- trait_reference);
+ *trait_reference);
trait_item_refs.push_back (trait_item_ref);
}
}
bool impl_block_missing_trait_items
= is_trait_impl_block
- && trait_reference.size () != trait_item_refs.size ();
+ && trait_reference->size () != trait_item_refs.size ();
if (impl_block_missing_trait_items)
{
// filter the missing impl_items
std::vector<std::reference_wrapper<const TraitItemReference>>
missing_trait_items;
- for (auto &trait_item_ref : trait_reference.get_trait_items ())
+ for (auto &trait_item_ref : trait_reference->get_trait_items ())
{
bool found = false;
for (const TraitItemReference &implemented_trait_item :
@@ -120,7 +120,7 @@ public:
rust_error_at (r, "missing %s in implementation of trait %<%s%>",
missing_items_buf.c_str (),
- trait_reference.get_name ().c_str ());
+ trait_reference->get_name ().c_str ());
}
}
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 91d9c53..fff86be 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -280,8 +280,11 @@ public:
case HIR::TypeParamBound::BoundType::TRAITBOUND: {
HIR::TraitBound *b
= static_cast<HIR::TraitBound *> (bound.get ());
+
+ TraitReference *trait = resolve_trait_path (b->get_path ());
TyTy::TypeBoundPredicate predicate (
- &resolve_trait_path (b->get_path ()));
+ trait->get_mappings ().get_defid (), b->get_locus ());
+
specified_bounds.push_back (std::move (predicate));
}
break;
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index b171123..d834ad8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -92,13 +92,13 @@ public:
trait_context.emplace (id, std::move (ref));
}
- bool lookup_trait_reference (DefId id, TraitReference &ref)
+ bool lookup_trait_reference (DefId id, TraitReference **ref)
{
auto it = trait_context.find (id);
if (it == trait_context.end ())
return false;
- ref = it->second;
+ *ref = &it->second;
return true;
}
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index a480155..008dc19 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -48,14 +48,14 @@ TypeBoundsProbe::scan ()
for (auto &trait_path : possible_trait_paths)
{
- TraitReference &trait_ref = TraitResolver::Resolve (*trait_path);
+ TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
- if (!trait_ref.is_error ())
+ if (!trait_ref->is_error ())
trait_references.push_back (trait_ref);
}
}
-TraitReference &
+TraitReference *
TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
{
return TraitResolver::Resolve (path);
@@ -68,7 +68,25 @@ namespace TyTy {
std::string
TypeBoundPredicate::as_string () const
{
- return reference->as_string ();
+ return get ()->as_string ();
+}
+
+const Resolver::TraitReference *
+TypeBoundPredicate::get () const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+
+ Resolver::TraitReference *ref = nullptr;
+ bool ok = context->lookup_trait_reference (reference, &ref);
+ rust_assert (ok);
+
+ return ref;
+}
+
+std::string
+TypeBoundPredicate::get_name () const
+{
+ return get ()->get_name ();
}
} // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index a2ae4fa..2d165c3 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,75 @@ 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<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;
+}
+
+bool
+BaseType::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);
+ }
+
+ // lets emit a single error for this
+ if (unsatisfied_bounds.size () > 0)
+ {
+ RichLocation r (locus);
+ std::string missing_preds;
+ for (size_t i = 0; i < unsatisfied_bounds.size (); i++)
+ {
+ const TypeBoundPredicate &pred = unsatisfied_bounds.at (i);
+ r.add_range (pred.get_locus ());
+ missing_preds += pred.get_name ();
+
+ bool have_next = (i + 1) < unsatisfied_bounds.size ();
+ if (have_next)
+ missing_preds += ", ";
+ }
+
+ rust_error_at (r, "bounds not satisfied for %s %<%s%> is not satisfied",
+ other.get_name ().c_str (), missing_preds.c_str ());
+ }
+
+ return unsatisfied_bounds.size () == 0;
+}
+
+void
+BaseType::inherit_bounds (const BaseType &other)
+{
+ for (auto &bound : other.get_specified_bounds ())
+ {
+ add_bound (bound);
+ }
+}
+
TyVar::TyVar (HirId ref) : ref (ref)
{
// ensure this reference is defined within the context
@@ -556,7 +627,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 +882,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 +907,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..c1afa14 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -132,26 +132,21 @@ public:
class TypeBoundPredicate
{
public:
- TypeBoundPredicate (Resolver::TraitReference *reference)
- : reference (reference)
+ TypeBoundPredicate (DefId reference, Location locus)
+ : reference (reference), locus (locus)
{}
- TypeBoundPredicate (const TypeBoundPredicate &other)
- : reference (other.reference)
- {}
+ std::string as_string () const;
- TypeBoundPredicate &operator= (const TypeBoundPredicate &other)
- {
- reference = other.reference;
- return *this;
- }
+ const Resolver::TraitReference *get () const;
- std::string as_string () const;
+ Location get_locus () const { return locus; }
- const Resolver::TraitReference *get () const { return reference; }
+ std::string get_name () const;
private:
- Resolver::TraitReference *reference;
+ DefId reference;
+ Location locus;
};
class TypeBoundsMappings
@@ -172,7 +167,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 +246,12 @@ public:
return get_kind () == other.get_kind ();
}
+ bool satisfies_bound (const TypeBoundPredicate &predicate) const;
+
+ bool bounds_compatible (const BaseType &other, Location locus) const;
+
+ void inherit_bounds (const BaseType &other);
+
virtual bool is_unit () const { return false; }
virtual bool is_concrete () const { return true; }
@@ -575,8 +590,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/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 4ffbff0..0f8f902 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -23,13 +23,6 @@
namespace Rust {
namespace Analysis {
-NodeMapping::NodeMapping (CrateNum crateNum, NodeId nodeId, HirId hirId,
- LocalDefId localDefId)
- : crateNum (crateNum), nodeId (nodeId), hirId (hirId), localDefId (localDefId)
-{}
-
-NodeMapping::~NodeMapping () {}
-
NodeMapping
NodeMapping::get_error ()
{
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index ccc873b..f689abf 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -53,8 +53,10 @@ class NodeMapping
{
public:
NodeMapping (CrateNum crateNum, NodeId nodeId, HirId hirId,
- LocalDefId localDefId);
- ~NodeMapping ();
+ LocalDefId localDefId)
+ : crateNum (crateNum), nodeId (nodeId), hirId (hirId),
+ localDefId (localDefId)
+ {}
static NodeMapping get_error ();
@@ -68,6 +70,14 @@ public:
std::string as_string () const;
+ bool is_equal (const NodeMapping &other) const
+ {
+ return get_crate_num () == other.get_crate_num ()
+ && get_nodeid () == other.get_nodeid ()
+ && get_hirid () == other.get_hirid ()
+ && get_local_defid () == other.get_local_defid ();
+ }
+
private:
CrateNum crateNum;
NodeId nodeId;
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 }
+}
diff --git a/gcc/testsuite/rust/compile/traits7.rs b/gcc/testsuite/rust/compile/traits7.rs
new file mode 100644
index 0000000..825553c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/traits7.rs
@@ -0,0 +1,24 @@
+trait Foo {
+ fn default() -> i32;
+}
+
+trait Bar {
+ fn not_default() -> i32;
+}
+
+struct Test(i32);
+
+impl Foo for Test {
+ fn default() -> i32 {
+ 1234
+ }
+}
+
+fn type_bound_test<T: Foo + Bar>() -> i32 {
+ T::default()
+}
+
+fn main() {
+ let a = type_bound_test::<Test>();
+ // { dg-error "bounds not satisfied for Test" "" { target *-*-* } .-1 }
+}