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;
