aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc84
-rw-r--r--gcc/rust/backend/rust-compile.cc118
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h5
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.h4
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h277
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h57
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h4
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h101
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h27
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc1
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h16
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h36
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc75
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc10
-rw-r--r--gcc/rust/typecheck/rust-tyty.h83
-rw-r--r--gcc/testsuite/rust/compile/torture/traits8.rs22
-rw-r--r--gcc/testsuite/rust/compile/torture/traits9.rs30
20 files changed, 845 insertions, 128 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 794c7a3..f4bc9ea 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -79,6 +79,7 @@ GRS_OBJS = \
rust/rust-hir-type-check.o \
rust/rust-tyty.o \
rust/rust-tyctx.o \
+ rust/rust-tyty-bounds.o \
rust/rust-hir-const-fold.o \
rust/rust-lint-marklive.o \
$(END)
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index af8d609..c87b477 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -20,6 +20,8 @@
#include "rust-backend.h"
#include "rust-compile-resolve-path.h"
#include "rust-compile-item.h"
+#include "rust-hir-trait-resolve.h"
+#include "rust-hir-path-probe.h"
namespace Rust {
namespace Compile {
@@ -94,7 +96,76 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
HIR::ImplItem *resolved_item
= ctx->get_mappings ()->lookup_hir_implitem (
expr.get_mappings ().get_crate_num (), ref, &parent_impl_id);
- if (resolved_item != nullptr)
+
+ if (resolved_item == nullptr)
+ {
+ // it might be resolved to a trait item
+ HIR::TraitItem *trait_item
+ = ctx->get_mappings ()->lookup_hir_trait_item (
+ expr.get_mappings ().get_crate_num (), ref);
+ HIR::Trait *trait
+ = ctx->get_mappings ()->lookup_trait_item_mapping (
+ trait_item->get_mappings ().get_hirid ());
+
+ Resolver::TraitReference &trait_ref
+ = Resolver::TraitResolver::error_node ();
+ bool ok = ctx->get_tyctx ()->lookup_trait_reference (
+ trait->get_mappings ().get_defid (), trait_ref);
+ rust_assert (ok);
+
+ TyTy::BaseType *receiver = nullptr;
+ ok = ctx->get_tyctx ()->lookup_receiver (
+ expr.get_mappings ().get_hirid (), &receiver);
+ rust_assert (ok);
+
+ if (receiver->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ TyTy::ParamType *p
+ = static_cast<TyTy::ParamType *> (receiver);
+ receiver = p->resolve ();
+ }
+
+ // the type resolver can only resolve type bounds to their trait
+ // item so its up to us to figure out if this path should resolve
+ // to an trait-impl-block-item or if it can be defaulted to the
+ // trait-impl-item's definition
+ std::vector<Resolver::PathProbeCandidate> candidates
+ = Resolver::PathProbeType::Probe (
+ receiver, expr.get_final_segment ().get_segment (), true,
+ false, true);
+
+ if (candidates.size () == 0)
+ {
+ // this means we are defaulting back to the trait_item if
+ // possible
+ // TODO
+ gcc_unreachable ();
+ }
+ else
+ {
+ Resolver::PathProbeCandidate &candidate = candidates.at (0);
+ rust_assert (candidate.is_impl_candidate ());
+
+ HIR::ImplBlock *impl = candidate.item.impl.parent;
+ HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
+
+ TyTy::BaseType *self = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ impl->get_type ()->get_mappings ().get_hirid (), &self);
+ rust_assert (ok);
+
+ if (!lookup->has_subsititions_defined ())
+ CompileInherentImplItem::Compile (self, impl_item, ctx,
+ true);
+ else
+ CompileInherentImplItem::Compile (self, impl_item, ctx,
+ true, lookup);
+
+ lookup->set_ty_ref (
+ impl_item->get_impl_mappings ().get_hirid ());
+ }
+ }
+ else
{
rust_assert (parent_impl_id != UNKNOWN_HIRID);
HIR::Item *impl_ref = ctx->get_mappings ()->lookup_hir_item (
@@ -114,18 +185,13 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
CompileInherentImplItem::Compile (self, resolved_item, ctx,
true, lookup);
}
- else
- {
- rust_error_at (expr.get_locus (),
- "failed to lookup definition declaration");
- return;
- }
}
if (!ctx->lookup_function_decl (lookup->get_ty_ref (), &fn))
{
- rust_fatal_error (expr.get_locus (),
- "forward declaration was not compiled");
+ resolved = ctx->get_backend ()->error_expression ();
+ rust_error_at (expr.get_locus (),
+ "forward declaration was not compiled");
return;
}
}
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index aa9aa2d..f422572 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -20,6 +20,8 @@
#include "rust-compile-item.h"
#include "rust-compile-expr.h"
#include "rust-compile-struct-field-expr.h"
+#include "rust-hir-trait-resolve.h"
+#include "rust-hir-path-probe.h"
#include "fnv-hash.h"
namespace Rust {
@@ -141,31 +143,105 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
expr.get_mappings ().get_crate_num (), ref, nullptr);
if (resolved_item == nullptr)
{
- rust_error_at (expr.get_locus (),
- "failed to lookup forward declaration");
- return;
- }
+ // it might be resolved to a trait item
+ HIR::TraitItem *trait_item
+ = ctx->get_mappings ()->lookup_hir_trait_item (
+ expr.get_mappings ().get_crate_num (), ref);
+ HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping (
+ trait_item->get_mappings ().get_hirid ());
+
+ Resolver::TraitReference &trait_ref
+ = Resolver::TraitResolver::error_node ();
+ bool ok = ctx->get_tyctx ()->lookup_trait_reference (
+ trait->get_mappings ().get_defid (), trait_ref);
+ rust_assert (ok);
+
+ TyTy::BaseType *receiver = nullptr;
+ ok = ctx->get_tyctx ()->lookup_receiver (
+ expr.get_mappings ().get_hirid (), &receiver);
+ rust_assert (ok);
+
+ if (receiver->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver);
+ receiver = p->resolve ();
+ }
- TyTy::BaseType *self_type = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (
- expr.get_receiver ()->get_mappings ().get_hirid (), &self_type))
- {
- rust_error_at (expr.get_locus (),
- "failed to resolve type for self param");
- return;
- }
+ // the type resolver can only resolve type bounds to their trait
+ // item so its up to us to figure out if this path should resolve
+ // to an trait-impl-block-item or if it can be defaulted to the
+ // trait-impl-item's definition
+ std::vector<Resolver::PathProbeCandidate> candidates
+ = Resolver::PathProbeType::Probe (
+ receiver, expr.get_method_name ().get_segment (), true, false,
+ true);
- if (!fntype->has_subsititions_defined ())
- CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true);
+ if (candidates.size () == 0)
+ {
+ // this means we are defaulting back to the trait_item if
+ // possible
+ // TODO
+ gcc_unreachable ();
+ }
+ else
+ {
+ Resolver::PathProbeCandidate &candidate = candidates.at (0);
+ rust_assert (candidate.is_impl_candidate ());
+
+ HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
+
+ TyTy::BaseType *self_type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_receiver ()->get_mappings ().get_hirid (),
+ &self_type))
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to resolve type for self param");
+ return;
+ }
+
+ if (!fntype->has_subsititions_defined ())
+ CompileInherentImplItem::Compile (self_type, impl_item, ctx,
+ true);
+ else
+ CompileInherentImplItem::Compile (self_type, impl_item, ctx,
+ true, fntype);
+
+ if (!ctx->lookup_function_decl (
+ impl_item->get_impl_mappings ().get_hirid (), &fn))
+ {
+ translated = ctx->get_backend ()->error_expression ();
+ rust_error_at (expr.get_locus (),
+ "forward declaration was not compiled");
+ return;
+ }
+ }
+ }
else
- CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true,
- fntype);
-
- if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
{
- rust_error_at (expr.get_locus (),
- "forward declaration was not compiled");
- return;
+ TyTy::BaseType *self_type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_receiver ()->get_mappings ().get_hirid (), &self_type))
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to resolve type for self param");
+ return;
+ }
+
+ if (!fntype->has_subsititions_defined ())
+ CompileInherentImplItem::Compile (self_type, resolved_item, ctx,
+ true);
+ else
+ CompileInherentImplItem::Compile (self_type, resolved_item, ctx,
+ true, fntype);
+
+ if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
+ {
+ translated = ctx->get_backend ()->error_expression ();
+ rust_error_at (expr.get_locus (),
+ "forward declaration was not compiled");
+ return;
+ }
}
}
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 3ad06c8..ba04339 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -124,6 +124,11 @@ public:
return type->get_mappings ();
}
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeParam *clone_generic_param_impl () const override
diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h
index 87dffcf..8d75d02 100644
--- a/gcc/rust/hir/tree/rust-hir-type.h
+++ b/gcc/rust/hir/tree/rust-hir-type.h
@@ -67,6 +67,10 @@ public:
BoundType get_bound_type () const final override { return TRAITBOUND; }
+ TypePath &get_path () { return type_path; }
+
+ const TypePath &get_path () const { return type_path; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 1b7aa4d..8e3ca31 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -23,6 +23,7 @@
#include "rust-hir-full.h"
#include "rust-tyty.h"
#include "rust-substitution-mapper.h"
+#include "rust-hir-type-bounds.h"
namespace Rust {
namespace Resolver {
@@ -34,12 +35,80 @@ struct PathProbeCandidate
IMPL_CONST,
IMPL_TYPE_ALIAS,
IMPL_FUNC,
+
+ TRAIT_ITEM_CONST,
+ TRAIT_TYPE_ALIAS,
+ TRAIT_FUNC,
+ };
+
+ struct ImplItemCandidate
+ {
+ HIR::ImplItem *impl_item;
+ HIR::ImplBlock *parent;
+ };
+
+ struct TraitItemCandidate
+ {
+ const TraitReference &trait_ref;
+ const TraitItemReference &item_ref;
};
CandidateType type;
- HIR::ImplItem *impl_item;
TyTy::BaseType *ty;
- HIR::ImplBlock *parent;
+ Location locus;
+ union Candidate
+ {
+ ImplItemCandidate impl;
+ TraitItemCandidate trait;
+
+ Candidate (ImplItemCandidate impl) : impl (impl) {}
+ Candidate (TraitItemCandidate trait) : trait (trait) {}
+ } item;
+
+ PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
+ ImplItemCandidate impl)
+ : type (type), ty (ty), item (impl)
+ {}
+
+ PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
+ TraitItemCandidate trait)
+ : type (type), ty (ty), item (trait)
+ {}
+
+ std::string as_string () const
+ {
+ return "PathProbe candidate TODO - as_string";
+ }
+
+ bool is_impl_candidate () const
+ {
+ switch (type)
+ {
+ case IMPL_CONST:
+ case IMPL_TYPE_ALIAS:
+ case IMPL_FUNC:
+ return true;
+
+ default:
+ return false;
+ }
+ gcc_unreachable ();
+ }
+
+ bool is_trait_candidate () const
+ {
+ switch (type)
+ {
+ case TRAIT_ITEM_CONST:
+ case TRAIT_TYPE_ALIAS:
+ case TRAIT_FUNC:
+ return true;
+
+ default:
+ return false;
+ }
+ gcc_unreachable ();
+ }
};
class PathProbeType : public TypeCheckBase
@@ -48,32 +117,33 @@ class PathProbeType : public TypeCheckBase
public:
static std::vector<PathProbeCandidate>
- Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name)
+ Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &segment_name, bool probe_impls,
+ bool probe_bounds, bool ignore_mandatory_trait_items)
{
PathProbeType probe (receiver, segment_name);
- probe.mappings->iterate_impl_items (
- [&] (HirId id, HIR::ImplItem *item,
- HIR::ImplBlock *impl) mutable -> bool {
- probe.process_candidate (id, item, impl);
- return true;
- });
+ if (probe_impls)
+ probe.process_impl_items_for_candidates ();
- return probe.candidates;
- }
+ if (!probe_bounds)
+ return probe.candidates;
- void process_candidate (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl)
- {
- current_impl = impl;
- HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid ();
- TyTy::BaseType *impl_block_ty = nullptr;
- bool ok = context->lookup_type (impl_ty_id, &impl_block_ty);
- rust_assert (ok);
+ std::vector<std::reference_wrapper<TraitReference>> probed_bounds
+ = TypeBoundsProbe::Probe (receiver);
- if (!receiver->can_eq (impl_block_ty, false))
- return;
+ std::vector<std::reference_wrapper<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);
+ }
- // lets visit the impl_item
- item->accept_vis (*this);
+ std::vector<std::reference_wrapper<const TraitReference>> union_type_bounds
+ = probe.union_bounds (probed_bounds, specified_bounds);
+ probe.process_traits_for_candidates (union_type_bounds,
+ ignore_mandatory_trait_items);
+ return probe.candidates;
}
void visit (HIR::TypeAlias &alias) override
@@ -86,9 +156,11 @@ public:
bool ok = context->lookup_type (tyid, &ty);
rust_assert (ok);
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
+ current_impl};
PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, &alias, ty,
- current_impl};
+ PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
+ alias.get_locus (), impl_item_candidate};
candidates.push_back (std::move (candidate));
}
}
@@ -103,9 +175,11 @@ public:
bool ok = context->lookup_type (tyid, &ty);
rust_assert (ok);
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
+ current_impl};
PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_CONST, &constant, ty,
- current_impl};
+ PathProbeCandidate::CandidateType::IMPL_CONST, ty,
+ constant.get_locus (), impl_item_candidate};
candidates.push_back (std::move (candidate));
}
}
@@ -120,20 +194,146 @@ public:
bool ok = context->lookup_type (tyid, &ty);
rust_assert (ok);
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
+ current_impl};
PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_FUNC, &function, ty,
- current_impl};
+ PathProbeCandidate::CandidateType::IMPL_FUNC, ty,
+ function.get_locus (), impl_item_candidate};
candidates.push_back (std::move (candidate));
}
}
private:
- PathProbeType (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query)
+ void process_impl_items_for_candidates ()
+ {
+ mappings->iterate_impl_items ([&] (HirId id, HIR::ImplItem *item,
+ HIR::ImplBlock *impl) mutable -> bool {
+ process_impl_item_candidate (id, item, impl);
+ return true;
+ });
+ }
+
+ void process_impl_item_candidate (HirId id, HIR::ImplItem *item,
+ HIR::ImplBlock *impl)
+ {
+ current_impl = impl;
+ HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid ();
+ TyTy::BaseType *impl_block_ty = nullptr;
+ bool ok = context->lookup_type (impl_ty_id, &impl_block_ty);
+ rust_assert (ok);
+
+ if (!receiver->can_eq (impl_block_ty, false))
+ return;
+
+ // lets visit the impl_item
+ item->accept_vis (*this);
+ }
+
+ void process_traits_for_candidates (
+ const std::vector<std::reference_wrapper<const TraitReference>> traits,
+ bool ignore_mandatory_trait_items)
+ {
+ 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 ())
+ continue;
+
+ 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 ())
+ {
+ case TraitItemReference::TraitItemType::FN:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
+ break;
+ case TraitItemReference::TraitItemType::CONST:
+ candidate_type
+ = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
+ break;
+ case TraitItemReference::TraitItemType::TYPE:
+ candidate_type
+ = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
+ break;
+
+ case TraitItemReference::TraitItemType::ERROR:
+ gcc_unreachable ();
+ break;
+ }
+
+ 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)
+ {
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
+ TyTy::SubstitutionParamMapping *param = nullptr;
+ for (auto &param_mapping : fn->get_substs ())
+ {
+ const HIR::TypeParam &type_param
+ = param_mapping.get_generic_param ();
+ if (type_param.get_type_representation ().compare ("Self") == 0)
+ {
+ param = &param_mapping;
+ break;
+ }
+ }
+ rust_assert (param != nullptr);
+
+ std::vector<TyTy::SubstitutionArg> mappings;
+ mappings.push_back (
+ TyTy::SubstitutionArg (param, receiver->clone ()));
+
+ Location locus; // FIXME
+ TyTy::SubstitutionArgumentMappings args (std::move (mappings),
+ locus);
+ trait_item_tyty
+ = SubstMapperInternal::Resolve (trait_item_tyty, args);
+ }
+
+ PathProbeCandidate::TraitItemCandidate trait_item_candidate{
+ trait_ref, trait_item_ref};
+ PathProbeCandidate candidate{candidate_type,
+ trait_item_tyty,
+ trait_ref.get_locus (),
+ {trait_item_candidate}};
+ candidates.push_back (std::move (candidate));
+ }
+ }
+
+private:
+ PathProbeType (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &query)
: TypeCheckBase (), receiver (receiver), search (query),
current_impl (nullptr)
{}
- TyTy::BaseType *receiver;
+ 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::map<DefId, std::reference_wrapper<const TraitReference>> mapper;
+ for (const TraitReference &ref : a)
+ {
+ mapper.insert ({ref.get_mappings ().get_defid (), ref});
+ }
+ for (const TraitReference &ref : b)
+ {
+ mapper.insert ({ref.get_mappings ().get_defid (), ref});
+ }
+
+ std::vector<std::reference_wrapper<const TraitReference>> union_set;
+ for (auto it = mapper.begin (); it != mapper.end (); it++)
+ {
+ union_set.push_back (it->second);
+ }
+ return union_set;
+ }
+
+ const TyTy::BaseType *receiver;
const HIR::PathIdentSegment &search;
std::vector<PathProbeCandidate> candidates;
HIR::ImplBlock *current_impl;
@@ -150,7 +350,22 @@ public:
RichLocation r (query_locus);
ReportMultipleCandidateError visitor (r);
for (auto &c : candidates)
- c.impl_item->accept_vis (visitor);
+ {
+ switch (c.type)
+ {
+ case PathProbeCandidate::CandidateType::IMPL_CONST:
+ case PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS:
+ case PathProbeCandidate::CandidateType::IMPL_FUNC:
+ c.item.impl.impl_item->accept_vis (visitor);
+ break;
+
+ 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 ());
+ break;
+ }
+ }
rust_error_at (r, "multiple applicable items in scope for: %s",
query.as_string ().c_str ());
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
index 35c0fef..b19c38a 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-ref.h
@@ -56,6 +56,7 @@ public:
locus = other.locus;
context = other.context;
+ inherited_substitutions.clear ();
inherited_substitutions.reserve (other.inherited_substitutions.size ());
for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
inherited_substitutions.push_back (other.inherited_substitutions.at (i));
@@ -221,6 +222,21 @@ public:
+ "]";
}
+ const Analysis::NodeMapping &get_mappings () const
+ {
+ return hir_trait_ref->get_mappings ();
+ }
+
+ const TraitItemReference &lookup_trait_item (const std::string &ident) const
+ {
+ for (auto &item : item_refs)
+ {
+ if (ident.compare (item.get_identifier ()) == 0)
+ return item;
+ }
+ return TraitItemReference::error_node ();
+ }
+
const TraitItemReference &
lookup_trait_item (const std::string &ident,
TraitItemReference::TraitItemType type) const
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index 3de68c8..6d7c864 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -121,8 +121,7 @@ private:
if (!resolver->lookup_resolved_type (path.get_mappings ().get_nodeid (),
&ref))
{
- rust_fatal_error (path.get_locus (),
- "Failed to resolve path to node-id");
+ rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
return error_node ();
}
@@ -130,8 +129,7 @@ private:
if (!mappings->lookup_node_to_hir (mappings->get_current_crate (), ref,
&hir_node))
{
- rust_fatal_error (path.get_locus (),
- "Failed to resolve path to hir-id");
+ rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
return error_node ();
}
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
new file mode 100644
index 0000000..d97c0f5
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_TYPE_BOUNDS_H
+#define RUST_HIR_TYPE_BOUNDS_H
+
+#include "rust-hir-type-check-base.h"
+#include "rust-hir-full.h"
+#include "rust-tyty.h"
+
+namespace Rust {
+namespace Resolver {
+
+class TypeBoundsProbe : public TypeCheckBase
+{
+ using Rust::Resolver::TypeCheckBase::visit;
+
+public:
+ static std::vector<std::reference_wrapper<TraitReference>>
+ Probe (const TyTy::BaseType *receiver)
+ {
+ TypeBoundsProbe probe (receiver);
+ probe.scan ();
+ return probe.trait_references;
+ }
+
+private:
+ void scan ();
+
+private:
+ TypeBoundsProbe (const TyTy::BaseType *receiver)
+ : TypeCheckBase (), receiver (receiver)
+ {}
+
+ const TyTy::BaseType *receiver;
+ std::vector<std::reference_wrapper<TraitReference>> trait_references;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_HIR_TYPE_BOUNDS_H
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index ae71611..f05ab86 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -28,6 +28,8 @@
namespace Rust {
namespace Resolver {
+class TraitReference;
+
// base class to allow derivatives to overload as needed
class TypeCheckBase : public HIR::HIRVisitor
{
@@ -200,6 +202,8 @@ protected:
context (TypeCheckContext::get ())
{}
+ TraitReference &resolve_trait_path (HIR::TypePath &);
+
Analysis::Mappings *mappings;
Resolver *resolver;
TypeCheckContext *context;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index bd42b4c..7f1a83d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -205,15 +205,25 @@ public:
return;
}
+ context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
+
// https://doc.rust-lang.org/reference/expressions/method-call-expr.html
// method resolution is complex in rust once we start handling generics and
// traits. For now we only support looking up the valid name in impl blocks
// which is simple. There will need to be adjustments to ensure we can turn
// the receiver into borrowed references etc
+ bool reciever_is_generic
+ = receiver_tyty->get_kind () == TyTy::TypeKind::PARAM;
+ bool probe_bounds = true;
+ bool probe_impls = !reciever_is_generic;
+ bool ignore_mandatory_trait_items = !reciever_is_generic;
+
auto candidates
= PathProbeType::Probe (receiver_tyty,
- expr.get_method_name ().get_segment ());
+ expr.get_method_name ().get_segment (),
+ probe_impls, probe_bounds,
+ ignore_mandatory_trait_items);
if (candidates.size () == 0)
{
rust_error_at (expr.get_locus (),
@@ -229,13 +239,18 @@ public:
}
auto resolved_candidate = candidates.at (0);
- HIR::ImplItem *resolved_method = resolved_candidate.impl_item;
TyTy::BaseType *lookup_tyty = resolved_candidate.ty;
+ NodeId resolved_node_id
+ = resolved_candidate.is_impl_candidate ()
+ ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
+ .get_nodeid ()
+ : resolved_candidate.item.trait.item_ref.get_mappings ()
+ .get_nodeid ();
if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
{
RichLocation r (expr.get_method_name ().get_locus ());
- r.add_range (resolved_method->get_impl_locus ());
+ r.add_range (resolved_candidate.locus);
rust_error_at (r, "associated impl item is not a method");
return;
}
@@ -245,7 +260,7 @@ public:
if (!fn->is_method ())
{
RichLocation r (expr.get_method_name ().get_locus ());
- r.add_range (resolved_method->get_impl_locus ());
+ r.add_range (resolved_candidate.locus);
rust_error_at (r, "associated function is not a method");
return;
}
@@ -303,20 +318,25 @@ public:
}
}
- // apply any remaining generic arguments
- if (expr.get_method_name ().has_generic_args ())
- {
- HIR::GenericArgs &args = expr.get_method_name ().get_generic_args ();
- lookup
- = SubstMapper::Resolve (lookup, expr.get_method_name ().get_locus (),
- &args);
- if (lookup->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
- else if (lookup->needs_generic_substitutions ())
+ if (!reciever_is_generic)
{
- lookup = SubstMapper::InferSubst (lookup,
- expr.get_method_name ().get_locus ());
+ // apply any remaining generic arguments
+ if (expr.get_method_name ().has_generic_args ())
+ {
+ HIR::GenericArgs &args
+ = expr.get_method_name ().get_generic_args ();
+ lookup = SubstMapper::Resolve (lookup,
+ expr.get_method_name ().get_locus (),
+ &args);
+ if (lookup->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+ else if (lookup->needs_generic_substitutions ())
+ {
+ lookup
+ = SubstMapper::InferSubst (lookup,
+ expr.get_method_name ().get_locus ());
+ }
}
TyTy::BaseType *function_ret_tyty
@@ -333,9 +353,8 @@ public:
context->insert_type (expr.get_method_name ().get_mappings (), lookup);
// set up the resolved name on the path
- resolver->insert_resolved_name (
- expr.get_mappings ().get_nodeid (),
- resolved_method->get_impl_mappings ().get_nodeid ());
+ resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
+ resolved_node_id);
// return the result of the function back
infered = function_ret_tyty;
@@ -429,7 +448,7 @@ public:
if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
ref_node_id, &ref))
{
- rust_error_at (expr.get_locus (), "reverse lookup failure");
+ rust_error_at (expr.get_locus (), "123 reverse lookup failure");
return;
}
@@ -937,8 +956,16 @@ public:
{
HIR::PathExprSegment &seg = expr.get_segments ().at (i);
+ bool reciever_is_generic
+ = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
+ bool probe_bounds = true;
+ bool probe_impls = !reciever_is_generic;
+ bool ignore_mandatory_trait_items = !reciever_is_generic;
+
// probe the path
- auto candidates = PathProbeType::Probe (tyseg, seg.get_segment ());
+ auto candidates
+ = PathProbeType::Probe (tyseg, seg.get_segment (), probe_impls,
+ probe_bounds, ignore_mandatory_trait_items);
if (candidates.size () == 0)
{
rust_error_at (
@@ -954,11 +981,21 @@ public:
return;
}
- auto candidate = candidates.at (0);
+ auto &candidate = candidates.at (0);
prev_segment = tyseg;
tyseg = candidate.ty;
- resolved_node_id
- = candidate.impl_item->get_impl_mappings ().get_nodeid ();
+
+ if (candidate.is_impl_candidate ())
+ {
+ resolved_node_id
+ = candidate.item.impl.impl_item->get_impl_mappings ()
+ .get_nodeid ();
+ }
+ else
+ {
+ resolved_node_id
+ = candidate.item.trait.item_ref.get_mappings ().get_nodeid ();
+ }
if (seg.has_generic_args ())
{
@@ -977,6 +1014,7 @@ public:
}
}
+ context->insert_receiver (expr.get_mappings ().get_hirid (), prev_segment);
if (tyseg->needs_generic_substitutions ())
{
Location locus = expr.get_segments ().back ().get_locus ();
@@ -984,8 +1022,9 @@ public:
{
auto used_args_in_prev_segment
= GetUsedSubstArgs::From (prev_segment);
- tyseg
- = SubstMapperInternal::Resolve (tyseg, used_args_in_prev_segment);
+ if (!used_args_in_prev_segment.is_error ())
+ tyseg = SubstMapperInternal::Resolve (tyseg,
+ used_args_in_prev_segment);
}
else
{
@@ -1214,7 +1253,13 @@ private:
{
if (is_root)
{
- rust_error_at (seg.get_locus (), "reverse lookup failure");
+ rust_error_at (seg.get_locus (), "456 reverse lookup failure");
+ rust_debug_loc (
+ seg.get_locus (),
+ "failure with [%s] mappings [%s] ref_node_id [%u]",
+ seg.as_string ().c_str (),
+ seg.get_mappings ().as_string ().c_str (), ref_node_id);
+
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
}
return root_tyty;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 0f75c54..91d9c53 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -215,7 +215,7 @@ private:
{}
void
- check_for_unconstrained (std::vector<std::unique_ptr<HIR::Type> > &type_args)
+ check_for_unconstrained (std::vector<std::unique_ptr<HIR::Type>> &type_args)
{
std::map<std::string, Location> param_location_map;
std::set<std::string> param_tys;
@@ -270,8 +270,31 @@ public:
if (param.has_type ())
TypeCheckType::Resolve (param.get_type ().get ());
+ std::vector<TyTy::TypeBoundPredicate> specified_bounds;
+ if (param.has_type_param_bounds ())
+ {
+ for (auto &bound : param.get_type_param_bounds ())
+ {
+ switch (bound->get_bound_type ())
+ {
+ case HIR::TypeParamBound::BoundType::TRAITBOUND: {
+ HIR::TraitBound *b
+ = static_cast<HIR::TraitBound *> (bound.get ());
+ TyTy::TypeBoundPredicate predicate (
+ &resolve_trait_path (b->get_path ()));
+ specified_bounds.push_back (std::move (predicate));
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
resolved = new TyTy::ParamType (param.get_type_representation (),
- param.get_mappings ().get_hirid (), param);
+ param.get_mappings ().get_hirid (), param,
+ specified_bounds);
}
private:
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index 66adfcb..4b66fdb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -418,6 +418,7 @@ TraitItemReference::TraitItemReference (TraitItemReference const &other)
type (other.type), hir_trait_item (other.hir_trait_item),
locus (other.locus), self (other.self), context (TypeCheckContext::get ())
{
+ inherited_substitutions.clear ();
inherited_substitutions.reserve (other.inherited_substitutions.size ());
for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
inherited_substitutions.push_back (other.inherited_substitutions.at (i));
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 0298068..b171123 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -102,6 +102,21 @@ public:
return true;
}
+ void insert_receiver (HirId id, TyTy::BaseType *t)
+ {
+ receiver_context[id] = t;
+ }
+
+ bool lookup_receiver (HirId id, TyTy::BaseType **ref)
+ {
+ auto it = receiver_context.find (id);
+ if (it == receiver_context.end ())
+ return false;
+
+ *ref = it->second;
+ return true;
+ }
+
private:
TypeCheckContext ();
@@ -111,6 +126,7 @@ private:
std::vector<TyTy::BaseType *> return_type_stack;
std::vector<TyTy::BaseType *> loop_type_stack;
std::map<DefId, TraitReference> trait_context;
+ std::map<HirId, TyTy::BaseType *> receiver_context;
};
class TypeResolution
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 3730faa..a3c00da 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -280,24 +280,24 @@ public:
args = type.get_substitution_arguments ();
}
- void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::TupleType &) override { gcc_unreachable (); }
- void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
- void visit (TyTy::ArrayType &) override { gcc_unreachable (); }
- void visit (TyTy::BoolType &) override { gcc_unreachable (); }
- void visit (TyTy::IntType &) override { gcc_unreachable (); }
- void visit (TyTy::UintType &) override { gcc_unreachable (); }
- void visit (TyTy::FloatType &) override { gcc_unreachable (); }
- void visit (TyTy::USizeType &) override { gcc_unreachable (); }
- void visit (TyTy::ISizeType &) override { gcc_unreachable (); }
- void visit (TyTy::ErrorType &) override { gcc_unreachable (); }
- void visit (TyTy::CharType &) override { gcc_unreachable (); }
- void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
- void visit (TyTy::PointerType &) override { gcc_unreachable (); }
- void visit (TyTy::ParamType &) override { gcc_unreachable (); }
- void visit (TyTy::StrType &) override { gcc_unreachable (); }
- void visit (TyTy::NeverType &) override { gcc_unreachable (); }
- void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
+ void visit (TyTy::InferType &) override {}
+ void visit (TyTy::TupleType &) override {}
+ void visit (TyTy::FnPtr &) override {}
+ void visit (TyTy::ArrayType &) override {}
+ void visit (TyTy::BoolType &) override {}
+ void visit (TyTy::IntType &) override {}
+ void visit (TyTy::UintType &) override {}
+ void visit (TyTy::FloatType &) override {}
+ void visit (TyTy::USizeType &) override {}
+ void visit (TyTy::ISizeType &) override {}
+ void visit (TyTy::ErrorType &) override {}
+ void visit (TyTy::CharType &) override {}
+ void visit (TyTy::ReferenceType &) override {}
+ void visit (TyTy::PointerType &) override {}
+ void visit (TyTy::ParamType &) override {}
+ void visit (TyTy::StrType &) override {}
+ void visit (TyTy::NeverType &) override {}
+ void visit (TyTy::PlaceholderType &) override {}
private:
GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {}
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
new file mode 100644
index 0000000..a480155
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -0,0 +1,75 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-bounds.h"
+#include "rust-hir-trait-resolve.h"
+
+namespace Rust {
+namespace Resolver {
+
+void
+TypeBoundsProbe::scan ()
+{
+ std::vector<HIR::TypePath *> possible_trait_paths;
+ mappings->iterate_impl_blocks (
+ [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
+ // we are filtering for trait-impl-blocks
+ if (!impl->has_trait_ref ())
+ return true;
+
+ TyTy::BaseType *impl_type = nullptr;
+ bool ok
+ = context->lookup_type (impl->get_type ()->get_mappings ().get_hirid (),
+ &impl_type);
+ if (!ok)
+ return true;
+
+ if (!receiver->can_eq (impl_type, false))
+ return true;
+
+ possible_trait_paths.push_back (impl->get_trait_ref ().get ());
+ return true;
+ });
+
+ for (auto &trait_path : possible_trait_paths)
+ {
+ TraitReference &trait_ref = TraitResolver::Resolve (*trait_path);
+
+ if (!trait_ref.is_error ())
+ trait_references.push_back (trait_ref);
+ }
+}
+
+TraitReference &
+TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
+{
+ return TraitResolver::Resolve (path);
+}
+
+} // namespace Resolver
+
+namespace TyTy {
+
+std::string
+TypeBoundPredicate::as_string () const
+{
+ return reference->as_string ();
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index a1315fb..a2ae4fa 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -243,6 +243,7 @@ SubstitutionParamMapping::override_context ()
auto mappings = Analysis::Mappings::get ();
auto context = Resolver::TypeCheckContext::get ();
+
context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
UNKNOWN_NODEID,
param->get_ref (),
@@ -1768,7 +1769,7 @@ BaseType *
ParamType::clone () const
{
return new ParamType (get_symbol (), get_ref (), get_ty_ref (), param,
- get_combined_refs ());
+ get_specified_bounds (), get_combined_refs ());
}
std::string
@@ -1780,8 +1781,6 @@ ParamType::get_symbol () const
BaseType *
ParamType::resolve () const
{
- rust_assert (can_resolve ());
-
TyVar var (get_ty_ref ());
BaseType *r = var.get_tyty ();
@@ -1795,7 +1794,10 @@ ParamType::resolve () const
r = v.get_tyty ();
}
- return TyVar (r->get_ty_ref ()).get_tyty ();
+ if (r->get_kind () == TypeKind::PARAM && (r->get_ref () == r->get_ty_ref ()))
+ return TyVar (r->get_ty_ref ()).get_tyty ();
+
+ return r;
}
bool
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 6abae53..13bab90 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -25,6 +25,10 @@
#include "rust-diagnostics.h"
namespace Rust {
+namespace Resolver {
+class TraitReference;
+}
+
namespace TyTy {
// https://rustc-dev-guide.rust-lang.org/type-inference.html#inference-variables
@@ -125,9 +129,56 @@ public:
}
};
+class TypeBoundPredicate
+{
+public:
+ TypeBoundPredicate (Resolver::TraitReference *reference)
+ : reference (reference)
+ {}
+
+ TypeBoundPredicate (const TypeBoundPredicate &other)
+ : reference (other.reference)
+ {}
+
+ TypeBoundPredicate &operator= (const TypeBoundPredicate &other)
+ {
+ reference = other.reference;
+ return *this;
+ }
+
+ std::string as_string () const;
+
+ const Resolver::TraitReference *get () const { return reference; }
+
+private:
+ Resolver::TraitReference *reference;
+};
+
+class TypeBoundsMappings
+{
+protected:
+ TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds)
+ : specified_bounds (specified_bounds)
+ {}
+
+public:
+ std::vector<TypeBoundPredicate> &get_specified_bounds ()
+ {
+ return specified_bounds;
+ }
+
+ const std::vector<TypeBoundPredicate> &get_specified_bounds () const
+ {
+ return specified_bounds;
+ }
+
+protected:
+ std::vector<TypeBoundPredicate> specified_bounds;
+};
+
class TyVisitor;
class TyConstVisitor;
-class BaseType
+class BaseType : public TypeBoundsMappings
{
public:
virtual ~BaseType () {}
@@ -240,8 +291,15 @@ public:
protected:
BaseType (HirId ref, HirId ty_ref, TypeKind kind,
std::set<HirId> refs = std::set<HirId> ())
- : kind (kind), ref (ref), ty_ref (ty_ref), combined (refs),
- mappings (Analysis::Mappings::get ())
+ : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref),
+ combined (refs), mappings (Analysis::Mappings::get ())
+ {}
+
+ BaseType (HirId ref, HirId ty_ref, TypeKind kind,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref),
+ ty_ref (ty_ref), combined (refs), mappings (Analysis::Mappings::get ())
{}
TypeKind kind;
@@ -347,15 +405,18 @@ class ParamType : public BaseType
{
public:
ParamType (std::string symbol, HirId ref, HIR::GenericParam &param,
+ std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PARAM, refs), symbol (symbol), param (param)
+ : BaseType (ref, ref, TypeKind::PARAM, specified_bounds, refs),
+ symbol (symbol), param (param)
{}
ParamType (std::string symbol, HirId ref, HirId ty_ref,
HIR::GenericParam &param,
+ std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PARAM, refs), symbol (symbol),
- param (param)
+ : BaseType (ref, ty_ref, TypeKind::PARAM, specified_bounds, refs),
+ symbol (symbol), param (param)
{}
void accept_vis (TyVisitor &vis) override;
@@ -986,7 +1047,7 @@ public:
#define FNTYPE_IS_VARADIC_FLAG 0X04
FnType (HirId ref, DefId id, std::string identifier, uint8_t flags,
- std::vector<std::pair<HIR::Pattern *, BaseType *> > params,
+ std::vector<std::pair<HIR::Pattern *, BaseType *>> params,
BaseType *type, std::vector<SubstitutionParamMapping> subst_refs,
std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ref, TypeKind::FNDEF, refs),
@@ -1001,7 +1062,7 @@ public:
FnType (HirId ref, HirId ty_ref, DefId id, std::string identifier,
uint8_t flags,
- std::vector<std::pair<HIR::Pattern *, BaseType *> > params,
+ std::vector<std::pair<HIR::Pattern *, BaseType *>> params,
BaseType *type, std::vector<SubstitutionParamMapping> subst_refs,
std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ty_ref, TypeKind::FNDEF, refs),
@@ -1054,12 +1115,12 @@ public:
return get_params ().at (0).second;
}
- std::vector<std::pair<HIR::Pattern *, BaseType *> > &get_params ()
+ std::vector<std::pair<HIR::Pattern *, BaseType *>> &get_params ()
{
return params;
}
- const std::vector<std::pair<HIR::Pattern *, BaseType *> > &get_params () const
+ const std::vector<std::pair<HIR::Pattern *, BaseType *>> &get_params () const
{
return params;
}
@@ -1094,7 +1155,7 @@ public:
handle_substitions (SubstitutionArgumentMappings mappings) override final;
private:
- std::vector<std::pair<HIR::Pattern *, BaseType *> > params;
+ std::vector<std::pair<HIR::Pattern *, BaseType *>> params;
BaseType *type;
uint8_t flags;
std::string identifier;
diff --git a/gcc/testsuite/rust/compile/torture/traits8.rs b/gcc/testsuite/rust/compile/torture/traits8.rs
new file mode 100644
index 0000000..0e83a7d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits8.rs
@@ -0,0 +1,22 @@
+trait Foo {
+ fn default() -> i32;
+}
+
+struct Bar(i32);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl Foo for Bar {
+ fn default() -> i32 {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ 123
+ }
+}
+
+fn type_bound_test<T: Foo>() -> i32 {
+ T::default()
+}
+
+fn main() {
+ let a;
+ a = type_bound_test::<Bar>();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits9.rs b/gcc/testsuite/rust/compile/torture/traits9.rs
new file mode 100644
index 0000000..075a219
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits9.rs
@@ -0,0 +1,30 @@
+trait Foo {
+ fn default() -> i32;
+ fn get(self) -> i32;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+struct Bar(i32);
+impl Foo for Bar {
+ fn default() -> i32 {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ 123
+ }
+
+ fn get(self) -> i32 {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ self.0
+ }
+}
+
+fn type_bound_test<T: Foo>(a: T) -> i32 {
+ T::default() + a.get()
+}
+
+fn main() {
+ let a;
+ a = Bar(456);
+
+ let b;
+ b = type_bound_test(a);
+}