public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] gccrs: Extract helper lookup_associated_impl_block
@ 2023-05-02 7:12 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2023-05-02 7:12 UTC (permalink / raw)
To: gcc-cvs
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;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-05-02 7:12 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-02 7:12 [gcc/devel/rust/master] gccrs: Extract helper lookup_associated_impl_block Thomas Schwinge
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).