aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc19
-rw-r--r--gcc/rust/backend/rust-compile.cc18
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.cc64
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.h20
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc169
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h24
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc14
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h34
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc12
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.cc18
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h29
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc152
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h24
-rw-r--r--gcc/rust/typecheck/rust-tyty-coercion.h10
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h15
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc197
-rw-r--r--gcc/rust/typecheck/rust-tyty.h69
-rw-r--r--gcc/testsuite/rust/compile/torture/traits19.rs33
-rw-r--r--gcc/testsuite/rust/execute/torture/slice-magic.rs106
-rw-r--r--gcc/testsuite/rust/execute/torture/slice-magic2.rs106
22 files changed, 833 insertions, 307 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 49a6f2f..2128f25 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -747,8 +747,9 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
auto root = receiver->get_root ();
std::vector<Resolver::PathProbeCandidate> candidates
- = Resolver::PathProbeType::Probe (root, segment, true, false, true);
-
+ = Resolver::PathProbeType::Probe (root, segment, true /* probe_impls */,
+ false /* probe_bounds */,
+ true /* ignore_mandatory_trait_items */);
if (candidates.size () == 0)
{
// this means we are defaulting back to the trait_item if
@@ -776,12 +777,22 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
rust_assert (candidates.size () == 1);
auto &candidate = candidates.at (0);
rust_assert (candidate.is_impl_candidate ());
+ rust_assert (candidate.ty->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *candidate_call = static_cast<TyTy::FnType *> (candidate.ty);
HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
- if (!fntype->has_subsititions_defined ())
+ if (!candidate_call->has_subsititions_defined ())
return CompileInherentImplItem::Compile (impl_item, ctx);
- return CompileInherentImplItem::Compile (impl_item, ctx, fntype);
+ TyTy::BaseType *monomorphized = candidate_call;
+ if (candidate_call->needs_generic_substitutions ())
+ {
+ TyTy::BaseType *infer_impl_call
+ = candidate_call->infer_substitions (expr_locus);
+ monomorphized = infer_impl_call->unify (fntype);
+ }
+
+ return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized);
}
}
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 9e2c5b3..bd782b0 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -38,7 +38,6 @@ CompileCrate::~CompileCrate () {}
void
CompileCrate::Compile (HIR::Crate &crate, Context *ctx)
-
{
CompileCrate c (crate, ctx);
c.go ();
@@ -383,26 +382,11 @@ HIRCompileBase::compute_address_for_trait_item (
= self_bound->lookup_associated_item (ref->get_identifier ());
rust_assert (!associated_self_item.is_error ());
- // apply any generic arguments from this predicate
TyTy::BaseType *mono1 = associated_self_item.get_tyty_for_receiver (self);
- TyTy::BaseType *mono2 = nullptr;
- if (predicate->has_generic_args ())
- {
- mono2 = associated_self_item.get_tyty_for_receiver (
- self, predicate->get_generic_args ());
- }
- else
- {
- mono2 = associated_self_item.get_tyty_for_receiver (self);
- }
rust_assert (mono1 != nullptr);
rust_assert (mono1->get_kind () == TyTy::TypeKind::FNDEF);
TyTy::FnType *assocated_item_ty1 = static_cast<TyTy::FnType *> (mono1);
- rust_assert (mono2 != nullptr);
- rust_assert (mono2->get_kind () == TyTy::TypeKind::FNDEF);
- TyTy::FnType *assocated_item_ty2 = static_cast<TyTy::FnType *> (mono2);
-
// Lookup the impl-block for the associated impl_item if it exists
HIR::Function *associated_function = nullptr;
for (auto &impl_item : associated_impl_block->get_impl_items ())
@@ -434,7 +418,7 @@ HIRCompileBase::compute_address_for_trait_item (
{
TyTy::SubstitutionArgumentMappings mappings
= assocated_item_ty1->solve_missing_mappings_from_this (
- *assocated_item_ty2, *lookup_fntype);
+ *trait_item_fntype, *lookup_fntype);
lookup_fntype = lookup_fntype->handle_substitions (mappings);
}
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index ce7c4e1..104bd16 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -126,9 +126,11 @@ MethodResolver::Try (const TyTy::BaseType *r,
PathProbeCandidate c = PathProbeCandidate::get_error ();
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds
= r->get_specified_bounds ();
+ const std::vector<MethodResolver::predicate_candidate> predicate_items
+ = get_predicate_items (segment_name, *r, specified_bounds);
// 1. try raw
- MethodResolver raw (*r, segment_name, specified_bounds);
+ MethodResolver raw (*r, segment_name, predicate_items);
c = raw.select ();
if (!c.is_error ())
{
@@ -139,7 +141,7 @@ MethodResolver::Try (const TyTy::BaseType *r,
TyTy::ReferenceType *r1
= new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
Mutability::Imm);
- MethodResolver imm_ref (*r1, segment_name, specified_bounds);
+ MethodResolver imm_ref (*r1, segment_name, predicate_items);
c = imm_ref.select ();
if (!c.is_error ())
{
@@ -152,7 +154,7 @@ MethodResolver::Try (const TyTy::BaseType *r,
TyTy::ReferenceType *r2
= new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
Mutability::Mut);
- MethodResolver mut_ref (*r2, segment_name, specified_bounds);
+ MethodResolver mut_ref (*r2, segment_name, predicate_items);
c = mut_ref.select ();
if (!c.is_error ())
{
@@ -288,27 +290,6 @@ MethodResolver::select ()
TyTy::FnType *fntype;
};
- std::vector<precdicate_candidate> predicate_items;
- for (auto &bound : specified_bounds)
- {
- TyTy::TypeBoundPredicateItem lookup
- = bound.lookup_associated_item (segment_name.as_string ());
- if (lookup.is_error ())
- continue;
-
- bool is_fn = lookup.get_raw_item ()->get_trait_item_type ()
- == TraitItemReference::TraitItemType::FN;
- if (!is_fn)
- continue;
-
- TyTy::BaseType *ty = lookup.get_raw_item ()->get_tyty ();
- rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF);
- TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
-
- precdicate_candidate candidate{lookup, fnty};
- predicate_items.push_back (candidate);
- }
-
for (auto impl_item : inherent_impl_fns)
{
TyTy::FnType *fn = impl_item.ty;
@@ -342,9 +323,9 @@ MethodResolver::select ()
}
}
- for (auto predicate : predicate_items)
+ for (const auto &predicate : predicate_items)
{
- TyTy::FnType *fn = predicate.fntype;
+ const TyTy::FnType *fn = predicate.fntype;
rust_assert (fn->is_method ());
TyTy::BaseType *fn_self = fn->get_self_type ();
@@ -355,14 +336,10 @@ MethodResolver::select ()
const TraitItemReference *trait_item
= predicate.lookup.get_raw_item ();
- TyTy::BaseType *subst = predicate.lookup.get_tyty_for_receiver (
- receiver.get_root (),
- predicate.lookup.get_parent ()->get_generic_args ());
-
PathProbeCandidate::TraitItemCandidate c{trait_ref, trait_item,
nullptr};
return PathProbeCandidate (
- PathProbeCandidate::CandidateType::TRAIT_FUNC, subst,
+ PathProbeCandidate::CandidateType::TRAIT_FUNC, fn->clone (),
trait_item->get_locus (), c);
}
}
@@ -370,5 +347,30 @@ MethodResolver::select ()
return PathProbeCandidate::get_error ();
}
+std::vector<MethodResolver::predicate_candidate>
+MethodResolver::get_predicate_items (
+ const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
+ const std::vector<TyTy::TypeBoundPredicate> &specified_bounds)
+{
+ std::vector<predicate_candidate> predicate_items;
+ for (auto &bound : specified_bounds)
+ {
+ TyTy::TypeBoundPredicateItem lookup
+ = bound.lookup_associated_item (segment_name.as_string ());
+ if (lookup.is_error ())
+ continue;
+
+ TyTy::BaseType *ty = lookup.get_tyty_for_receiver (&receiver);
+ if (ty->get_kind () == TyTy::TypeKind::FNDEF)
+ {
+ TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
+ predicate_candidate candidate{lookup, fnty};
+ predicate_items.push_back (candidate);
+ }
+ }
+
+ return predicate_items;
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index f14300a..ef1038b 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -48,22 +48,32 @@ public:
bool autoderef_flag = false);
protected:
+ struct predicate_candidate
+ {
+ TyTy::TypeBoundPredicateItem lookup;
+ TyTy::FnType *fntype;
+ };
+
static MethodCandidate Try (const TyTy::BaseType *r,
const HIR::PathIdentSegment &segment_name,
std::vector<Adjustment> &adjustments);
+ static std::vector<predicate_candidate> get_predicate_items (
+ const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
+ const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
+
PathProbeCandidate select ();
- MethodResolver (const TyTy::BaseType &receiver,
- const HIR::PathIdentSegment &segment_name,
- const std::vector<TyTy::TypeBoundPredicate> &specified_bounds)
+ MethodResolver (
+ const TyTy::BaseType &receiver, const HIR::PathIdentSegment &segment_name,
+ const std::vector<MethodResolver::predicate_candidate> &predicate_items)
: receiver (receiver), segment_name (segment_name),
- specified_bounds (specified_bounds)
+ predicate_items (predicate_items)
{}
const TyTy::BaseType &receiver;
const HIR::PathIdentSegment &segment_name;
- const std::vector<TyTy::TypeBoundPredicate> &specified_bounds;
+ const std::vector<MethodResolver::predicate_candidate> &predicate_items;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
index 585fb6c..d8c8a19 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-ref.h
@@ -262,6 +262,8 @@ public:
return hir_trait_ref->get_mappings ();
}
+ DefId get_defid () const { return get_mappings ().get_defid (); }
+
bool lookup_hir_trait_item (const HIR::TraitItem &item,
TraitItemReference **ref)
{
@@ -436,6 +438,9 @@ public:
void setup_associated_types ();
+ void setup_associated_types2 (const TyTy::BaseType *self,
+ const TyTy::TypeBoundPredicate &bound);
+
void reset_associated_types ();
TyTy::BaseType *get_projected_type (const TraitItemReference *trait_item_ref,
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 54fdc02..b4e0efe 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -137,7 +137,7 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty)
TyTy::PlaceholderType *placeholder
= static_cast<TyTy::PlaceholderType *> (item_ty);
- placeholder->set_associated_type (ty->get_ref ());
+ placeholder->set_associated_type (ty->get_ty_ref ());
}
void
@@ -176,6 +176,173 @@ AssociatedImplTrait::setup_associated_types ()
}
void
+AssociatedImplTrait::setup_associated_types2 (
+ const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound)
+{
+ // compute the constrained impl block generic arguments based on self and the
+ // higher ranked trait bound
+ TyTy::BaseType *receiver = self->clone ();
+
+ // impl<Y> SliceIndex<[Y]> for Range<usize>
+ // vs
+ // I: SliceIndex<[<integer>]> and Range<<integer>>
+ //
+ // we need to figure out what Y is
+
+ TyTy::BaseType *associated_self = get_self ();
+ rust_assert (associated_self->can_eq (self, false));
+
+ // grab the parameters
+ HIR::ImplBlock &impl_block = *get_impl_block ();
+ std::vector<TyTy::SubstitutionParamMapping> substitutions;
+ for (auto &generic_param : impl_block.get_generic_params ())
+ {
+ switch (generic_param.get ()->get_kind ())
+ {
+ case HIR::GenericParam::GenericKind::LIFETIME:
+ // Skipping Lifetime completely until better handling.
+ break;
+
+ case HIR::GenericParam::GenericKind::TYPE: {
+ TyTy::BaseType *l = nullptr;
+ bool ok = context->lookup_type (
+ generic_param->get_mappings ().get_hirid (), &l);
+ if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ substitutions.push_back (TyTy::SubstitutionParamMapping (
+ static_cast<HIR::TypeParam &> (*generic_param),
+ static_cast<TyTy::ParamType *> (l)));
+ }
+ }
+ break;
+ }
+ }
+
+ // generate inference variables for these bound arguments so we can compute
+ // their values
+ Location locus;
+ std::vector<TyTy::SubstitutionArg> args;
+ for (auto &p : substitutions)
+ {
+ if (p.needs_substitution ())
+ {
+ TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
+ args.push_back (TyTy::SubstitutionArg (&p, infer_var.get_tyty ()));
+ }
+ else
+ {
+ args.push_back (
+ TyTy::SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
+ }
+ }
+
+ // this callback gives us the parameters that get substituted so we can
+ // compute the constrained type parameters for this impl block
+ std::map<std::string, HirId> param_mappings;
+ TyTy::ParamSubstCb param_subst_cb
+ = [&] (const TyTy::ParamType &p, const TyTy::SubstitutionArg &a) {
+ param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
+ };
+
+ TyTy::SubstitutionArgumentMappings infer_arguments (std::move (args), locus,
+ param_subst_cb);
+ TyTy::BaseType *impl_self_infer
+ = (associated_self->needs_generic_substitutions ())
+ ? SubstMapperInternal::Resolve (associated_self, infer_arguments)
+ : associated_self;
+
+ // FIXME this needs to do a lookup for the trait-reference DefId instead of
+ // assuming its the first one in the list
+ rust_assert (associated_self->num_specified_bounds () > 0);
+ TyTy::TypeBoundPredicate &impl_predicate
+ = associated_self->get_specified_bounds ().at (0);
+
+ // infer the arguments on the predicate
+ std::vector<TyTy::BaseType *> impl_trait_predicate_args;
+ for (const auto &arg : impl_predicate.get_substs ())
+ {
+ const TyTy::ParamType *p = arg.get_param_ty ();
+ if (p->get_symbol ().compare ("Self") == 0)
+ continue;
+
+ TyTy::BaseType *r = p->resolve ();
+ r = SubstMapperInternal::Resolve (r, infer_arguments);
+ impl_trait_predicate_args.push_back (r);
+ }
+
+ // we need to unify the receiver with the impl-block Self so that we compute
+ // the type correctly as our receiver may be generic and we are inferring its
+ // generic arguments and this Self might be the concrete version or vice
+ // versa.
+ auto result = receiver->unify (impl_self_infer);
+ rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+
+ // unify the bounds arguments
+ std::vector<TyTy::BaseType *> hrtb_bound_arguments;
+ for (const auto &arg : bound.get_substs ())
+ {
+ const TyTy::ParamType *p = arg.get_param_ty ();
+ if (p->get_symbol ().compare ("Self") == 0)
+ continue;
+
+ TyTy::BaseType *r = p->resolve ();
+ hrtb_bound_arguments.push_back (r);
+ }
+
+ rust_assert (impl_trait_predicate_args.size ()
+ == hrtb_bound_arguments.size ());
+ for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
+ {
+ TyTy::BaseType *a = impl_trait_predicate_args.at (i);
+ TyTy::BaseType *b = hrtb_bound_arguments.at (i);
+
+ result = a->unify (b);
+ rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+ }
+
+ // create the argument list
+ std::vector<TyTy::SubstitutionArg> associated_arguments;
+ for (auto &p : substitutions)
+ {
+ std::string symbol = p.get_param_ty ()->get_symbol ();
+ auto it = param_mappings.find (symbol);
+ rust_assert (it != param_mappings.end ());
+
+ HirId id = it->second;
+ TyTy::BaseType *argument = nullptr;
+ bool ok = context->lookup_type (id, &argument);
+ rust_assert (ok);
+
+ TyTy::SubstitutionArg arg (&p, argument);
+ associated_arguments.push_back (arg);
+ }
+
+ TyTy::SubstitutionArgumentMappings associated_type_args (
+ std::move (associated_arguments), locus);
+
+ ImplTypeIterator iter (*impl, [&] (HIR::TypeAlias &type) {
+ TraitItemReference *resolved_trait_item = nullptr;
+ bool ok = trait->lookup_trait_item (type.get_new_type_name (),
+ &resolved_trait_item);
+ if (!ok)
+ return;
+ if (resolved_trait_item->get_trait_item_type ()
+ != TraitItemReference::TraitItemType::TYPE)
+ return;
+
+ TyTy::BaseType *lookup;
+ if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
+ return;
+
+ // this might be generic
+ TyTy::BaseType *substituted
+ = SubstMapperInternal::Resolve (lookup, associated_type_args);
+ resolved_trait_item->associated_type_set (substituted);
+ });
+ iter.go ();
+}
+
+void
AssociatedImplTrait::reset_associated_types ()
{
trait->clear_associated_types ();
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index 806a46f..651af9d 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -141,24 +141,26 @@ private:
break;
}
}
-
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
+ // copy the substitition mappings
std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
for (auto &sub : substitutions)
self_subst_copy.push_back (sub.clone ());
- specified_bounds.push_back (
- TyTy::TypeBoundPredicate (trait_reference->get_mappings ().get_defid (),
- std::move (self_subst_copy),
- trait_reference->get_locus ()));
+ // They also inherit themselves as a bound this enables a trait item to
+ // reference other Self::trait_items
+ auto self_hrtb
+ = TyTy::TypeBoundPredicate (trait_reference->get_mappings ().get_defid (),
+ std::move (self_subst_copy),
+ trait_reference->get_locus ());
+ specified_bounds.push_back (self_hrtb);
+ // look for any
std::vector<const TraitReference *> super_traits;
if (trait_reference->has_type_param_bounds ())
{
@@ -171,12 +173,8 @@ private:
= 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,
- bound->get_locus ());
-
- specified_bounds.push_back (std::move (predicate));
+ auto predicate = get_predicate_from_bound (b->get_path ());
+ specified_bounds.push_back (predicate);
super_traits.push_back (predicate.get ());
}
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 539a3fe..a3d911e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -390,7 +390,6 @@ TypeCheckExpr::resolve_operator_overload (
rust_assert (fn->is_method ());
auto root = lhs->get_root ();
- bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
if (root->get_kind () == TyTy::TypeKind::ADT)
{
const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
@@ -446,13 +445,8 @@ TypeCheckExpr::resolve_operator_overload (
}
// handle generics
- if (!receiver_is_type_param)
- {
- if (lookup->needs_generic_substitutions ())
- {
- lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
- }
- }
+ if (lookup->needs_generic_substitutions ())
+ lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
// type check the arguments if required
TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
@@ -470,6 +464,10 @@ TypeCheckExpr::resolve_operator_overload (
fnparam.second->unify (rhs); // typecheck the rhs
}
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
+ fn = static_cast<TyTy::FnType *> (lookup);
+ fn->monomorphize ();
+
// get the return type
TyTy::BaseType *function_ret_tyty = type->get_return_type ()->clone ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 1b14693..560581d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -291,7 +291,6 @@ public:
}
auto root = receiver_tyty->get_root ();
- bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
if (root->get_kind () == TyTy::TypeKind::ADT)
{
const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
@@ -346,28 +345,21 @@ public:
}
}
- if (!receiver_is_type_param)
+ // apply any remaining generic arguments
+ if (expr.get_method_name ().has_generic_args ())
{
- // 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 ());
- }
+ 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 ());
}
-
- // ADT expected but got PARAM
TyTy::BaseType *function_ret_tyty
= TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 4c6c4a6..9846ed6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -79,6 +79,8 @@ public:
rust_assert (!trait_reference->is_error ());
specified_bound = get_predicate_from_bound (*ref.get ());
+ // FIXME error out maybe?
+ // if specified_Bound == TyTy::TypeBoundPredicate::error() ?
}
TyTy::BaseType *self = nullptr;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index cd6d67a..e2fa7f5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -45,8 +45,8 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
}
// Resolve the trait now
- TraitReference *trait_ref
- = TraitResolver::Resolve (*qual_path_type.get_trait ().get ());
+ std::unique_ptr<HIR::TypePath> &trait_path_ref = qual_path_type.get_trait ();
+ TraitReference *trait_ref = TraitResolver::Resolve (*trait_path_ref.get ());
if (trait_ref->is_error ())
return;
@@ -59,6 +59,14 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
if (expr.get_segments ().empty ())
return;
+ // get the predicate for the bound
+ auto specified_bound = get_predicate_from_bound (*trait_path_ref.get ());
+ if (specified_bound.is_error ())
+ return;
+
+ // inherit the bound
+ root->inherit_bounds ({specified_bound});
+
// we need resolve to the impl block
NodeId impl_resolved_id = UNKNOWN_NODEID;
bool ok = resolver->lookup_resolved_name (
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc
index f96b9b3..f80368a 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -26,19 +26,31 @@ TyTy::BaseType *
SubstMapperInternal::Resolve (TyTy::BaseType *base,
TyTy::SubstitutionArgumentMappings &mappings)
{
+ auto context = TypeCheckContext::get ();
+
SubstMapperInternal mapper (base->get_ref (), mappings);
base->accept_vis (mapper);
rust_assert (mapper.resolved != nullptr);
// insert these new implict types into the context
- bool is_param = mapper.resolved->get_kind () == TyTy::TypeKind::PARAM;
- if (!is_param)
+ TyTy::BaseType *unused = nullptr;
+ bool is_ty_available
+ = context->lookup_type (mapper.resolved->get_ty_ref (), &unused);
+ if (!is_ty_available)
{
- auto context = TypeCheckContext::get ();
context->insert_type (
Analysis::NodeMapping (0, 0, mapper.resolved->get_ty_ref (), 0),
mapper.resolved);
}
+ bool is_ref_available
+ = context->lookup_type (mapper.resolved->get_ref (), &unused);
+ if (!is_ref_available)
+ {
+ context->insert_type (Analysis::NodeMapping (0, 0,
+ mapper.resolved->get_ref (),
+ 0),
+ mapper.resolved);
+ }
return mapper.resolved;
}
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 5f17816..e12432e 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -232,19 +232,22 @@ public:
}
// nothing to do for these
- void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::FnPtr &) 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::StrType &) override { gcc_unreachable (); }
- void visit (TyTy::NeverType &) override { gcc_unreachable (); }
- void visit (TyTy::DynamicObjectType &) override { gcc_unreachable (); }
+ void visit (TyTy::InferType &type) override { resolved = type.clone (); }
+ void visit (TyTy::FnPtr &type) override { resolved = type.clone (); }
+ void visit (TyTy::BoolType &type) override { resolved = type.clone (); }
+ void visit (TyTy::IntType &type) override { resolved = type.clone (); }
+ void visit (TyTy::UintType &type) override { resolved = type.clone (); }
+ void visit (TyTy::FloatType &type) override { resolved = type.clone (); }
+ void visit (TyTy::USizeType &type) override { resolved = type.clone (); }
+ void visit (TyTy::ISizeType &type) override { resolved = type.clone (); }
+ void visit (TyTy::ErrorType &type) override { resolved = type.clone (); }
+ void visit (TyTy::CharType &type) override { resolved = type.clone (); }
+ void visit (TyTy::StrType &type) override { resolved = type.clone (); }
+ void visit (TyTy::NeverType &type) override { resolved = type.clone (); }
+ void visit (TyTy::DynamicObjectType &type) override
+ {
+ resolved = type.clone ();
+ }
private:
SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index b34db3b..e226400 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -106,28 +106,46 @@ TypeBoundPredicate::TypeBoundPredicate (
: SubstitutionRef (trait_reference.get_trait_substs (),
SubstitutionArgumentMappings::error ()),
reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
- args (HIR::GenericArgs::create_empty ()), error_flag (false)
-{}
+ error_flag (false)
+{
+ // we setup a dummy implict self argument
+ SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
+ used_arguments.get_mappings ().push_back (placeholder_self);
+}
TypeBoundPredicate::TypeBoundPredicate (
DefId reference, std::vector<SubstitutionParamMapping> substitutions,
Location locus)
: SubstitutionRef (std::move (substitutions),
SubstitutionArgumentMappings::error ()),
- reference (reference), locus (locus),
- args (HIR::GenericArgs::create_empty ()), error_flag (false)
-{}
+ reference (reference), locus (locus), error_flag (false)
+{
+ // we setup a dummy implict self argument
+ SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
+ used_arguments.get_mappings ().push_back (placeholder_self);
+}
TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
- : SubstitutionRef ({}, other.used_arguments), reference (other.reference),
- locus (other.locus), args (other.args), error_flag (other.error_flag)
+ : SubstitutionRef ({}, SubstitutionArgumentMappings::error ()),
+ reference (other.reference), locus (other.locus),
+ error_flag (other.error_flag)
{
substitutions.clear ();
- if (!other.is_error ())
+
+ for (const auto &p : other.get_substs ())
+ substitutions.push_back (p.clone ());
+
+ std::vector<SubstitutionArg> mappings;
+ for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
{
- for (const auto &p : other.get_substs ())
- substitutions.push_back (p.clone ());
+ const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
+ SubstitutionArg arg (oa);
+ mappings.push_back (std::move (arg));
}
+
+ used_arguments
+ = SubstitutionArgumentMappings (mappings,
+ other.used_arguments.get_locus ());
}
TypeBoundPredicate &
@@ -135,17 +153,25 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
{
reference = other.reference;
locus = other.locus;
- args = other.args;
error_flag = other.error_flag;
- used_arguments = other.used_arguments;
+ used_arguments = SubstitutionArgumentMappings::error ();
substitutions.clear ();
- if (!other.is_error ())
+ for (const auto &p : other.get_substs ())
+ substitutions.push_back (p.clone ());
+
+ std::vector<SubstitutionArg> mappings;
+ for (size_t i = 0; i < other.used_arguments.get_mappings ().size (); i++)
{
- for (const auto &p : other.get_substs ())
- substitutions.push_back (p.clone ());
+ const SubstitutionArg &oa = other.used_arguments.get_mappings ().at (i);
+ SubstitutionArg arg (oa);
+ mappings.push_back (std::move (arg));
}
+ used_arguments
+ = SubstitutionArgumentMappings (mappings,
+ other.used_arguments.get_locus ());
+
return *this;
}
@@ -203,17 +229,22 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args)
{
// we need to get the substitutions argument mappings but also remember that
// we have an implicit Self argument which we must be careful to respect
- rust_assert (used_arguments.is_empty ());
+ rust_assert (!used_arguments.is_empty ());
rust_assert (!substitutions.empty ());
- // we setup a dummy implict self argument
- SubstitutionArg placeholder_self (&substitutions.front (), nullptr);
- used_arguments.get_mappings ().push_back (std::move (placeholder_self));
-
// now actually perform a substitution
used_arguments = get_mappings_from_generic_args (*generic_args);
+
error_flag |= used_arguments.is_error ();
- args = *generic_args;
+ auto &subst_mappings = used_arguments;
+ for (auto &sub : get_substs ())
+ {
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool ok
+ = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
+ if (ok && arg.get_tyty () != nullptr)
+ sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
+ }
}
bool
@@ -235,47 +266,34 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const
return TypeBoundPredicateItem (this, trait_item_ref);
}
+TypeBoundPredicateItem
+TypeBoundPredicate::lookup_associated_item (
+ const Resolver::TraitItemReference *ref) const
+{
+ return lookup_associated_item (ref->get_identifier ());
+}
+
BaseType *
-TypeBoundPredicateItem::get_tyty_for_receiver (
- const TyTy::BaseType *receiver, const HIR::GenericArgs *bound_args)
+TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
{
TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
- 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
- = Resolver::SubstMapperInternal::Resolve (trait_item_tyty, args);
- }
+ if (parent->get_substitution_arguments ().is_empty ())
+ return trait_item_tyty;
- if (!parent->has_generic_args ())
+ const Resolver::TraitItemReference *tref = get_raw_item ();
+ bool is_associated_type = tref->get_trait_item_type ();
+ if (is_associated_type)
return trait_item_tyty;
- // FIXME LEAK this should really be const
- const HIR::GenericArgs *args
- = (bound_args != nullptr) ? bound_args : parent->get_generic_args ();
- HIR::GenericArgs *generic_args = new HIR::GenericArgs (*args);
- TyTy::BaseType *resolved
- = Resolver::SubstMapper::Resolve (trait_item_tyty, parent->get_locus (),
- generic_args);
+ SubstitutionArgumentMappings gargs = parent->get_substitution_arguments ();
+
+ // set up the self mapping
+ rust_assert (!gargs.is_empty ());
+ auto &sarg = gargs.get_mappings ().at (0);
+ SubstitutionArg self (sarg.get_param_mapping (), receiver->clone ());
+ gargs.get_mappings ()[0] = self;
- return resolved;
+ return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, gargs);
}
bool
TypeBoundPredicate::is_error () const
@@ -289,9 +307,25 @@ TypeBoundPredicate::is_error () const
}
BaseType *
-TypeBoundPredicate::handle_substitions (SubstitutionArgumentMappings mappings)
+TypeBoundPredicate::handle_substitions (
+ SubstitutionArgumentMappings subst_mappings)
{
- gcc_unreachable ();
+ for (auto &sub : get_substs ())
+ {
+ if (sub.get_param_ty () == nullptr)
+ continue;
+
+ ParamType *p = sub.get_param_ty ();
+ BaseType *r = p->resolve ();
+ BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
+
+ p->set_ty_ref (s->get_ty_ref ());
+ }
+
+ // FIXME more error handling at some point
+ // used_arguments = subst_mappings;
+ // error_flag |= used_arguments.is_error ();
+
return nullptr;
}
@@ -301,7 +335,7 @@ TypeBoundPredicate::requires_generic_args () const
if (is_error ())
return false;
- return substitutions.size () > 1 && args.is_empty ();
+ return substitutions.size () > 1;
}
// trait item reference
@@ -351,7 +385,7 @@ TypeBoundsMappings::raw_bounds_as_string () const
{
const TypeBoundPredicate &b = specified_bounds.at (i);
bool has_next = (i + 1) < specified_bounds.size ();
- buf += b.get_name () + (has_next ? " + " : "");
+ buf += b.as_string () + (has_next ? " + " : "");
}
return buf;
}
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index 34c8963..f3118ba 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -43,16 +43,19 @@ public:
return ok;
}
}
- else if (other->get_kind () == TypeKind::PLACEHOLDER)
+ if (other->get_kind () == TypeKind::PLACEHOLDER)
{
const PlaceholderType *p = static_cast<const PlaceholderType *> (other);
if (p->can_resolve ())
{
- const BaseType *resolved = p->resolve ();
- resolved->accept_vis (*this);
- return ok;
+ other = p->resolve ();
}
}
+ if (other->get_kind () == TypeKind::PROJECTION)
+ {
+ const ProjectionType *p = static_cast<const ProjectionType *> (other);
+ other = p->get ();
+ }
other->accept_vis (*this);
return ok;
@@ -1268,14 +1271,10 @@ public:
// to handle the typing of the struct
bool can_eq (const BaseType *other) override
{
- if (base->get_ref () == base->get_ty_ref ())
+ if (!base->can_resolve ())
return BaseCmp::can_eq (other);
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
- rust_assert (ok);
-
+ auto lookup = base->resolve ();
return lookup->can_eq (other, emit_error_flag);
}
@@ -1422,11 +1421,6 @@ public:
void visit (const SliceType &) override { ok = true; }
- void visit (const PlaceholderType &type) override
- {
- ok = base->get_symbol ().compare (type.get_symbol ()) == 0;
- }
-
private:
const BaseType *get_base () const override { return base; }
diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h
index 4deed55..c24f17e 100644
--- a/gcc/rust/typecheck/rust-tyty-coercion.h
+++ b/gcc/rust/typecheck/rust-tyty-coercion.h
@@ -53,12 +53,14 @@ public:
if (p->can_resolve ())
{
other = p->resolve ();
+ return get_base ()->coerce (other);
}
}
else if (other->get_kind () == TypeKind::PROJECTION)
{
ProjectionType *p = static_cast<ProjectionType *> (other);
other = p->get ();
+ return get_base ()->coerce (other);
}
other->accept_vis (*this);
@@ -1351,14 +1353,10 @@ public:
// to handle the typing of the struct
BaseType *coerce (BaseType *other) override final
{
- if (base->get_ref () == base->get_ty_ref ())
+ if (!base->can_resolve ())
return BaseCoercionRules::coerce (other);
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
- rust_assert (ok);
-
+ auto lookup = base->resolve ();
return lookup->unify (other);
}
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index c1fc2cd..7c50112 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -60,10 +60,7 @@ public:
if (other->get_kind () == TypeKind::PARAM)
{
ParamType *p = static_cast<ParamType *> (other);
- if (p->can_resolve ())
- {
- other = p->resolve ();
- }
+ other = p->resolve ();
}
else if (other->get_kind () == TypeKind::PLACEHOLDER)
{
@@ -71,12 +68,14 @@ public:
if (p->can_resolve ())
{
other = p->resolve ();
+ return get_base ()->unify (other);
}
}
else if (other->get_kind () == TypeKind::PROJECTION)
{
ProjectionType *p = static_cast<ProjectionType *> (other);
other = p->get ();
+ return get_base ()->unify (other);
}
other->accept_vis (*this);
@@ -1328,14 +1327,10 @@ public:
// to handle the typing of the struct
BaseType *unify (BaseType *other) override final
{
- if (base->get_ref () == base->get_ty_ref ())
+ if (!base->can_resolve ())
return BaseRules::unify (other);
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
- rust_assert (ok);
-
+ auto lookup = base->resolve ();
return lookup->unify (other);
}
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 1d197f5..156cc10 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -266,6 +266,23 @@ TyVar::get_implicit_infer_var (Location locus)
return TyVar (infer->get_ref ());
}
+TyVar
+TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst)
+{
+ if (orig->get_kind () != TyTy::TypeKind::PARAM)
+ return TyVar (subst->get_ty_ref ());
+ else if (subst->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ TyTy::ParamType *p = static_cast<TyTy::ParamType *> (subst);
+ if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ return TyVar (subst->get_ty_ref ());
+ }
+ }
+
+ return TyVar (subst->get_ref ());
+}
+
void
InferType::accept_vis (TyVisitor &vis)
{
@@ -442,10 +459,15 @@ SubstitutionParamMapping::need_substitution () const
}
bool
-SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus)
+SubstitutionParamMapping::fill_param_ty (
+ SubstitutionArgumentMappings &subst_mappings, Location locus)
{
- auto context = Resolver::TypeCheckContext::get ();
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
+ if (!ok)
+ return true;
+ TyTy::BaseType &type = *arg.get_tyty ();
if (type.get_kind () == TyTy::TypeKind::INFER)
{
type.inherit_bounds (*param);
@@ -467,43 +489,9 @@ SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus)
if (!param->bounds_compatible (type, locus, true))
return false;
- // setup any associated type mappings for the specified bonds and this
- // type
- auto candidates = Resolver::TypeBoundsProbe::Probe (&type);
- for (auto &specified_bound : param->get_specified_bounds ())
- {
- const Resolver::TraitReference *specified_bound_ref
- = specified_bound.get ();
-
- // since the bounds_compatible check has occurred we should be able to
- // assert on finding the trait references
- HirId associated_impl_block_id = UNKNOWN_HIRID;
- bool found = false;
- for (auto &bound : candidates)
- {
- const Resolver::TraitReference *bound_trait_ref = bound.first;
- const HIR::ImplBlock *associated_impl = bound.second;
-
- found = specified_bound_ref->is_equal (*bound_trait_ref);
- if (found)
- {
- rust_assert (associated_impl != nullptr);
- associated_impl_block_id
- = associated_impl->get_mappings ().get_hirid ();
- break;
- }
- }
-
- if (found && associated_impl_block_id != UNKNOWN_HIRID)
- {
- Resolver::AssociatedImplTrait *lookup_associated = nullptr;
- bool found_impl_trait = context->lookup_associated_trait_impl (
- associated_impl_block_id, &lookup_associated);
-
- if (found_impl_trait)
- lookup_associated->setup_associated_types ();
- }
- }
+ // recursively pass this down to all HRTB's
+ for (auto &bound : param->get_specified_bounds ())
+ bound.handle_substitions (subst_mappings);
param->set_ty_ref (type.get_ref ());
}
@@ -602,6 +590,7 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
args.get_locus ());
resolved = Resolver::SubstMapperInternal::Resolve (resolved,
intermediate);
+
if (resolved->get_kind () == TypeKind::ERROR)
return SubstitutionArgumentMappings::error ();
}
@@ -773,6 +762,65 @@ SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
return SubstitutionArgumentMappings (resolved_mappings, locus);
}
+bool
+SubstitutionRef::monomorphize ()
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ for (const auto &subst : get_substs ())
+ {
+ const TyTy::ParamType *pty = subst.get_param_ty ();
+
+ if (!pty->can_resolve ())
+ continue;
+
+ const TyTy::BaseType *binding = pty->resolve ();
+ if (binding->get_kind () == TyTy::TypeKind::PARAM)
+ continue;
+
+ for (const auto &bound : pty->get_specified_bounds ())
+ {
+ const Resolver::TraitReference *specified_bound_ref = bound.get ();
+
+ // setup any associated type mappings for the specified bonds and this
+ // type
+ auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
+
+ Resolver::AssociatedImplTrait *associated_impl_trait = nullptr;
+ for (auto &probed_bound : candidates)
+ {
+ const Resolver::TraitReference *bound_trait_ref
+ = probed_bound.first;
+ const HIR::ImplBlock *associated_impl = probed_bound.second;
+
+ HirId impl_block_id
+ = associated_impl->get_mappings ().get_hirid ();
+ Resolver::AssociatedImplTrait *associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id,
+ &associated);
+ rust_assert (found_impl_trait);
+
+ bool found_trait
+ = specified_bound_ref->is_equal (*bound_trait_ref);
+ bool found_self
+ = associated->get_self ()->can_eq (binding, false);
+ if (found_trait && found_self)
+ {
+ associated_impl_trait = associated;
+ break;
+ }
+ }
+
+ if (associated_impl_trait != nullptr)
+ {
+ associated_impl_trait->setup_associated_types2 (binding, bound);
+ }
+ }
+ }
+
+ return true;
+}
+
void
ADTType::accept_vis (TyVisitor &vis)
{
@@ -951,7 +999,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 (), subst_mappings.get_locus ());
+ sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
}
for (auto &variant : adt->get_variants ())
@@ -1059,6 +1107,7 @@ TupleType::handle_substitions (SubstitutionArgumentMappings mappings)
auto mappings_table = Analysis::Mappings::get ();
TupleType *tuple = static_cast<TupleType *> (clone ());
+ tuple->set_ref (mappings_table->get_next_hir_id ());
tuple->set_ty_ref (mappings_table->get_next_hir_id ());
for (size_t i = 0; i < tuple->fields.size (); i++)
@@ -1069,7 +1118,8 @@ TupleType::handle_substitions (SubstitutionArgumentMappings mappings)
BaseType *concrete
= Resolver::SubstMapperInternal::Resolve (field.get_tyty (),
mappings);
- tuple->fields[i] = TyVar (concrete->get_ty_ref ());
+ tuple->fields[i]
+ = TyVar::subst_covariant_var (field.get_tyty (), concrete);
}
}
@@ -1196,7 +1246,7 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
if (ok)
{
- sub.fill_param_ty (*arg.get_tyty (), subst_mappings.get_locus ());
+ sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
}
}
@@ -1538,7 +1588,7 @@ ArrayType::handle_substitions (SubstitutionArgumentMappings mappings)
// might be &T or &ADT so this needs to be recursive
auto base = ref->get_element_type ();
BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings);
- ref->element_type = TyVar (concrete->get_ty_ref ());
+ ref->element_type = TyVar::subst_covariant_var (base, concrete);
return ref;
}
@@ -1627,7 +1677,7 @@ SliceType::handle_substitions (SubstitutionArgumentMappings mappings)
// might be &T or &ADT so this needs to be recursive
auto base = ref->get_element_type ();
BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings);
- ref->element_type = TyVar (concrete->get_ty_ref ());
+ ref->element_type = TyVar::subst_covariant_var (base, concrete);
return ref;
}
@@ -2146,7 +2196,7 @@ ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
// might be &T or &ADT so this needs to be recursive
auto base = ref->get_base ();
BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings);
- ref->base = TyVar (concrete->get_ty_ref ());
+ ref->base = TyVar::subst_covariant_var (base, concrete);
return ref;
}
@@ -2232,7 +2282,7 @@ PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
// might be &T or &ADT so this needs to be recursive
auto base = ref->get_base ();
BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings);
- ref->base = TyVar (concrete->get_ty_ref ());
+ ref->base = TyVar::subst_covariant_var (base, concrete);
return ref;
}
@@ -2252,31 +2302,22 @@ ParamType::accept_vis (TyConstVisitor &vis) const
std::string
ParamType::as_string () const
{
- if (get_ref () == get_ty_ref ())
+ if (!can_resolve ())
{
return get_symbol () + " REF: " + std::to_string (get_ref ());
}
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (get_ty_ref (), &lookup);
- rust_assert (ok);
-
+ BaseType *lookup = resolve ();
return get_symbol () + "=" + lookup->as_string ();
}
std::string
ParamType::get_name () const
{
- if (get_ref () == get_ty_ref ())
+ if (!can_resolve ())
return get_symbol ();
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (get_ty_ref (), &lookup);
- rust_assert (ok);
-
- return lookup->get_name ();
+ return resolve ()->get_name ();
}
BaseType *
@@ -2364,14 +2405,27 @@ ParamType::is_equal (const BaseType &other) const
}
ParamType *
-ParamType::handle_substitions (SubstitutionArgumentMappings mappings)
+ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
{
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool ok = subst_mappings.get_argument_for_symbol (this, &arg);
+ if (!ok || arg.is_error ())
+ return this;
+
ParamType *p = static_cast<ParamType *> (clone ());
+ subst_mappings.on_param_subst (*p, arg);
- SubstitutionArg arg = SubstitutionArg::error ();
- bool ok = mappings.get_argument_for_symbol (this, &arg);
- if (ok && !arg.is_error ())
- p->set_ty_ref (arg.get_tyty ()->get_ref ());
+ // there are two cases one where we substitute directly to a new PARAM and
+ // otherwise
+ if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ p->set_ty_ref (arg.get_tyty ()->get_ref ());
+ return p;
+ }
+
+ // this is the new subst that this needs to pass
+ p->set_ref (mappings->get_next_hir_id ());
+ p->set_ty_ref (arg.get_tyty ()->get_ref ());
return p;
}
@@ -2658,7 +2712,7 @@ ProjectionType::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 (), subst_mappings.get_locus ());
+ sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
}
auto fty = projection->base;
@@ -2935,17 +2989,7 @@ TypeCheckCallExpr::visit (FnType &type)
return;
}
- if (type.get_return_type ()->get_kind () == TyTy::TypeKind::PLACEHOLDER)
- {
- const TyTy::PlaceholderType *p
- = static_cast<const TyTy::PlaceholderType *> (type.get_return_type ());
- if (p->can_resolve ())
- {
- resolved = p->resolve ()->clone ();
- return;
- }
- }
-
+ type.monomorphize ();
resolved = type.get_return_type ()->clone ();
}
@@ -3050,6 +3094,7 @@ TypeCheckMethodCallExpr::visit (FnType &type)
return;
}
+ type.monomorphize ();
resolved = type.get_return_type ()->clone ();
}
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 58b5042..17ba655 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -93,9 +93,7 @@ public:
return parent == nullptr || trait_item_ref == nullptr;
}
- BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver,
- const HIR::GenericArgs *bound_args
- = nullptr);
+ BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
const Resolver::TraitItemReference *get_raw_item () const;
@@ -293,6 +291,9 @@ public:
static TyVar get_implicit_infer_var (Location locus);
+ static TyVar subst_covariant_var (TyTy::BaseType *orig,
+ TyTy::BaseType *subst);
+
private:
HirId ref;
};
@@ -431,10 +432,10 @@ public:
bool is_concrete () const override final
{
- if (!can_resolve ())
+ auto r = resolve ();
+ if (r == this)
return false;
- auto r = resolve ();
return r->is_concrete ();
}
@@ -559,7 +560,8 @@ public:
return param->get_name ();
}
- bool fill_param_ty (BaseType &type, Location locus);
+ bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
+ Location locus);
SubstitutionParamMapping clone () const
{
@@ -567,6 +569,8 @@ public:
param->clone ()));
}
+ ParamType *get_param_ty () { return param; }
+
const ParamType *get_param_ty () const { return param; }
const HIR::TypeParam &get_generic_param () { return generic; };
@@ -577,11 +581,7 @@ public:
bool needs_substitution () const
{
- auto p = get_param_ty ();
- if (!p->can_resolve ())
- return true;
-
- return p->resolve ()->get_kind () == TypeKind::PARAM;
+ return !(get_param_ty ()->is_concrete ());
}
Location get_param_locus () const { return generic.get_locus (); }
@@ -605,9 +605,12 @@ class SubstitutionArg
{
public:
SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument)
- : param (std::move (param)), argument (argument)
+ : param (param), argument (argument)
{}
+ // FIXME
+ // the copy constructors need removed - they are unsafe see
+ // TypeBoundPredicate
SubstitutionArg (const SubstitutionArg &other)
: param (other.param), argument (other.argument)
{}
@@ -651,16 +654,20 @@ private:
BaseType *argument;
};
+typedef std::function<void (const ParamType &, const SubstitutionArg &)>
+ ParamSubstCb;
class SubstitutionArgumentMappings
{
public:
SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
- Location locus)
- : mappings (mappings), locus (locus)
+ Location locus,
+ ParamSubstCb param_subst_cb = nullptr)
+ : mappings (mappings), locus (locus), param_subst_cb (param_subst_cb)
{}
SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other)
- : mappings (other.mappings), locus (other.locus)
+ : mappings (other.mappings), locus (other.locus),
+ param_subst_cb (other.param_subst_cb)
{}
SubstitutionArgumentMappings &
@@ -668,12 +675,14 @@ public:
{
mappings = other.mappings;
locus = other.locus;
+ param_subst_cb = other.param_subst_cb;
+
return *this;
}
static SubstitutionArgumentMappings error ()
{
- return SubstitutionArgumentMappings ({}, Location ());
+ return SubstitutionArgumentMappings ({}, Location (), nullptr);
}
bool is_error () const { return mappings.size () == 0; }
@@ -717,7 +726,7 @@ public:
return true;
}
- Location get_locus () { return locus; }
+ Location get_locus () const { return locus; }
size_t size () const { return mappings.size (); }
@@ -737,9 +746,18 @@ public:
return "<" + buffer + ">";
}
+ void on_param_subst (const ParamType &p, const SubstitutionArg &a) const
+ {
+ if (param_subst_cb == nullptr)
+ return;
+
+ param_subst_cb (p, a);
+ }
+
private:
std::vector<SubstitutionArg> mappings;
Location locus;
+ ParamSubstCb param_subst_cb;
};
class SubstitutionRef
@@ -944,9 +962,18 @@ public:
return handle_substitions (std::move (infer_arguments));
}
+ // TODO comment
+ bool monomorphize ();
+
+ // TODO comment
virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings)
= 0;
+ SubstitutionArgumentMappings get_used_arguments () const
+ {
+ return used_arguments;
+ }
+
protected:
std::vector<SubstitutionParamMapping> substitutions;
SubstitutionArgumentMappings used_arguments;
@@ -987,11 +1014,8 @@ public:
TypeBoundPredicateItem
lookup_associated_item (const std::string &search) const;
- HIR::GenericArgs *get_generic_args () { return &args; }
-
- const HIR::GenericArgs *get_generic_args () const { return &args; }
-
- bool has_generic_args () const { return args.has_generic_args (); }
+ TypeBoundPredicateItem
+ lookup_associated_item (const Resolver::TraitItemReference *ref) const;
// WARNING THIS WILL ALWAYS RETURN NULLPTR
BaseType *
@@ -1004,7 +1028,6 @@ public:
private:
DefId reference;
Location locus;
- HIR::GenericArgs args;
bool error_flag;
};
diff --git a/gcc/testsuite/rust/compile/torture/traits19.rs b/gcc/testsuite/rust/compile/torture/traits19.rs
new file mode 100644
index 0000000..4412656
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits19.rs
@@ -0,0 +1,33 @@
+// { dg-additional-options "-w" }
+trait Get {
+ type Value;
+ fn get(&self) -> &<Self as Get>::Value;
+}
+
+struct Struct {
+ x: isize,
+}
+
+impl Get for Struct {
+ type Value = isize;
+ fn get(&self) -> &isize {
+ &self.x
+ }
+}
+
+trait Grab {
+ type U;
+ fn grab(&self) -> &<Self as Grab>::U;
+}
+
+impl<T: Get> Grab for T {
+ type U = <T as Get>::Value;
+ fn grab(&self) -> &<T as Get>::Value {
+ self.get()
+ }
+}
+
+fn main() {
+ let s = Struct { x: 100 };
+ let a = s.grab();
+}
diff --git a/gcc/testsuite/rust/execute/torture/slice-magic.rs b/gcc/testsuite/rust/execute/torture/slice-magic.rs
new file mode 100644
index 0000000..bac8a78
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/slice-magic.rs
@@ -0,0 +1,106 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+ pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<A> *const [A] {
+ pub const fn len(self) -> usize {
+ let a = unsafe { Repr { rust: self }.raw };
+ a.len
+ }
+
+ pub const fn as_ptr(self) -> *const A {
+ self as *const A
+ }
+}
+
+#[lang = "const_ptr"]
+impl<B> *const B {
+ pub const unsafe fn offset(self, count: isize) -> *const B {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const B {
+ self as *const B
+ }
+}
+
+const fn slice_from_raw_parts<C>(data: *const C, len: usize) -> *const [C] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<X> {
+ type Output;
+
+ unsafe fn get_unchecked(self, slice: *const X) -> *const Self::Output;
+
+ fn index(self, slice: &X) -> &Self::Output;
+}
+
+unsafe impl<Y> SliceIndex<[Y]> for Range<usize> {
+ type Output = [Y];
+
+ unsafe fn get_unchecked(self, slice: *const [Y]) -> *const [Y] {
+ unsafe {
+ let a: *const Y = slice.as_ptr();
+ let b: *const Y = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[Y]) -> &[Y] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let a = [1, 2, 3, 4, 5];
+ let b = &a[1..3];
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/slice-magic2.rs b/gcc/testsuite/rust/execute/torture/slice-magic2.rs
new file mode 100644
index 0000000..5a89f2e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/slice-magic2.rs
@@ -0,0 +1,106 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+ pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+ pub const fn len(self) -> usize {
+ let a = unsafe { Repr { rust: self }.raw };
+ a.len
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+ pub const unsafe fn offset(self, count: isize) -> *const T {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+ type Output;
+
+ unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+ fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+ type Output = [T];
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ unsafe {
+ let a: *const T = slice.as_ptr();
+ let b: *const T = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[T]) -> &[T] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let a = [1, 2, 3, 4, 5];
+ let b = &a[1..3];
+
+ 0
+}