From be60529682864ef136dbdd4e2d537ec2df82c427 Mon Sep 17 00:00:00 2001 From: vishruth-thimmaiah Date: Wed, 29 Oct 2025 22:50:49 +0530 Subject: [PATCH] gccrs: Fix ICE with non-trailing const defaults When a const generic with a default value is not trailing, emit an error. gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_generic_params): Emit an error when const generics with a default value is not trailing. gcc/testsuite/ChangeLog: * rust/compile/const_generics_17.rs: New test. * rust/compile/generics14.rs: New test. Signed-off-by: vishruth-thimmaiah --- gcc/rust/parse/rust-parse-impl.h | 34 +++++++++++++++++-- .../rust/compile/const_generics_17.rs | 3 ++ gcc/testsuite/rust/compile/generics14.rs | 1 + 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/rust/compile/const_generics_17.rs create mode 100644 gcc/testsuite/rust/compile/generics14.rs diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index ec4c1c1d6c7..7b573e0c7a1 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -3262,8 +3262,12 @@ Parser::parse_generic_params (EndTokenPred is_end_token) // Did we parse a generic type param yet auto type_seen = false; + // Did we parse a const param with a default value yet + auto const_with_default_seen = false; // Did the user write a lifetime parameter after a type one auto order_error = false; + // Did the user write a const param with a default value after a type one + auto const_with_default_order_error = false; // parse lifetime params while (!is_end_token (lexer.peek_token ()->get_id ())) @@ -3271,12 +3275,29 @@ Parser::parse_generic_params (EndTokenPred is_end_token) auto param = parse_generic_param (is_end_token); if (param) { - // TODO: Handle `Const` here as well if necessary if (param->get_kind () == AST::GenericParam::Kind::Type) - type_seen = true; + { + type_seen = true; + if (const_with_default_seen) + const_with_default_order_error = true; + } else if (param->get_kind () == AST::GenericParam::Kind::Lifetime && type_seen) - order_error = true; + { + order_error = true; + if (const_with_default_seen) + const_with_default_order_error = true; + } + else if (param->get_kind () == AST::GenericParam::Kind::Const) + { + type_seen = true; + AST::ConstGenericParam *const_param + = static_cast (param.get ()); + if (const_param->has_default_value ()) + const_with_default_seen = true; + else if (const_with_default_seen) + const_with_default_order_error = true; + } generic_params.emplace_back (std::move (param)); maybe_skip_token (COMMA); @@ -3293,6 +3314,13 @@ Parser::parse_generic_params (EndTokenPred is_end_token) "must be declared prior to type and const parameters"); add_error (std::move (error)); } + if (const_with_default_order_error) + { + Error error (generic_params.front ()->get_locus (), + "invalid order for generic parameters: generic parameters " + "with a default must be trailing"); + add_error (std::move (error)); + } generic_params.shrink_to_fit (); return generic_params; diff --git a/gcc/testsuite/rust/compile/const_generics_17.rs b/gcc/testsuite/rust/compile/const_generics_17.rs new file mode 100644 index 00000000000..f65ca22b326 --- /dev/null +++ b/gcc/testsuite/rust/compile/const_generics_17.rs @@ -0,0 +1,3 @@ +struct Foo; // { dg-error "invalid order for generic parameters: generic parameters with a default must be trailing" } + +impl Foo {} diff --git a/gcc/testsuite/rust/compile/generics14.rs b/gcc/testsuite/rust/compile/generics14.rs new file mode 100644 index 00000000000..d97fd35a3a4 --- /dev/null +++ b/gcc/testsuite/rust/compile/generics14.rs @@ -0,0 +1 @@ +struct Foo; // { dg-error "invalid order for generic parameters: lifetime parameters must be declared prior to type and const parameters" }