aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-04-12 09:50:56 +0000
committerGitHub <noreply@github.com>2022-04-12 09:50:56 +0000
commitc1a022385f5ed99b579e373d37cec389433e93f4 (patch)
tree11d8928918796afb88de93d53c0cf21eb167e990 /gcc
parent68458036c81d141a3899ac4e6ec6ddf0fdfde174 (diff)
parent0e686c0fe01ef29be1c08fb8440caf76c9fb66d9 (diff)
downloadgcc-c1a022385f5ed99b579e373d37cec389433e93f4.zip
gcc-c1a022385f5ed99b579e373d37cec389433e93f4.tar.gz
gcc-c1a022385f5ed99b579e373d37cec389433e93f4.tar.bz2
Merge #1086
1086: Slice support r=philberty a=philberty Please see the commit a8de089969cb45199008027cd8d1b80dff25746f for a long explanation of what's going on in the patch. Unfortunately, I have not been able to split this patch up anymore since supporting slices exposed many bugs in the implementation of generics in general never main the missing support for generic associated types. Fixes #849 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-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
+}