From: Philip Herron Date: Thu, 20 Apr 2023 16:10:15 +0000 (+0100) Subject: gccrs: qualified path syntax is used to disambiguate predicates X-Git-Tag: basepoints/gcc-15~2601 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=04877f1096b9afe9d27552ffd0cc76388bbc6c03;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index dd7bc9aee6e2..9b5c6fee1010 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:: 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 000000000000..563345efee36 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2135.rs @@ -0,0 +1,19 @@ +pub trait Foo { + fn foo(self, _: A) -> u16; +} + +impl Foo for u16 { + fn foo(self, _: u16) -> u16 { + self + } +} + +impl Foo for u16 { + fn foo(self, _: u8) -> u16 { + self + } +} + +pub fn bar() -> u16 { + >::foo(0u16, 0u16) +}