From 6aa5b04b966436f46f1b3e5c7a71848e63c027d9 Mon Sep 17 00:00:00 2001 From: Vivek JM <24496671+vivekjm@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:34:22 +0530 Subject: [PATCH] Reject dataclass decorators on NamedTuple classes --- pyrefly/lib/alt/class/class_metadata.rs | 13 ++++++++++++- pyrefly/lib/test/dataclasses.rs | 13 +++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/pyrefly/lib/alt/class/class_metadata.rs b/pyrefly/lib/alt/class/class_metadata.rs index 1079e2c723..9a290039c6 100644 --- a/pyrefly/lib/alt/class/class_metadata.rs +++ b/pyrefly/lib/alt/class/class_metadata.rs @@ -446,6 +446,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> { protocol_metadata.is_some(), enum_metadata.is_some(), is_typed_dict, + named_tuple_metadata.is_some(), errors, ); if let Some(dm) = dataclass_metadata.as_ref() @@ -1037,6 +1038,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> { is_protocol: bool, is_enum: bool, is_typed_dict: bool, + is_named_tuple: bool, errors: &ErrorCollector, ) -> Option { // If we inherit from a dataclass, inherit its metadata. Note that if this class is @@ -1106,7 +1108,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> { _ => {} } } - // @dataclass cannot be applied to Protocol, Enum, or TypedDict classes. + // @dataclass cannot be applied to Protocol, Enum, TypedDict, or NamedTuple classes. // Emit the error and return None so the class is not treated as a dataclass. if has_dataclass_decorator { if is_protocol { @@ -1139,6 +1141,15 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> { ); return None; } + if is_named_tuple { + self.error( + errors, + cls.range(), + ErrorKind::BadClassDefinition, + format!("Cannot apply `@dataclass` to NamedTuple `{}`", cls.name()), + ); + return None; + } } if let Some((kws, field_specifiers)) = dataclass_from_dataclass_transform { // Inherit before-validator fields from base pydantic models, then add our own. diff --git a/pyrefly/lib/test/dataclasses.rs b/pyrefly/lib/test/dataclasses.rs index 407ee53456..0ff2130bda 100644 --- a/pyrefly/lib/test/dataclasses.rs +++ b/pyrefly/lib/test/dataclasses.rs @@ -2443,6 +2443,19 @@ class DC2(Protocol, DC): # E: If `Protocol` is included as a base class, all ot "#, ); +// https://github.com/facebook/pyrefly/issues/3751 +testcase!( + test_dataclass_decorator_on_named_tuple, + r#" +from dataclasses import dataclass +from typing import NamedTuple + +@dataclass +class Foo(NamedTuple): # E: Cannot apply `@dataclass` to NamedTuple + x: int +"#, +); + // https://github.com/facebook/pyrefly/issues/2920 testcase!( test_frozen_dataclass_override_setattr_delattr,