public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Thomas Schwinge <tschwinge@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] gccrs: Extract helper lookup_associated_impl_block Date: Tue, 2 May 2023 07:12:04 +0000 (GMT) [thread overview] Message-ID: <20230502071204.CADF3385840D@sourceware.org> (raw) https://gcc.gnu.org/g:c13032e55c0bd39557c6366729e4afca3890c6c1 commit c13032e55c0bd39557c6366729e4afca3890c6c1 Author: Philip Herron <herron.philip@googlemail.com> Date: Thu Apr 20 16:56:46 2023 +0100 gccrs: Extract helper lookup_associated_impl_block This will look for a specified predicate that is associated with it so we might have the predicate Foo<u16, i32> which would refer to: impl Foo<i32> for u16 {} This is a general helper which can be used in several places. gcc/rust/ChangeLog: * typecheck/rust-hir-trait-reference.cc (AssociatedImplTrait::AssociatedImplTrait): bind the predicate (AssociatedImplTrait::get_trait): remove (AssociatedImplTrait::get_predicate): new getter * typecheck/rust-hir-trait-reference.h: bind predicate * typecheck/rust-hir-type-check-item.cc: update ctor * typecheck/rust-type-util.cc (lookup_associated_impl_block): new function * typecheck/rust-type-util.h (class BaseType): remove unused forward decl (lookup_associated_impl_block): new helper * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::is_equal): new * typecheck/rust-tyty-subst.cc (SubstitutionRef::lookup_associated_impl): use new helper (SubstitutionRef::monomorphize): update usage/error handling * typecheck/rust-tyty-subst.h: remove old prototype * typecheck/rust-tyty.h: add is_equal decl Signed-off-by: Philip Herron <herron.philip@googlemail.com> Diff: --- gcc/rust/typecheck/rust-hir-trait-reference.cc | 11 +- gcc/rust/typecheck/rust-hir-trait-reference.h | 6 +- gcc/rust/typecheck/rust-hir-type-check-item.cc | 4 +- gcc/rust/typecheck/rust-type-util.cc | 108 +++++++++++++++++ gcc/rust/typecheck/rust-type-util.h | 10 +- gcc/rust/typecheck/rust-tyty-bounds.cc | 34 ++++++ gcc/rust/typecheck/rust-tyty-subst.cc | 153 ++++--------------------- gcc/rust/typecheck/rust-tyty-subst.h | 4 - gcc/rust/typecheck/rust-tyty.h | 2 + 9 files changed, 183 insertions(+), 149 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc index a1229adc06c..f4593ce00fb 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.cc +++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc @@ -442,16 +442,18 @@ TraitReference::satisfies_bound (const TraitReference &reference) const } AssociatedImplTrait::AssociatedImplTrait (TraitReference *trait, + TyTy::TypeBoundPredicate predicate, HIR::ImplBlock *impl, TyTy::BaseType *self, Resolver::TypeCheckContext *context) - : trait (trait), impl (impl), self (self), context (context) + : trait (trait), predicate (predicate), impl (impl), self (self), + context (context) {} -TraitReference * -AssociatedImplTrait::get_trait () +TyTy::TypeBoundPredicate & +AssociatedImplTrait::get_predicate () { - return trait; + return predicate; } HIR::ImplBlock * @@ -465,6 +467,7 @@ AssociatedImplTrait::get_self () { return self; } + const TyTy::BaseType * AssociatedImplTrait::get_self () const { diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h index d20b2952e5b..2179d09403f 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.h +++ b/gcc/rust/typecheck/rust-hir-trait-reference.h @@ -238,11 +238,12 @@ private: class AssociatedImplTrait { public: - AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl, + AssociatedImplTrait (TraitReference *trait, + TyTy::TypeBoundPredicate predicate, HIR::ImplBlock *impl, TyTy::BaseType *self, Resolver::TypeCheckContext *context); - TraitReference *get_trait (); + TyTy::TypeBoundPredicate &get_predicate (); HIR::ImplBlock *get_impl_block (); @@ -257,6 +258,7 @@ public: private: TraitReference *trait; + TyTy::TypeBoundPredicate predicate; HIR::ImplBlock *impl; TyTy::BaseType *self; Resolver::TypeCheckContext *context; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 0e8ce6b7b78..4b9f9bce2ea 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -607,8 +607,8 @@ TypeCheckItem::validate_trait_impl_block ( { trait_reference->clear_associated_types (); - AssociatedImplTrait associated (trait_reference, &impl_block, self, - context); + AssociatedImplTrait associated (trait_reference, specified_bound, + &impl_block, self, context); context->insert_associated_trait_impl ( impl_block.get_mappings ().get_hirid (), std::move (associated)); context->insert_associated_impl_mapping ( diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index 578e0c4509e..d77175eedc0 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -25,6 +25,7 @@ #include "rust-casts.h" #include "rust-unify.h" #include "rust-coercion.h" +#include "rust-hir-type-bounds.h" namespace Rust { namespace Resolver { @@ -254,5 +255,112 @@ cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to, return casted; } +AssociatedImplTrait * +lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound, + const TyTy::BaseType *binding, bool *ambigious) +{ + auto context = TypeCheckContext::get (); + + // setup any associated type mappings for the specified bonds and this + // type + auto candidates = TypeBoundsProbe::Probe (binding); + std::vector<AssociatedImplTrait *> associated_impl_traits; + for (auto &probed_bound : candidates) + { + HIR::ImplBlock *associated_impl = probed_bound.second; + + HirId impl_block_id = associated_impl->get_mappings ().get_hirid (); + AssociatedImplTrait *associated = nullptr; + bool found_impl_trait + = context->lookup_associated_trait_impl (impl_block_id, &associated); + if (found_impl_trait) + { + // compare the bounds from here i think is what we can do: + if (bound.is_equal (associated->get_predicate ())) + { + associated_impl_traits.push_back (associated); + } + } + } + + if (associated_impl_traits.empty ()) + return nullptr; + + // This code is important when you look at slices for example when + // you have a slice such as: + // + // let slice = &array[1..3] + // + // the higher ranked bounds will end up having an Index trait + // implementation for Range<usize> so we need this code to resolve + // that we have an integer inference variable that needs to become + // a usize + // + // The other complicated issue is that we might have an intrinsic + // which requires the :Clone or Copy bound but the libcore adds + // implementations for all the integral types so when there are + // multiple candidates we need to resolve to the default + // implementation for that type otherwise its an error for + // ambiguous type bounds + + // if we have a non-general inference variable we need to be + // careful about the selection here + bool is_infer_var = binding->get_kind () == TyTy::TypeKind::INFER; + bool is_integer_infervar + = is_infer_var + && static_cast<const TyTy::InferType *> (binding)->get_infer_kind () + == TyTy::InferType::InferTypeKind::INTEGRAL; + bool is_float_infervar + = is_infer_var + && static_cast<const TyTy::InferType *> (binding)->get_infer_kind () + == TyTy::InferType::InferTypeKind::FLOAT; + + AssociatedImplTrait *associate_impl_trait = nullptr; + if (associated_impl_traits.size () == 1) + { + // just go for it + associate_impl_trait = associated_impl_traits.at (0); + } + else if (is_integer_infervar) + { + TyTy::BaseType *type = nullptr; + bool ok = context->lookup_builtin ("i32", &type); + rust_assert (ok); + + for (auto &impl : associated_impl_traits) + { + bool found = impl->get_self ()->is_equal (*type); + if (found) + { + associate_impl_trait = impl; + break; + } + } + } + else if (is_float_infervar) + { + TyTy::BaseType *type = nullptr; + bool ok = context->lookup_builtin ("f64", &type); + rust_assert (ok); + + for (auto &impl : associated_impl_traits) + { + bool found = impl->get_self ()->is_equal (*type); + if (found) + { + associate_impl_trait = impl; + break; + } + } + } + + if (associate_impl_trait == nullptr && ambigious != nullptr) + { + *ambigious = true; + } + + return associate_impl_trait; +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h index 8ecba738ff4..89e4a185a50 100644 --- a/gcc/rust/typecheck/rust-type-util.h +++ b/gcc/rust/typecheck/rust-type-util.h @@ -23,11 +23,6 @@ #include "rust-tyty.h" namespace Rust { - -namespace TyTy { -class BaseType; -} - namespace Resolver { bool @@ -50,6 +45,11 @@ TyTy::BaseType * cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to, Location cast_locus); +AssociatedImplTrait * +lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound, + const TyTy::BaseType *binding, + bool *ambigious = nullptr); + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index defa0ec1edf..67aa4f8fa86 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -680,6 +680,40 @@ TypeBoundPredicate::get_associated_type_items () return items; } +bool +TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const +{ + // check they match the same trait reference + if (reference != other.reference) + return false; + + // check that the generics match + if (get_num_substitutions () != other.get_num_substitutions ()) + return false; + + // then match the generics applied + for (size_t i = 0; i < get_num_substitutions (); i++) + { + const SubstitutionParamMapping &a = substitutions.at (i); + const SubstitutionParamMapping &b = other.substitutions.at (i); + + const ParamType *ap = a.get_param_ty (); + const ParamType *bp = b.get_param_ty (); + + const BaseType *apd = ap->destructure (); + const BaseType *bpd = bp->destructure (); + + // FIXME use the unify_and infer inteface or try coerce + if (!apd->can_eq (bpd, false /*emit_errors*/)) + { + if (!bpd->can_eq (apd, false /*emit_errors*/)) + return false; + } + } + + return true; +} + // trait item reference const Resolver::TraitItemReference * diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 60bf219e26c..7d7ab7ca79a 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -21,7 +21,7 @@ #include "rust-hir-type-check.h" #include "rust-substitution-mapper.h" #include "rust-hir-type-check-type.h" -#include "rust-hir-type-bounds.h" +#include "rust-type-util.h" namespace Rust { namespace TyTy { @@ -831,132 +831,6 @@ SubstitutionRef::solve_mappings_from_receiver_for_self ( mappings.get_locus ()); } -Resolver::AssociatedImplTrait * -SubstitutionRef::lookup_associated_impl (const SubstitutionParamMapping &subst, - const TypeBoundPredicate &bound, - const TyTy::BaseType *binding, - bool *error_flag) const -{ - auto context = Resolver::TypeCheckContext::get (); - 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); - std::vector<Resolver::AssociatedImplTrait *> associated_impl_traits; - 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); - if (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_traits.push_back (associated); - } - } - } - - if (associated_impl_traits.empty ()) - return nullptr; - - // This code is important when you look at slices for example when - // you have a slice such as: - // - // let slice = &array[1..3] - // - // the higher ranked bounds will end up having an Index trait - // implementation for Range<usize> so we need this code to resolve - // that we have an integer inference variable that needs to become - // a usize - // - // The other complicated issue is that we might have an intrinsic - // which requires the :Clone or Copy bound but the libcore adds - // implementations for all the integral types so when there are - // multiple candidates we need to resolve to the default - // implementation for that type otherwise its an error for - // ambiguous type bounds - - // if we have a non-general inference variable we need to be - // careful about the selection here - bool is_infer_var = binding->get_kind () == TyTy::TypeKind::INFER; - bool is_integer_infervar - = is_infer_var - && static_cast<const TyTy::InferType *> (binding)->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL; - bool is_float_infervar - = is_infer_var - && static_cast<const TyTy::InferType *> (binding)->get_infer_kind () - == TyTy::InferType::InferTypeKind::FLOAT; - - Resolver::AssociatedImplTrait *associate_impl_trait = nullptr; - if (associated_impl_traits.size () == 1) - { - // just go for it - associate_impl_trait = associated_impl_traits.at (0); - } - else if (is_integer_infervar) - { - TyTy::BaseType *type = nullptr; - bool ok = context->lookup_builtin ("i32", &type); - rust_assert (ok); - - for (auto &impl : associated_impl_traits) - { - bool found = impl->get_self ()->is_equal (*type); - if (found) - { - associate_impl_trait = impl; - break; - } - } - } - else if (is_float_infervar) - { - TyTy::BaseType *type = nullptr; - bool ok = context->lookup_builtin ("f64", &type); - rust_assert (ok); - - for (auto &impl : associated_impl_traits) - { - bool found = impl->get_self ()->is_equal (*type); - if (found) - { - associate_impl_trait = impl; - break; - } - } - } - - if (associate_impl_trait == nullptr) - { - // go for the first one? or error out? - auto &mappings = *Analysis::Mappings::get (); - const auto &type_param = subst.get_generic_param (); - const auto *trait_ref = bound.get (); - - RichLocation r (type_param.get_locus ()); - r.add_range (bound.get_locus ()); - r.add_range (mappings.lookup_location (binding->get_ref ())); - - rust_error_at (r, "ambiguous type bound for trait %s and type %s", - trait_ref->get_name ().c_str (), - binding->get_name ().c_str ()); - - *error_flag = true; - return nullptr; - } - - return associate_impl_trait; -} - void SubstitutionRef::prepare_higher_ranked_bounds () { @@ -987,16 +861,31 @@ SubstitutionRef::monomorphize () for (const auto &bound : pty->get_specified_bounds ()) { - bool error_flag = false; + bool ambigious = false; auto associated - = lookup_associated_impl (subst, bound, binding, &error_flag); + = Resolver::lookup_associated_impl_block (bound, binding, + &ambigious); + if (associated == nullptr && ambigious) + { + // go for the first one? or error out? + auto &mappings = *Analysis::Mappings::get (); + const auto &type_param = subst.get_generic_param (); + const auto *trait_ref = bound.get (); + + RichLocation r (type_param.get_locus ()); + r.add_range (bound.get_locus ()); + r.add_range (mappings.lookup_location (binding->get_ref ())); + + rust_error_at (r, "ambiguous type bound for trait %s and type %s", + trait_ref->get_name ().c_str (), + binding->get_name ().c_str ()); + return false; + } + if (associated != nullptr) { associated->setup_associated_types (binding, bound); } - - if (error_flag) - return false; } } diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h index 639a275eea0..0bbb164b8d5 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.h +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -318,10 +318,6 @@ public: SubstitutionArgumentMappings get_used_arguments () const; protected: - Resolver::AssociatedImplTrait *lookup_associated_impl ( - const SubstitutionParamMapping &subst, const TypeBoundPredicate &bound, - const TyTy::BaseType *binding, bool *error_flag) const; - std::vector<SubstitutionParamMapping> substitutions; SubstitutionArgumentMappings used_arguments; }; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 550b76672ea..5daf1ca40c5 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -438,6 +438,8 @@ public: TypeBoundPredicateItem lookup_associated_type (const std::string &search) override final; + bool is_equal (const TypeBoundPredicate &other) const; + private: DefId reference; Location locus;
reply other threads:[~2023-05-02 7:12 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20230502071204.CADF3385840D@sourceware.org \ --to=tschwinge@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).