https://gcc.gnu.org/g:dcf3cbc0f78de4834914895122d70530c3ffd775
commit r17-5154-gdcf3cbc0f78de4834914895122d70530c3ffd775 Author: Owen Avery <[email protected]> Date: Sun Sep 20 19:10:08 2026 -0400 gccrs: Improve bodyless function pattern check gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit (Function)): Emit error on complex patterns in non-extern bodyless functions as well. gcc/testsuite/ChangeLog: * rust/compile/function-param-bodyless.rs: New test. Signed-off-by: Owen Avery <[email protected]> Diff: --- gcc/rust/checks/errors/rust-ast-validation.cc | 49 ++++++++++++++++------ .../rust/compile/function-param-bodyless.rs | 35 ++++++++++++++++ 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index b2825fb2c958..e5f8577cbabb 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -104,6 +104,35 @@ ASTValidation::visit (AST::Function &function) function.get_self_param ().get_locus (), "%<self%> parameter is only allowed in associated functions"); + // functions without bodies can only have very specific + // kinds of patterns in their parameters + auto is_param_complex_with_loc + = [] (AST::Param ¶m) -> tl::optional<location_t> { + tl::optional<location_t> ret; + + if (param.is_self () || param.is_variadic ()) + return ret; + + auto &fn_param = static_cast<AST::FunctionParam &> (param); + if (!fn_param.has_name ()) + return ret; + + auto &pat = fn_param.get_pattern (); + ret = pat.get_locus (); + auto kind = pat.get_pattern_kind (); + if (kind == AST::Pattern::Kind::Identifier) + { + auto &ident_pat = static_cast<AST::IdentifierPattern &> (pat); + if (!ident_pat.get_is_ref () && !ident_pat.get_is_mut () + && !ident_pat.has_subpattern ()) + ret = tl::nullopt; + } + else if (kind == AST::Pattern::Kind::Wildcard) + ret = tl::nullopt; + + return ret; + }; + if (function.is_external ()) { if (function.has_body ()) @@ -123,20 +152,11 @@ ASTValidation::visit (AST::Function &function) it->get ()->get_locus (), "%<...%> must be the last argument of a C-variadic function"); - // if functional parameter - if (!it->get ()->is_self () && !it->get ()->is_variadic ()) - { - auto ¶m = static_cast<AST::FunctionParam &> (**it); - auto kind = param.get_pattern ().get_pattern_kind (); - - if (kind != AST::Pattern::Kind::Identifier - && kind != AST::Pattern::Kind::Wildcard) - rust_error_at (it->get ()->get_locus (), ErrorCode::E0130, - "pattern not allowed in foreign function"); - } + if (auto pat_loc = is_param_complex_with_loc (**it)) + rust_error_at (*pat_loc, ErrorCode::E0130, + "pattern not allowed in foreign function"); } } - else { if (!function.has_body ()) @@ -158,6 +178,11 @@ ASTValidation::visit (AST::Function &function) it->get ()->get_locus (), "only foreign or %<unsafe extern \"C\"%> functions may " "be C-variadic"); + + if (!function.has_body ()) + if (auto pat_loc = is_param_complex_with_loc (**it)) + rust_error_at (*pat_loc, ErrorCode::E0642, + "pattern not allowed in function without body"); } } diff --git a/gcc/testsuite/rust/compile/function-param-bodyless.rs b/gcc/testsuite/rust/compile/function-param-bodyless.rs new file mode 100644 index 000000000000..eb71d475beba --- /dev/null +++ b/gcc/testsuite/rust/compile/function-param-bodyless.rs @@ -0,0 +1,35 @@ +// { dg-additional-options "-w" } +#![feature(no_core)] +#![no_core] + +mod extern_test { + extern "C" { + // { dg-error "pattern not allowed in foreign function .E0130." "" { target *-*-* } .+1 } + fn f1(mut a: i32); + // { dg-error "pattern not allowed in foreign function .E0130." "" { target *-*-* } .+1 } + fn f2(ref a: i32); + // { dg-error "pattern not allowed in foreign function .E0130." "" { target *-*-* } .+1 } + fn f3(a @ _: i32); + // { dg-error "pattern not allowed in foreign function .E0130." "" { target *-*-* } .+1 } + fn f4((a,): i32); + // { dg-error "pattern not allowed in foreign function .E0130." "" { target *-*-* } .+1 } + fn f5((a): i32); + + fn f6(_: i32); + } +} + +trait Foo { + // { dg-error "pattern not allowed in function without body .E0642." "" { target *-*-* } .+1 } + fn f1(mut a: i32); + // { dg-error "pattern not allowed in function without body .E0642." "" { target *-*-* } .+1 } + fn f2(ref a: i32); + // { dg-error "pattern not allowed in function without body .E0642." "" { target *-*-* } .+1 } + fn f3(a @ _: i32); + // { dg-error "pattern not allowed in function without body .E0642." "" { target *-*-* } .+1 } + fn f4((a,): i32); + // { dg-error "pattern not allowed in function without body .E0642." "" { target *-*-* } .+1 } + fn f5((a): i32); + + fn f6(_: i32); +}
