From: Philip Herron Date: Wed, 3 Sep 2025 19:50:59 +0000 (+0100) Subject: gccrs: track abi and unsafety on fnptrs for proper type checking X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=07b7e33869ad04d93eb0f2c68e6a917f6a92d266;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index d9df6029c5a..eb9cec74196 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 39772b42a0d..dfefae8bef3 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 15d4a592059..9c1a84f5919 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 ()) { @@ -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 22aa28d6fe1..973ada3bdc4 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 params, - TyVar result_type, std::set refs = std::set ()) + TyVar result_type, ABI abi, Unsafety unsafety, + std::set refs = std::set ()) : 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 params, - TyVar result_type, std::set refs = std::set ()) + TyVar result_type, ABI abi, Unsafety unsafety, + std::set refs = std::set ()) : 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 &get_params () { return params; } const std::vector &get_params () const { return params; } + ABI get_abi () const { return abi; } + + Unsafety get_unsafety () const { return unsafety; } + private: std::vector 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 5ab1020d596..be7ac51962b 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;