Skip to content

Commit 9cee832

Browse files
committed
expand: Add error check if derive has wrong item
The DeriveVisitor previously dispatched calls to specific handlers (like DeriveClone) without validating the input item type. This caused internal compiler errors (ICEs) when users attempted to derive traits on invalid items like functions or traits, as the handlers assumed the input was a struct, enum, or union. This patch adds a validation predicate `validate_item` to the DeriveVisitor to reject invalid items gracefully with a diagnostic error before dispatching. Fixes #3875 gcc/rust/ChangeLog: * expand/rust-derive.h (DeriveVisitor::validate_item): Add prototype. * expand/rust-derive.cc (DeriveVisitor::derive): Use visitor validation. (DeriveVisitor::validate_item): New function to check item kind. gcc/testsuite/ChangeLog: * rust/compile/issue-3875.rs: New test. Signed-off-by: Jayant Chauhan <0001jayant@gmail.com>
1 parent c35ffdb commit 9cee832

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

gcc/rust/expand/rust-derive.cc

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,9 @@ DeriveVisitor::derive (Item &item, const Attribute &attr,
4040
{
4141
auto loc = attr.get_locus ();
4242

43-
using Kind = AST::Item::Kind;
44-
auto item_kind = item.get_item_kind ();
45-
if (item_kind != Kind::Enum && item_kind != Kind::Struct
46-
&& item_kind != Kind::Union)
43+
if (!DeriveVisitor::validate_item (item, attr))
4744
{
48-
rust_error_at (loc,
49-
"derive may only be applied to structs, enums and unions");
50-
return {};
45+
return std::vector<std::unique_ptr<Item>> ();
5146
}
5247

5348
switch (to_derive)
@@ -159,5 +154,20 @@ DeriveVisitor::setup_impl_generics (
159154
return ImplGenerics{std::move (self_type_path), std::move (impl_generics)};
160155
}
161156

157+
bool
158+
DeriveVisitor::validate_item (const Item &item, const Attribute &attr)
159+
{
160+
using Kind = AST::Item::Kind;
161+
auto item_kind = item.get_item_kind ();
162+
163+
if (item_kind == Kind::Enum || item_kind == Kind::Struct
164+
|| item_kind == Kind::Union || item_kind == Kind::TupleStruct)
165+
return true;
166+
167+
rust_error_at (attr.get_locus (),
168+
"derive may only be applied to structs, enums and unions");
169+
return false;
170+
}
171+
162172
} // namespace AST
163173
} // namespace Rust

gcc/rust/expand/rust-derive.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class DeriveVisitor : public AST::ASTVisitor
7171
= tl::nullopt) const;
7272

7373
private:
74+
static bool validate_item (const AST::Item &item, const Attribute &attr);
7475
// the 4 "allowed" visitors, which a derive-visitor can specify and override
7576
virtual void visit_struct (StructStruct &struct_item) = 0;
7677
virtual void visit_tuple (TupleStruct &tuple_item) = 0;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// { dg-options "-w" }
2+
3+
#[derive(Clone)] // { dg-error "derive may only be applied to structs, enums and unions" }
4+
fn foo() {} // { dg-excess-errors "" }
5+
6+
#[derive(Debug)] // { dg-error "derive may only be applied to structs, enums and unions" }
7+
trait Bar {} // { dg-excess-errors "" }
8+
9+
#[derive(Copy, Clone)]
10+
struct TupleStruct(i32); // This should NOT error
11+
12+
fn main() {}

0 commit comments

Comments
 (0)