https://gcc.gnu.org/g:07b7e33869ad04d93eb0f2c68e6a917f6a92d266

commit r16-4853-g07b7e33869ad04d93eb0f2c68e6a917f6a92d266
Author: Philip Herron <[email protected]>
Date:   Wed Sep 3 20:50:59 2025 +0100

    gccrs: track abi and unsafety on fnptrs for proper type checking
    
    We need to distinguish between abi's and unsafety on fnptrs. There is
    a commented out check because there is a regression in:
    
      rust/compile/try-catch-unwind-{new/old}.rs
    
    But i think this is because the test case should be taking an FnOnce
    from reading std::panic in rust 1.49. Where as we are passing an fnptr
    which is probably because we didnt support fnonce at all then.
    
    Addresses Rust-GCC/gccrs#4090
    
    gcc/rust/ChangeLog:
    
            * hir/tree/rust-hir-item.h: add unsafe helper
            * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): 
pass in abi and unsafe
            * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): likewise
            (FnPtr::as_string): emit more info
            (FnPtr::clone): update ctor call
            * typecheck/rust-tyty.h: new ctor params
            * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): check abi and 
unsafe
    
    Signed-off-by: Philip Herron <[email protected]>

Diff:
---
 gcc/rust/hir/tree/rust-hir-item.h              |  1 +
 gcc/rust/typecheck/rust-hir-type-check-type.cc |  9 +++++---
 gcc/rust/typecheck/rust-tyty.cc                | 16 +++++++++-----
 gcc/rust/typecheck/rust-tyty.h                 | 17 +++++++++++----
 gcc/rust/typecheck/rust-unify.cc               | 29 ++++++++++++++++++++++++++
 5 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/hir/tree/rust-hir-item.h 
b/gcc/rust/hir/tree/rust-hir-item.h
index d9df6029c5ac..eb9cec741963 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -452,6 +452,7 @@ public:
   bool is_unsafe () const { return unsafety == Unsafety::Unsafe; }
   bool is_async () const { return async_status == Async::Yes; }
 
+  Unsafety get_unsafety () const { return unsafety; }
   ABI get_abi () const { return abi; }
 };
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc 
b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 39772b42a0db..dfefae8bef3e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -105,9 +105,12 @@ TypeCheckType::visit (HIR::BareFunctionType &fntype)
       params.emplace_back (ptype->get_ref ());
     }
 
-  translated = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (),
-                               fntype.get_locus (), std::move (params),
-                               TyTy::TyVar (return_type->get_ref ()));
+  translated
+    = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), fntype.get_locus 
(),
+                      std::move (params),
+                      TyTy::TyVar (return_type->get_ref ()),
+                      fntype.get_function_qualifiers ().get_abi (),
+                      fntype.get_function_qualifiers ().get_unsafety ());
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 15d4a5920591..9c1a84f5919a 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -608,8 +608,8 @@ BaseType::monomorphized_clone () const
 
       TyVar retty = fn->get_var_return_type ().monomorphized_clone ();
       return new FnPtr (fn->get_ref (), fn->get_ty_ref (), ident.locus,
-                       std::move (cloned_params), retty,
-                       fn->get_combined_refs ());
+                       std::move (cloned_params), retty, fn->get_abi (),
+                       fn->get_unsafety (), fn->get_combined_refs ());
     }
   else if (auto adt = x->try_as<const ADTType> ())
     {
@@ -2268,7 +2268,13 @@ FnPtr::as_string () const
       params_str += p.get_tyty ()->as_string () + " ,";
     }
 
-  return "fnptr (" + params_str + ") -> " + get_return_type ()->as_string ();
+  std::string unsafety = "";
+  if (get_unsafety () == Unsafety::Unsafe)
+    unsafety = "unsafe ";
+
+  std::string abi = get_string_from_abi (get_abi ());
+  return unsafety + "abi:" + abi + " " + "fnptr (" + params_str + ") -> "
+        + get_return_type ()->as_string ();
 }
 
 bool
@@ -2304,8 +2310,8 @@ FnPtr::clone () const
     cloned_params.emplace_back (p.get_ref ());
 
   return new FnPtr (get_ref (), get_ty_ref (), ident.locus,
-                   std::move (cloned_params), result_type,
-                   get_combined_refs ());
+                   std::move (cloned_params), result_type, get_abi (),
+                   get_unsafety (), get_combined_refs ());
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 22aa28d6fe15..973ada3bdc42 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -1046,19 +1046,22 @@ public:
   static constexpr auto KIND = TypeKind::FNPTR;
 
   FnPtr (HirId ref, location_t locus, std::vector<TyVar> params,
-        TyVar result_type, std::set<HirId> refs = std::set<HirId> ())
+        TyVar result_type, ABI abi, Unsafety unsafety,
+        std::set<HirId> refs = std::set<HirId> ())
     : CallableTypeInterface (ref, ref, TypeKind::FNPTR,
                             {Resolver::CanonicalPath::create_empty (), locus},
                             refs),
-      params (std::move (params)), result_type (result_type)
+      params (std::move (params)), result_type (result_type), abi (abi),
+      unsafety (unsafety)
   {}
 
   FnPtr (HirId ref, HirId ty_ref, location_t locus, std::vector<TyVar> params,
-        TyVar result_type, std::set<HirId> refs = std::set<HirId> ())
+        TyVar result_type, ABI abi, Unsafety unsafety,
+        std::set<HirId> refs = std::set<HirId> ())
     : CallableTypeInterface (ref, ty_ref, TypeKind::FNPTR,
                             {Resolver::CanonicalPath::create_empty (), locus},
                             refs),
-      params (params), result_type (result_type)
+      params (params), result_type (result_type), abi (abi), unsafety 
(unsafety)
   {}
 
   std::string get_name () const override final { return as_string (); }
@@ -1094,9 +1097,15 @@ public:
   std::vector<TyVar> &get_params () { return params; }
   const std::vector<TyVar> &get_params () const { return params; }
 
+  ABI get_abi () const { return abi; }
+
+  Unsafety get_unsafety () const { return unsafety; }
+
 private:
   std::vector<TyVar> params;
   TyVar result_type;
+  ABI abi;
+  Unsafety unsafety;
 };
 
 class ClosureType : public CallableTypeInterface, public SubstitutionRef
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 5ab1020d5967..be7ac51962b5 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -1146,6 +1146,16 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, 
TyTy::BaseType *rtype)
            return unify_error_type_node ();
          }
 
+       if (ltype->get_abi () != type.get_abi ())
+         {
+           return unify_error_type_node ();
+         }
+
+       if (ltype->get_unsafety () != type.get_unsafety ())
+         {
+           return unify_error_type_node ();
+         }
+
        return ltype;
       }
       break;
@@ -1183,6 +1193,25 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, 
TyTy::BaseType *rtype)
              }
          }
 
+       // FIXME
+       //
+       // there is a bug in:
+       // testsuite/rust/compile/try-catch-unwind-{new,old}.rs I think the test
+       //
+       // case is wrong because it should be taking an FnOnce which probably
+       // didnt exist at the time in gccrs
+       //
+       // if (ltype->get_abi () != type.get_abi ())
+       //   {
+       //     return unify_error_type_node ();
+       //   }
+
+       // FIXME fntype needs to track unsafe or not
+       // if (ltype->get_unsafety () != type.get_unsafety ())
+       //   {
+       //     return unify_error_type_node ();
+       //   }
+
        return ltype;
       }
       break;

Reply via email to