diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 49a6f2f75bf0..2128f25f2965 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 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 (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 9e2c5b32b171..bd782b003905 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 (mono1); - rust_assert (mono2 != nullptr); - rust_assert (mono2->get_kind () == TyTy::TypeKind::FNDEF); - TyTy::FnType *assocated_item_ty2 = static_cast (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 ce7c4e1028c3..104bd16080e9 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 &specified_bounds = r->get_specified_bounds (); + const std::vector 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 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 (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::get_predicate_items ( + const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver, + const std::vector &specified_bounds) +{ + std::vector 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 (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 f14300a4bfec..ef1038bd78c3 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.h +++ b/gcc/rust/typecheck/rust-hir-dot-operator.h @@ -48,22 +48,32 @@ class MethodResolver : public TypeCheckBase 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 &adjustments); + static std::vector get_predicate_items ( + const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver, + const std::vector &specified_bounds); + PathProbeCandidate select (); - MethodResolver (const TyTy::BaseType &receiver, - const HIR::PathIdentSegment &segment_name, - const std::vector &specified_bounds) + MethodResolver ( + const TyTy::BaseType &receiver, const HIR::PathIdentSegment &segment_name, + const std::vector &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 &specified_bounds; + const std::vector &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 585fb6c8dbfe..d8c8a1906cd1 100644 --- a/gcc/rust/typecheck/rust-hir-trait-ref.h +++ b/gcc/rust/typecheck/rust-hir-trait-ref.h @@ -262,6 +262,8 @@ class TraitReference 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 @@ class AssociatedImplTrait 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 54fdc0253b6c..b4e0efea0fa7 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 (item_ty); - placeholder->set_associated_type (ty->get_ref ()); + placeholder->set_associated_type (ty->get_ty_ref ()); } void @@ -175,6 +175,173 @@ AssociatedImplTrait::setup_associated_types () iter.go (); } +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 SliceIndex<[Y]> for Range + // vs + // I: SliceIndex<[]> and Range<> + // + // 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 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 (*generic_param), + static_cast (l))); + } + } + break; + } + } + + // generate inference variables for these bound arguments so we can compute + // their values + Location locus; + std::vector 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 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 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 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 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 () { diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h index 806a46f13cee..651af9db81a6 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.h +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h @@ -141,24 +141,26 @@ class TraitResolver : public TypeCheckBase break; } } - rust_assert (self != nullptr); // Check if there is a super-trait, and apply this bound to the Self // TypeParam std::vector 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 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 super_traits; if (trait_reference->has_type_param_bounds ()) { @@ -171,12 +173,8 @@ class TraitResolver : public TypeCheckBase = static_cast (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 539a3fee6f59..a3d911efd794 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 (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 (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 (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 1b14693aa8d1..560581d588bf 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 @@ class TypeCheckExpr : public TypeCheckBase } 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 (root); @@ -346,28 +345,21 @@ class TypeCheckExpr : public TypeCheckBase } } - 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 4c6c4a633d29..9846ed602f7e 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 @@ class TypeCheckItem : public TypeCheckBase 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 cd6d67a56ff4..e2fa7f5e9aca 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 &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 f96b9b3ee7a8..f80368a03399 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 5f1781635cce..e12432e59ee2 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -232,19 +232,22 @@ class SubstMapperInternal : public TyTy::TyVisitor } // 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 b34db3bd44e3..e226400f5d97 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 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 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 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 (trait_item_tyty); - TyTy::SubstitutionParamMapping *param = nullptr; - for (auto ¶m_mapping : fn->get_substs ()) - { - const HIR::TypeParam &type_param = param_mapping.get_generic_param (); - if (type_param.get_type_representation ().compare ("Self") == 0) - { - param = ¶m_mapping; - break; - } - } - rust_assert (param != nullptr); - - std::vector 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 34c89639f6f1..f3118ba7dbb8 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -43,16 +43,19 @@ class BaseCmp : public TyConstVisitor return ok; } } - else if (other->get_kind () == TypeKind::PLACEHOLDER) + if (other->get_kind () == TypeKind::PLACEHOLDER) { const PlaceholderType *p = static_cast (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 (other); + other = p->get (); + } other->accept_vis (*this); return ok; @@ -1268,14 +1271,10 @@ class ParamCmp : public BaseCmp // 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 @@ class PlaceholderCmp : public BaseCmp 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 4deed5521a9b..c24f17e6c945 100644 --- a/gcc/rust/typecheck/rust-tyty-coercion.h +++ b/gcc/rust/typecheck/rust-tyty-coercion.h @@ -53,12 +53,14 @@ class BaseCoercionRules : public TyVisitor if (p->can_resolve ()) { other = p->resolve (); + return get_base ()->coerce (other); } } else if (other->get_kind () == TypeKind::PROJECTION) { ProjectionType *p = static_cast (other); other = p->get (); + return get_base ()->coerce (other); } other->accept_vis (*this); @@ -1351,14 +1353,10 @@ class ParamCoercionRules : public BaseCoercionRules // 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 c1fc2cd96c13..7c50112db60d 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -60,10 +60,7 @@ class BaseRules : public TyVisitor if (other->get_kind () == TypeKind::PARAM) { ParamType *p = static_cast (other); - if (p->can_resolve ()) - { - other = p->resolve (); - } + other = p->resolve (); } else if (other->get_kind () == TypeKind::PLACEHOLDER) { @@ -71,12 +68,14 @@ class BaseRules : public TyVisitor if (p->can_resolve ()) { other = p->resolve (); + return get_base ()->unify (other); } } else if (other->get_kind () == TypeKind::PROJECTION) { ProjectionType *p = static_cast (other); other = p->get (); + return get_base ()->unify (other); } other->accept_vis (*this); @@ -1328,14 +1327,10 @@ class ParamRules : public BaseRules // 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 1d197f5a8459..156cc101c79b 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 (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 (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 (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 (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 58b5042c34ab..17ba6554c4a7 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -93,9 +93,7 @@ class TypeBoundPredicateItem 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 @@ class TyVar 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 @@ class ParamType : public BaseType 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 @@ class SubstitutionParamMapping 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 @@ class SubstitutionParamMapping 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 @@ class SubstitutionParamMapping 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 @@ class SubstitutionArg BaseType *argument; }; +typedef std::function + ParamSubstCb; class SubstitutionArgumentMappings { public: SubstitutionArgumentMappings (std::vector 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 @@ class SubstitutionArgumentMappings { 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 @@ class SubstitutionArgumentMappings return true; } - Location get_locus () { return locus; } + Location get_locus () const { return locus; } size_t size () const { return mappings.size (); } @@ -737,9 +746,18 @@ class SubstitutionArgumentMappings 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 mappings; Location locus; + ParamSubstCb param_subst_cb; }; class SubstitutionRef @@ -944,9 +962,18 @@ class SubstitutionRef 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 substitutions; SubstitutionArgumentMappings used_arguments; @@ -987,11 +1014,8 @@ class TypeBoundPredicate : public SubstitutionRef 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 @@ class TypeBoundPredicate : public SubstitutionRef 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 000000000000..4412656f5351 --- /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) -> &::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) -> &::U; +} + +impl Grab for T { + type U = ::Value; + fn grab(&self) -> &::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 000000000000..bac8a7803e60 --- /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(dst: *const T, offset: isize) -> *const T; +} + +struct FatPtr { + data: *const T, + len: usize, +} + +union Repr { + rust: *const [T], + rust_mut: *mut [T], + raw: FatPtr, +} + +#[lang = "Range"] +pub struct Range { + pub start: Idx, + pub end: Idx, +} + +#[lang = "const_slice_ptr"] +impl *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 *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(data: *const C, len: usize) -> *const [C] { + unsafe { + Repr { + raw: FatPtr { data, len }, + } + .rust + } +} + +#[lang = "index"] +trait Index { + type Output; + + fn index(&self, index: Idx) -> &Self::Output; +} + +pub unsafe trait SliceIndex { + type Output; + + unsafe fn get_unchecked(self, slice: *const X) -> *const Self::Output; + + fn index(self, slice: &X) -> &Self::Output; +} + +unsafe impl SliceIndex<[Y]> for Range { + 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 Index 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 000000000000..5a89f2ef3dd1 --- /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(dst: *const T, offset: isize) -> *const T; +} + +struct FatPtr { + data: *const T, + len: usize, +} + +union Repr { + rust: *const [T], + rust_mut: *mut [T], + raw: FatPtr, +} + +#[lang = "Range"] +pub struct Range { + pub start: Idx, + pub end: Idx, +} + +#[lang = "const_slice_ptr"] +impl *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 *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(data: *const T, len: usize) -> *const [T] { + unsafe { + Repr { + raw: FatPtr { data, len }, + } + .rust + } +} + +#[lang = "index"] +trait Index { + type Output; + + fn index(&self, index: Idx) -> &Self::Output; +} + +pub unsafe trait SliceIndex { + type Output; + + unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output; + + fn index(self, slice: &T) -> &Self::Output; +} + +unsafe impl SliceIndex<[T]> for Range { + 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 Index 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 +}