facebook / facebook/pyrefly

1.2.0-dev.1: false bad-class-definition when a non-dataclass mixin annotates an inherited MappedAsDataclass field

Open
#4,179 0 comments 0 reactions 0 assignees View on GitHub
sqlalchemy typechecking
Dominant language
Rust
Stars
7k
Forks
516
PR merge metrics
No merged PRs in 30d

Description

### Describe the Bug

Hello,
See script & commands below:
```python
❯ uvx --from pyrefly==1.1.1 pyrefly check repro_pyrefly_dataclass_false_positive.py
INFO 0 errors

❯ uvx --from pyrefly==1.2.0-dev.1 pyrefly check repro_pyrefly_dataclass_false_positive.py
ERROR Dataclass field `data` without a default may not follow dataclass field with a default [bad-class-definition]
--> repro_pyrefly_dataclass_false_positive.py:36:7
|
36 | class VideoJob(PlainMixin, JobBase):
| ^^^^^^^^
|
INFO 1 error

❯ uvx --from pyrefly==1.2.0-dev.2 pyrefly check repro_pyrefly_dataclass_false_positive.py
ERROR Dataclass field `data` without a default may not follow dataclass field with a default [bad-class-definition]
--> repro_pyrefly_dataclass_false_positive.py:36:7
|
36 | class VideoJob(PlainMixin, JobBase):
| ^^^^^^^^
|
INFO 1 error
```

```python
# /// script
# requires-python = "==3.14.*"
# dependencies = ["sqlalchemy==2.0.51"]
# ///
"""Pyrefly >=1.2.0-dev.1 reports "Dataclass field `data` without a default may not follow
dataclass field with a default" on ``VideoJob``, yet nothing here has a default: ``__init__``
is ``(self, id, data)`` and the class instantiates, which running the file prints.
"""

import inspect
from typing import TYPE_CHECKING

from sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass, mapped_column

class Base(MappedAsDataclass, DeclarativeBase):
pass

class JobBase(Base):
__abstract__ = True
id: Mapped[int] = mapped_column(primary_key=True)
data: Mapped[str] = mapped_column()

class PlainMixin:
if TYPE_CHECKING:
data: str

class VideoJob(PlainMixin, JobBase):
__tablename__ = "video_job"

if __name__ == "__main__":
print("VideoJob.__init__", inspect.signature(VideoJob.__init__))
print(VideoJob(id=1, data="x"))

```

### Sandbox Link

_No response_

### (Only applicable for extension issues) IDE Information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the diagnostic with repro_pyrefly_dataclass_false_positive.py using the pyrefly 1.2.0-dev.1 or dev.2 command shown. Trace handling of MappedAsDataclass inheritance, the PlainMixin annotation, and the bad-class-definition diagnostic. Done means the example produces no false-positive error while preserving the reported valid constructor behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.