aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-02-24 16:02:50 +0000
committerPhilip Herron <philip.herron@embecosm.com>2022-02-24 16:02:50 +0000
commit5d5396d52277be5e2c82249f889a78d909f29084 (patch)
tree7bd41cb281f4b437185efbc1b82822864f9ed30e /gcc
parent3b3079eba5f9faa5fe6623314a367b44070f9c19 (diff)
downloadgcc-5d5396d52277be5e2c82249f889a78d909f29084.zip
gcc-5d5396d52277be5e2c82249f889a78d909f29084.tar.gz
gcc-5d5396d52277be5e2c82249f889a78d909f29084.tar.bz2
Refactor operator overloading code into cc file
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc186
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h186
2 files changed, 187 insertions, 185 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 0269433..2703d91 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -286,5 +286,191 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
infered = array_type->get_element_type ()->clone ();
}
+bool
+TypeCheckExpr::resolve_operator_overload (
+ Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExpr &expr,
+ TyTy::BaseType *lhs, TyTy::BaseType *rhs)
+{
+ // look up lang item for arithmetic type
+ std::string associated_item_name
+ = Analysis::RustLangItem::ToString (lang_item_type);
+ DefId respective_lang_item_id = UNKNOWN_DEFID;
+ bool lang_item_defined
+ = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
+
+ // probe for the lang-item
+ if (!lang_item_defined)
+ return false;
+
+ auto segment = HIR::PathIdentSegment (associated_item_name);
+ auto candidate
+ = MethodResolver::Probe (lhs, HIR::PathIdentSegment (associated_item_name));
+
+ bool have_implementation_for_lang_item = !candidate.is_error ();
+ if (!have_implementation_for_lang_item)
+ return false;
+
+ // Get the adjusted self
+ Adjuster adj (lhs);
+ TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
+
+ // is this the case we are recursive
+ // 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
+ 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;
+
+ 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 ())
+ {
+ 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 ());
+
+ 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_self);
+ bool recursive_operator_overload
+ = is_lang_item_impl && self_is_lang_item_self;
+
+ if (recursive_operator_overload)
+ return false;
+ }
+ }
+ }
+
+ // store the adjustments for code-generation to know what to do
+ context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
+ std::move (candidate.adjustments));
+
+ // now its just like a method-call-expr
+ context->insert_receiver (expr.get_mappings ().get_hirid (), lhs);
+
+ PathProbeCandidate &resolved_candidate = candidate.candidate;
+ TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
+ NodeId resolved_node_id
+ = resolved_candidate.is_impl_candidate ()
+ ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
+ .get_nodeid ()
+ : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
+
+ rust_assert (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::BaseType *lookup = lookup_tyty;
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
+ rust_assert (fn->is_method ());
+
+ auto root = lhs->get_root ();
+ bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
+ if (root->get_kind () == TyTy::TypeKind::ADT)
+ {
+ const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
+ if (adt->has_substitutions () && fn->needs_substitution ())
+ {
+ // consider the case where we have:
+ //
+ // struct Foo<X,Y>(X,Y);
+ //
+ // impl<T> Foo<T, i32> {
+ // fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
+ // }
+ //
+ // In this case we end up with an fn type of:
+ //
+ // fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
+ //
+ // This means the instance or self we are calling this method for
+ // will be substituted such that we can get the inherited type
+ // arguments but then need to use the turbo fish if available or
+ // infer the remaining arguments. Luckily rust does not allow for
+ // default types GenericParams on impl blocks since these must
+ // always be at the end of the list
+
+ auto s = fn->get_self_type ()->get_root ();
+ rust_assert (s->can_eq (adt, false));
+ rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
+ const TyTy::ADTType *self_adt
+ = static_cast<const TyTy::ADTType *> (s);
+
+ // we need to grab the Self substitutions as the inherit type
+ // parameters for this
+ if (self_adt->needs_substitution ())
+ {
+ rust_assert (adt->was_substituted ());
+
+ TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
+ = GetUsedSubstArgs::From (adt);
+
+ TyTy::SubstitutionArgumentMappings inherit_type_args
+ = self_adt->solve_mappings_from_receiver_for_self (
+ used_args_in_prev_segment);
+
+ // there may or may not be inherited type arguments
+ if (!inherit_type_args.is_error ())
+ {
+ // need to apply the inherited type arguments to the
+ // function
+ lookup = fn->handle_substitions (inherit_type_args);
+ }
+ }
+ }
+ }
+
+ // handle generics
+ if (!receiver_is_type_param)
+ {
+ if (lookup->needs_generic_substitutions ())
+ {
+ lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
+ }
+ }
+
+ // type check the arguments if required
+ TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
+ rust_assert (type->num_params () > 0);
+ auto fnparam = type->param_at (0);
+ fnparam.second->unify (adjusted_self); // typecheck the self
+ if (rhs == nullptr)
+ {
+ rust_assert (type->num_params () == 1);
+ }
+ else
+ {
+ rust_assert (type->num_params () == 2);
+ auto fnparam = type->param_at (1);
+ fnparam.second->unify (rhs); // typecheck the rhs
+ }
+
+ // get the return type
+ TyTy::BaseType *function_ret_tyty = type->get_return_type ()->clone ();
+
+ // store the expected fntype
+ context->insert_operator_overload (expr.get_mappings ().get_hirid (), type);
+
+ // set up the resolved name on the path
+ resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
+ resolved_node_id);
+
+ // return the result of the function back
+ infered = function_ret_tyty;
+
+ return true;
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 5b96854f..e222528 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -1240,191 +1240,7 @@ protected:
bool
resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type,
HIR::OperatorExpr &expr, TyTy::BaseType *lhs,
- TyTy::BaseType *rhs)
- {
- // look up lang item for arithmetic type
- std::string associated_item_name
- = Analysis::RustLangItem::ToString (lang_item_type);
- DefId respective_lang_item_id = UNKNOWN_DEFID;
- bool lang_item_defined
- = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
-
- // probe for the lang-item
- if (!lang_item_defined)
- return false;
-
- auto segment = HIR::PathIdentSegment (associated_item_name);
- auto candidate
- = MethodResolver::Probe (lhs,
- HIR::PathIdentSegment (associated_item_name));
-
- bool have_implementation_for_lang_item = !candidate.is_error ();
- if (!have_implementation_for_lang_item)
- return false;
-
- // Get the adjusted self
- Adjuster adj (lhs);
- TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
-
- // is this the case we are recursive
- // 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
- 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;
-
- 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 ())
- {
- 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 ());
-
- 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_self);
- bool recursive_operator_overload
- = is_lang_item_impl && self_is_lang_item_self;
-
- if (recursive_operator_overload)
- return false;
- }
- }
- }
-
- // store the adjustments for code-generation to know what to do
- context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
- std::move (candidate.adjustments));
-
- // now its just like a method-call-expr
- context->insert_receiver (expr.get_mappings ().get_hirid (), lhs);
-
- PathProbeCandidate &resolved_candidate = candidate.candidate;
- TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
- NodeId resolved_node_id
- = resolved_candidate.is_impl_candidate ()
- ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
- .get_nodeid ()
- : resolved_candidate.item.trait.item_ref->get_mappings ()
- .get_nodeid ();
-
- rust_assert (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF);
- TyTy::BaseType *lookup = lookup_tyty;
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
- rust_assert (fn->is_method ());
-
- auto root = lhs->get_root ();
- bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
- if (root->get_kind () == TyTy::TypeKind::ADT)
- {
- const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
- if (adt->has_substitutions () && fn->needs_substitution ())
- {
- // consider the case where we have:
- //
- // struct Foo<X,Y>(X,Y);
- //
- // impl<T> Foo<T, i32> {
- // fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
- // }
- //
- // In this case we end up with an fn type of:
- //
- // fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
- //
- // This means the instance or self we are calling this method for
- // will be substituted such that we can get the inherited type
- // arguments but then need to use the turbo fish if available or
- // infer the remaining arguments. Luckily rust does not allow for
- // default types GenericParams on impl blocks since these must
- // always be at the end of the list
-
- auto s = fn->get_self_type ()->get_root ();
- rust_assert (s->can_eq (adt, false));
- rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
- const TyTy::ADTType *self_adt
- = static_cast<const TyTy::ADTType *> (s);
-
- // we need to grab the Self substitutions as the inherit type
- // parameters for this
- if (self_adt->needs_substitution ())
- {
- rust_assert (adt->was_substituted ());
-
- TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
- = GetUsedSubstArgs::From (adt);
-
- TyTy::SubstitutionArgumentMappings inherit_type_args
- = self_adt->solve_mappings_from_receiver_for_self (
- used_args_in_prev_segment);
-
- // there may or may not be inherited type arguments
- if (!inherit_type_args.is_error ())
- {
- // need to apply the inherited type arguments to the
- // function
- lookup = fn->handle_substitions (inherit_type_args);
- }
- }
- }
- }
-
- // handle generics
- if (!receiver_is_type_param)
- {
- if (lookup->needs_generic_substitutions ())
- {
- lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
- }
- }
-
- // type check the arguments if required
- TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
- rust_assert (type->num_params () > 0);
- auto fnparam = type->param_at (0);
- fnparam.second->unify (adjusted_self); // typecheck the self
- if (rhs == nullptr)
- {
- rust_assert (type->num_params () == 1);
- }
- else
- {
- rust_assert (type->num_params () == 2);
- auto fnparam = type->param_at (1);
- fnparam.second->unify (rhs); // typecheck the rhs
- }
-
- // get the return type
- TyTy::BaseType *function_ret_tyty = type->get_return_type ()->clone ();
-
- // store the expected fntype
- context->insert_operator_overload (expr.get_mappings ().get_hirid (), type);
-
- // set up the resolved name on the path
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
-
- // return the result of the function back
- infered = function_ret_tyty;
-
- return true;
- }
+ TyTy::BaseType *rhs);
private:
TypeCheckExpr (bool inside_loop)