]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Ensure we look at the bounds behind a reference
authorPhilip Herron <herron.philip@googlemail.com>
Fri, 20 Jun 2025 16:49:32 +0000 (17:49 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:50 +0000 (16:36 +0200)
When type checking expressions that involve references, we need to
examine the bounds of the referenced type to properly resolve traits
and methods.

gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check-expr.cc: Look at bounds behind
references.
* typecheck/rust-hir-type-check-expr.h: Add helper method.

gcc/rust/typecheck/rust-hir-type-check-expr.cc
gcc/rust/typecheck/rust-hir-type-check-expr.h

index 81d95c83239fa4edc0debb1a013f0e79594dd696..753d3915f69fa2a2dabbbb03c49d227d88942e0f 100644 (file)
@@ -2086,16 +2086,13 @@ TypeCheckExpr::resolve_operator_overload (
 
 HIR::PathIdentSegment
 TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
-  TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate)
+  const TyTy::BaseType &receiver,
+  TyTy::TypeBoundPredicate *associated_predicate)
 {
-  // Question
-  // do we need to probe possible bounds here? I think not, i think when we
-  // support Fn traits they are explicitly specified
-
   // FIXME
   // the logic to map the FnTrait to their respective call trait-item is
   // duplicated over in the backend/rust-compile-expr.cc
-  for (auto &bound : receiver.get_specified_bounds ())
+  for (const auto &bound : receiver.get_specified_bounds ())
     {
       bool found_fn = bound.get_name ().compare ("Fn") == 0;
       bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
@@ -2118,6 +2115,34 @@ TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
        }
     }
 
+  if (receiver.is<TyTy::ReferenceType> ())
+    {
+      const auto &ref = static_cast<const TyTy::ReferenceType &> (receiver);
+      const auto &underlying = *ref.get_base ();
+      for (const auto &bound : underlying.get_specified_bounds ())
+       {
+         bool found_fn = bound.get_name ().compare ("Fn") == 0;
+         bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
+         bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0;
+
+         if (found_fn)
+           {
+             *associated_predicate = bound;
+             return HIR::PathIdentSegment ("call");
+           }
+         else if (found_fn_mut)
+           {
+             *associated_predicate = bound;
+             return HIR::PathIdentSegment ("call_mut");
+           }
+         else if (found_fn_once)
+           {
+             *associated_predicate = bound;
+             return HIR::PathIdentSegment ("call_once");
+           }
+       }
+    }
+
   // nothing
   *associated_predicate = TyTy::TypeBoundPredicate::error ();
   return HIR::PathIdentSegment ("");
index e0a3278fb82d9e133ef31390af4305a603ccfac9..5311974368532daf2f6d4a329533b4caa53beee2 100644 (file)
@@ -109,7 +109,8 @@ protected:
                              TyTy::BaseType **result);
 
   HIR::PathIdentSegment resolve_possible_fn_trait_call_method_name (
-    TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate);
+    const TyTy::BaseType &receiver,
+    TyTy::TypeBoundPredicate *associated_predicate);
 
 private:
   TypeCheckExpr ();