public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Refactor type resolution of method call expression
@ 2022-08-06 12:09 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-08-06 12:09 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:6f88307147ac7b63c315aab2e81811e985a867a7
commit 6f88307147ac7b63c315aab2e81811e985a867a7
Author: Philip Herron <philip.herron@embecosm.com>
Date: Thu Aug 4 12:18:37 2022 +0100
Refactor type resolution of method call expression
This simply moves the implementation of this into a cc file to help with
compilation times.
Diff:
---
gcc/rust/typecheck/rust-hir-type-check-expr.cc | 151 ++++++++++++++++++++++++
gcc/rust/typecheck/rust-hir-type-check-expr.h | 152 +------------------------
2 files changed, 152 insertions(+), 151 deletions(-)
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 80f351a8c45..c328f410c6c 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -295,6 +295,157 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
infered = array_type->get_element_type ()->clone ();
}
+void
+TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
+{
+ auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ());
+ if (receiver_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (expr.get_receiver ()->get_locus (),
+ "failed to resolve receiver in MethodCallExpr");
+ return;
+ }
+
+ context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
+
+ auto candidate
+ = MethodResolver::Probe (receiver_tyty,
+ expr.get_method_name ().get_segment ());
+ if (candidate.is_error ())
+ {
+ rust_error_at (
+ expr.get_method_name ().get_locus (),
+ "failed to resolve method for %<%s%>",
+ expr.get_method_name ().get_segment ().as_string ().c_str ());
+ return;
+ }
+
+ // Get the adjusted self
+ Adjuster adj (receiver_tyty);
+ TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
+
+ // store the adjustments for code-generation to know what to do
+ context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
+ std::move (candidate.adjustments));
+
+ 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 ();
+
+ if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
+ {
+ RichLocation r (expr.get_method_name ().get_locus ());
+ r.add_range (resolved_candidate.locus);
+ rust_error_at (r, "associated impl item is not a method");
+ return;
+ }
+
+ TyTy::BaseType *lookup = lookup_tyty;
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
+ if (!fn->is_method ())
+ {
+ RichLocation r (expr.get_method_name ().get_locus ());
+ r.add_range (resolved_candidate.locus);
+ rust_error_at (r, "associated function is not a method");
+ return;
+ }
+
+ auto root = receiver_tyty->get_root ();
+ 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);
+ }
+ }
+ }
+ }
+
+ // apply any remaining generic arguments
+ if (expr.get_method_name ().has_generic_args ())
+ {
+ HIR::GenericArgs &args = expr.get_method_name ().get_generic_args ();
+ lookup
+ = SubstMapper::Resolve (lookup, expr.get_method_name ().get_locus (),
+ &args);
+ if (lookup->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+ else if (lookup->needs_generic_substitutions ())
+ {
+ lookup = SubstMapper::InferSubst (lookup,
+ expr.get_method_name ().get_locus ());
+ }
+
+ TyTy::BaseType *function_ret_tyty
+ = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self, context);
+ if (function_ret_tyty == nullptr
+ || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to lookup type to MethodCallExpr");
+ return;
+ }
+
+ // store the expected fntype
+ context->insert_type (expr.get_method_name ().get_mappings (), lookup);
+
+ // 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;
+}
+
bool
TypeCheckExpr::resolve_operator_overload (
Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExprMeta expr,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 88545c6e5cb..8a0c3054cd7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -220,157 +220,7 @@ public:
= TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
}
- void visit (HIR::MethodCallExpr &expr) override
- {
- auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ());
- if (receiver_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (expr.get_receiver ()->get_locus (),
- "failed to resolve receiver in MethodCallExpr");
- return;
- }
-
- context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
-
- auto candidate
- = MethodResolver::Probe (receiver_tyty,
- expr.get_method_name ().get_segment ());
- if (candidate.is_error ())
- {
- rust_error_at (
- expr.get_method_name ().get_locus (),
- "failed to resolve method for %<%s%>",
- expr.get_method_name ().get_segment ().as_string ().c_str ());
- return;
- }
-
- // Get the adjusted self
- Adjuster adj (receiver_tyty);
- TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
-
- // store the adjustments for code-generation to know what to do
- context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
- std::move (candidate.adjustments));
-
- 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 ();
-
- if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
- {
- RichLocation r (expr.get_method_name ().get_locus ());
- r.add_range (resolved_candidate.locus);
- rust_error_at (r, "associated impl item is not a method");
- return;
- }
-
- TyTy::BaseType *lookup = lookup_tyty;
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
- if (!fn->is_method ())
- {
- RichLocation r (expr.get_method_name ().get_locus ());
- r.add_range (resolved_candidate.locus);
- rust_error_at (r, "associated function is not a method");
- return;
- }
-
- auto root = receiver_tyty->get_root ();
- 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);
- }
- }
- }
- }
-
- // apply any remaining generic arguments
- if (expr.get_method_name ().has_generic_args ())
- {
- HIR::GenericArgs &args = expr.get_method_name ().get_generic_args ();
- lookup
- = SubstMapper::Resolve (lookup, expr.get_method_name ().get_locus (),
- &args);
- if (lookup->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
- else if (lookup->needs_generic_substitutions ())
- {
- lookup = SubstMapper::InferSubst (lookup,
- expr.get_method_name ().get_locus ());
- }
-
- TyTy::BaseType *function_ret_tyty
- = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self,
- context);
- if (function_ret_tyty == nullptr
- || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (expr.get_locus (),
- "failed to lookup type to MethodCallExpr");
- return;
- }
-
- // store the expected fntype
- context->insert_type (expr.get_method_name ().get_mappings (), lookup);
-
- // 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;
- }
+ void visit (HIR::MethodCallExpr &expr) override;
void visit (HIR::AssignmentExpr &expr) override
{
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-08-06 12:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-06 12:09 [gcc/devel/rust/master] Refactor type resolution of method call expression 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).