summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2023-04-20 17:10:15 +0100
committerPhilip Herron <philip.herron@embecosm.com>2023-04-28 10:16:43 +0000
commit187f4b9eb897a08c124742e018b323c1ad6c9189 (patch)
treed307e2a7e363275c220fbe14f69fb77e074a1432
parentc13032e55c0bd39557c6366729e4afca3890c6c1 (diff)
downloadgcc-187f4b9eb897a08c124742e018b323c1ad6c9189.tar.gz
gccrs: qualified path syntax is used to disambiguate predicates
When resolving a qualified path we need to use the predicate to lookup the relevant assoicated impl block where possible. The issue here is that it might not have one due to a valid error in the impl block or it might be used within a trait this is a valid case. Generally we will be able to resolve to an impl block then it can grab that type and move on. Fixes #2135 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit): use the predicate (TypeCheckExpr::resolve_segments): cleanup gcc/testsuite/ChangeLog: * rust/compile/issue-2135.rs: New test. Signed-off-by: Philip Herron <herron.philip@googlemail.com>
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc82
-rw-r--r--gcc/testsuite/rust/compile/issue-2135.rs19
2 files changed, 66 insertions, 35 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index d43587f6f35..67b8d24b5a9 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -69,49 +69,63 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
// inherit the bound
root->inherit_bounds ({specified_bound});
- // setup the associated types
- const TraitReference *specified_bound_ref = specified_bound.get ();
- auto candidates = TypeBoundsProbe::Probe (root);
- AssociatedImplTrait *associated_impl_trait = nullptr;
- for (auto &probed_bound : candidates)
+ // lookup the associated item from the specified bound
+ HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
+ HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment ();
+ TyTy::TypeBoundPredicateItem item
+ = specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
+ if (item.is_error ())
{
- const 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 ();
- AssociatedImplTrait *associated = nullptr;
- bool found_impl_trait
- = context->lookup_associated_trait_impl (impl_block_id, &associated);
- if (found_impl_trait)
+ rust_error_at (item_seg.get_locus (), "unknown associated item");
+ return;
+ }
+
+ // we try to look for the real impl item if possible
+ HIR::ImplItem *impl_item = nullptr;
+
+ // lookup the associated impl trait for this if we can (it might be generic)
+ AssociatedImplTrait *associated_impl_trait
+ = lookup_associated_impl_block (specified_bound, root);
+ if (associated_impl_trait != nullptr)
+ {
+ for (auto &i :
+ associated_impl_trait->get_impl_block ()->get_impl_items ())
{
- bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref);
- bool found_self = associated->get_self ()->can_eq (root, false);
- if (found_trait && found_self)
+ bool found = i->get_impl_item_name ().compare (
+ item_seg_identifier.as_string ())
+ == 0;
+ if (found)
{
- associated_impl_trait = associated;
+ impl_item = i.get ();
break;
}
}
}
- if (associated_impl_trait != nullptr)
+ NodeId root_resolved_node_id = UNKNOWN_NODEID;
+ if (impl_item == nullptr)
{
- associated_impl_trait->setup_associated_types (root, specified_bound);
+ // this may be valid as there could be a default trait implementation here
+ // and we dont need to worry if the trait item is actually implemented or
+ // not because this will have already been validated as part of the trait
+ // impl block
+ infered = item.get_tyty_for_receiver (root);
+ root_resolved_node_id
+ = item.get_raw_item ()->get_mappings ().get_nodeid ();
}
-
- // lookup the associated item from the specified bound
- HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
- HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment ();
- TyTy::TypeBoundPredicateItem item
- = specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
- if (item.is_error ())
+ else
{
- rust_error_at (item_seg.get_locus (), "unknown associated item");
- return;
- }
+ HirId impl_item_id = impl_item->get_impl_mappings ().get_hirid ();
+ bool ok = query_type (impl_item_id, &infered);
+ if (!ok)
+ {
+ // FIXME
+ // I think query_type should error if required here anyway
+ return;
+ }
- // infer the root type
- infered = item.get_tyty_for_receiver (root);
+ root_resolved_node_id = impl_item->get_impl_mappings ().get_nodeid ();
+ }
// turbo-fish segment path::<ty>
if (item_seg.has_generic_args ())
@@ -129,10 +143,7 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
}
// continue on as a path-in-expression
- const TraitItemReference *trait_item_ref = item.get_raw_item ();
- NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid ();
bool fully_resolved = expr.get_segments ().size () <= 1;
-
if (fully_resolved)
{
resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
@@ -321,7 +332,8 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
// candidate is found then we search extensions from traits
auto candidates
= PathProbeType::Probe (prev_segment, seg.get_segment (), probe_impls,
- false, true /*ignore_mandatory_trait_items*/);
+ false /*probe_bounds*/,
+ true /*ignore_mandatory_trait_items*/);
if (candidates.size () == 0)
{
candidates
diff --git a/gcc/testsuite/rust/compile/issue-2135.rs b/gcc/testsuite/rust/compile/issue-2135.rs
new file mode 100644
index 00000000000..563345efee3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2135.rs
@@ -0,0 +1,19 @@
+pub trait Foo<A> {
+ fn foo(self, _: A) -> u16;
+}
+
+impl Foo<u16> for u16 {
+ fn foo(self, _: u16) -> u16 {
+ self
+ }
+}
+
+impl Foo<u8> for u16 {
+ fn foo(self, _: u8) -> u16 {
+ self
+ }
+}
+
+pub fn bar() -> u16 {
+ <u16 as Foo<u16>>::foo(0u16, 0u16)
+}