Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion pyrefly/lib/alt/class/class_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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<DataclassMetadata> {
// If we inherit from a dataclass, inherit its metadata. Note that if this class is
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down
13 changes: 13 additions & 0 deletions pyrefly/lib/test/dataclasses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading