aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-11-24 18:16:37 +0000
committerPhilip Herron <philip.herron@embecosm.com>2021-11-25 14:11:10 +0000
commit12b7154e90f676222262fe3d6935a950805a8566 (patch)
tree80b6d67075bf8d3adb1ceefdc039b30e6d0cb306
parent717b6da459b26ace9a3c303cfa5e485ff8935709 (diff)
downloadgcc-12b7154e90f676222262fe3d6935a950805a8566.zip
gcc-12b7154e90f676222262fe3d6935a950805a8566.tar.gz
gcc-12b7154e90f676222262fe3d6935a950805a8566.tar.bz2
improve the error handling on operator overload cases
This operator overloading function was extracted from the callers within compound assignment etc, where we needed to be able to fall back to code within the same function. This improves the error handling to return early when there are no such lang-items or no available method instead of trying to continue. It flattens the conditional's previously required in the code path.
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h114
1 files changed, 54 insertions, 60 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index fb1cd97..4923426 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -1260,7 +1260,6 @@ protected:
const TyTy::BaseType *root = lhs->get_root ();
// look up lang item for arithmetic type
- std::vector<PathProbeCandidate> candidates;
std::string associated_item_name
= Analysis::RustLangItem::ToString (lang_item_type);
DefId respective_lang_item_id = UNKNOWN_DEFID;
@@ -1268,26 +1267,30 @@ protected:
= mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
// probe for the lang-item
- if (lang_item_defined)
- {
- bool receiver_is_type_param
- = root->get_kind () == TyTy::TypeKind::PARAM;
- bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
-
- bool receiver_is_generic = receiver_is_type_param || receiver_is_dyn;
- bool probe_bounds = true;
- bool probe_impls = !receiver_is_generic;
- bool ignore_mandatory_trait_items = !receiver_is_generic;
-
- candidates = PathProbeType::Probe (
- root, HIR::PathIdentSegment (associated_item_name), probe_impls,
- probe_bounds, ignore_mandatory_trait_items, respective_lang_item_id);
- }
+ if (!lang_item_defined)
+ return false;
- // autoderef
+ bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
+ bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
+ bool receiver_is_generic = receiver_is_type_param || receiver_is_dyn;
+ bool probe_bounds = true;
+ bool probe_impls = !receiver_is_generic;
+ bool ignore_mandatory_trait_items = !receiver_is_generic;
+
+ auto candidates = PathProbeType::Probe (
+ root, HIR::PathIdentSegment (associated_item_name), probe_impls,
+ probe_bounds, ignore_mandatory_trait_items, respective_lang_item_id);
+
+ // autoderef to find the relevant method
std::vector<Adjustment> adjustments;
PathProbeCandidate *resolved_candidate
= MethodResolution::Select (candidates, lhs, adjustments);
+ if (resolved_candidate == nullptr)
+ return false;
+
+ bool have_implementation_for_lang_item = resolved_candidate != nullptr;
+ if (!have_implementation_for_lang_item)
+ return false;
// mark the required tree addressable
if (Adjuster::needs_address (adjustments))
@@ -1297,56 +1300,47 @@ protected:
// handle the case where we are within the impl block for this lang_item
// otherwise we end up with a recursive operator overload such as the i32
// operator overload trait
- if (lang_item_defined && resolved_candidate != nullptr)
+ TypeCheckContextItem &fn_context = context->peek_context ();
+ if (fn_context.get_type () == TypeCheckContextItem::ItemType::IMPL_ITEM)
{
- TypeCheckContextItem &fn_context = context->peek_context ();
- if (fn_context.get_type () == TypeCheckContextItem::ItemType::IMPL_ITEM)
- {
- auto &impl_item = fn_context.get_impl_item ();
- HIR::ImplBlock *parent = impl_item.first;
- HIR::Function *fn = impl_item.second;
+ auto &impl_item = fn_context.get_impl_item ();
+ HIR::ImplBlock *parent = impl_item.first;
+ HIR::Function *fn = impl_item.second;
- if (parent->has_trait_ref ()
- && fn->get_function_name ().compare (associated_item_name) == 0)
+ if (parent->has_trait_ref ()
+ && fn->get_function_name ().compare (associated_item_name) == 0)
+ {
+ TraitReference *trait_reference
+ = TraitResolver::Lookup (*parent->get_trait_ref ().get ());
+ if (!trait_reference->is_error ())
{
- TraitReference *trait_reference
- = TraitResolver::Lookup (*parent->get_trait_ref ().get ());
- if (!trait_reference->is_error ())
- {
- TyTy::BaseType *lookup = nullptr;
- bool ok
- = context->lookup_type (fn->get_mappings ().get_hirid (),
- &lookup);
- rust_assert (ok);
- rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
-
- TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
- rust_assert (fntype->is_method ());
-
- Adjuster adj (lhs);
- TyTy::BaseType *adjusted = adj.adjust_type (adjustments);
-
- bool is_lang_item_impl
- = trait_reference->get_mappings ().get_defid ()
- == respective_lang_item_id;
- bool self_is_lang_item_self
- = fntype->get_self_type ()->is_equal (*adjusted);
- bool recursive_operator_overload
- = is_lang_item_impl && self_is_lang_item_self;
-
- lang_item_defined = !recursive_operator_overload;
- }
+ TyTy::BaseType *lookup = nullptr;
+ bool ok
+ = context->lookup_type (fn->get_mappings ().get_hirid (),
+ &lookup);
+ rust_assert (ok);
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
+
+ TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
+ rust_assert (fntype->is_method ());
+
+ Adjuster adj (lhs);
+ TyTy::BaseType *adjusted = adj.adjust_type (adjustments);
+
+ bool is_lang_item_impl
+ = trait_reference->get_mappings ().get_defid ()
+ == respective_lang_item_id;
+ bool self_is_lang_item_self
+ = fntype->get_self_type ()->is_equal (*adjusted);
+ bool recursive_operator_overload
+ = is_lang_item_impl && self_is_lang_item_self;
+
+ if (recursive_operator_overload)
+ return false;
}
}
}
- bool have_implementation_for_lang_item = resolved_candidate != nullptr;
- if (!lang_item_defined || !have_implementation_for_lang_item)
- {
- // no operator overload exists for this
- return false;
- }
-
// now its just like a method-call-expr
context->insert_receiver (expr.get_mappings ().get_hirid (), lhs);