https://gcc.gnu.org/g:dd4eabb87bff25a1a1ad5fc7b8f2da7cce8e0e47
commit r16-2893-gdd4eabb87bff25a1a1ad5fc7b8f2da7cce8e0e47 Author: Philip Herron <herron.phi...@googlemail.com> Date: Mon Jun 23 11:21:02 2025 +0100 gccrs: check for invalid const calls during code-gen Closure calls are not const so this is invalid. This patch fixes two bugs 1. Make the look at the parent context optional for generics 2. Ensure we look for non const calls during call expr code-gen Fixes Rust-GCC#3551 gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): add const call check * backend/rust-compile-item.cc (CompileItem::visit): ensure we upfront compile types where possible * backend/rust-compile-item.h: update header * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): make parent ctx optional gcc/testsuite/ChangeLog: * rust/compile/issue-3551.rs: New test. Signed-off-by: Philip Herron <herron.phi...@googlemail.com> Diff: --- gcc/rust/backend/rust-compile-expr.cc | 22 ++++++++++ gcc/rust/backend/rust-compile-item.cc | 60 ++++++++++++++++++++++++++ gcc/rust/backend/rust-compile-item.h | 8 ++-- gcc/rust/typecheck/rust-hir-type-check-expr.cc | 20 ++++++--- gcc/testsuite/rust/compile/issue-3551.rs | 15 +++++++ 5 files changed, 114 insertions(+), 11 deletions(-) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index d8ddab5bd9aa..7a1e5a70ab69 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1338,6 +1338,28 @@ CompileExpr::visit (HIR::CallExpr &expr) }; auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx); + if (ctx->const_context_p ()) + { + if (!FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn_address))) + { + rust_error_at (expr.get_locus (), + "calls in constants are limited to constant " + "functions, tuple structs and tuple variants"); + return; + } + + if (TREE_CODE (fn_address) == ADDR_EXPR) + { + tree fndecl = TREE_OPERAND (fn_address, 0); + if (!DECL_DECLARED_CONSTEXPR_P (fndecl)) + { + rust_error_at (expr.get_locus (), + "calls in constants are limited to constant " + "functions, tuple structs and tuple variants"); + return; + } + } + } // is this a closure call? bool possible_trait_call diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 3e7ea9a25e93..78f6f571e9ce 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -297,5 +297,65 @@ CompileItem::visit (HIR::Module &module) CompileItem::compile (item.get (), ctx); } +void +CompileItem::visit (HIR::TupleStruct &tuple_struct_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + tuple_struct_decl.get_mappings ().get_hirid (), &lookup)) + { + rust_error_at (tuple_struct_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::Enum &enum_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (enum_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (enum_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::Union &union_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (union_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (union_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::StructStruct &struct_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (struct_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (struct_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index d9d946d25140..56baaabce877 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -44,9 +44,12 @@ public: void visit (HIR::ImplBlock &impl_block) override; void visit (HIR::ExternBlock &extern_block) override; void visit (HIR::Module &module) override; + void visit (HIR::TupleStruct &tuple_struct) override; + void visit (HIR::Enum &enum_decl) override; + void visit (HIR::Union &union_decl) override; + void visit (HIR::StructStruct &struct_decl) override; // Empty visit for unused Stmt HIR nodes. - void visit (HIR::TupleStruct &) override {} void visit (HIR::EnumItem &) override {} void visit (HIR::EnumItemTuple &) override {} void visit (HIR::EnumItemStruct &) override {} @@ -57,9 +60,6 @@ public: void visit (HIR::ExternCrate &) override {} void visit (HIR::UseDeclaration &) override {} void visit (HIR::TypeAlias &) override {} - void visit (HIR::StructStruct &) override {} - void visit (HIR::Enum &) override {} - void visit (HIR::Union &) override {} void visit (HIR::Trait &) override {} void visit (HIR::EmptyStmt &) override {} void visit (HIR::LetStmt &) override {} diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 753d3915f69f..eb50803814f4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1726,16 +1726,22 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr) void TypeCheckExpr::visit (HIR::ClosureExpr &expr) { - TypeCheckContextItem current_context = context->peek_context (); - TyTy::FnType *current_context_fndecl = current_context.get_context_type (); - + std::vector<TyTy::SubstitutionParamMapping> subst_refs; HirId ref = expr.get_mappings ().get_hirid (); DefId id = expr.get_mappings ().get_defid (); - RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()}; + RustIdent ident{CanonicalPath::create_empty (), expr.get_locus ()}; + + if (context->have_function_context ()) + { + TypeCheckContextItem current_context = context->peek_context (); + TyTy::FnType *current_context_fndecl + = current_context.get_context_type (); + + ident = RustIdent{current_context_fndecl->get_ident ().path, + expr.get_locus ()}; - // get from parent context - std::vector<TyTy::SubstitutionParamMapping> subst_refs - = current_context_fndecl->clone_substs (); + subst_refs = current_context_fndecl->clone_substs (); + } std::vector<TyTy::TyVar> parameter_types; for (auto &p : expr.get_params ()) diff --git a/gcc/testsuite/rust/compile/issue-3551.rs b/gcc/testsuite/rust/compile/issue-3551.rs new file mode 100644 index 000000000000..6d6a8129885d --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3551.rs @@ -0,0 +1,15 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce<Args> { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct Bug { + a: [(); (|| 0)()], + // { dg-error "calls in constants are limited to constant functions, tuple structs and tuple variants" "" { target *-*-* } .-1 } +}