Skip to content

Fundamental inconsistency in dataclass initializtion: MVE #2045

Open
@rebcabin

Description

@rebcabin

There is a fundamental inconsistency between LPython and CPython. I do not know how to make a single Python file with the following features that passes both. This issue is a minimization and clarification of Issue #2031, but not exactly a duplicate.

Consider

from lpython import (dataclass, i32)

@dataclass
class Foo:
    string : str

@dataclass
class Bar :
    foo : Foo
    il : list[i32]

bar : Bar = Bar(Foo('bar'), [1, 2, 3])

This passes CPython, but not LPython:

# CPYTHON

(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm)─────────────────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s001)─┐
└─(19:11:35 on brian-lasr ✖ ✹ ✭)──> PYTHONPATH='../../src/runtime/lpython' python issue2045.py                                                        1 ↵ ──(Mon,Jun26)─┘

# LPYTHON

(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm)─────────────────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s001)─┐
└─(19:11:51 on brian-lasr ✖ ✹ ✭)──> ~/CLionProjects/lpython/src/bin/lpython -I. issue2045.py                                                              ──(Mon,Jun26)─┘
semantic error: `foo` must be initialized with an instance of Foo
  --> issue2045.py:11:5
   |
11 |     foo : Foo
   |     ^^^^^^^^^ 

ok, so we'll add that initializer. Now it fails CPython but not LPython:

from lpython import (dataclass, i32)

@dataclass
class Foo:
    string : str

@dataclass
class Bar :
    foo : Foo = Foo('foo')
    il : list[i32]

bar : Bar = Bar(Foo('bar'), [1, 2, 3])

run:

# CPYTHON

(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm)─────────────────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s001)─┐
└─(19:16:19 on brian-lasr ✖ ✹ ✭)──> PYTHONPATH='../../src/runtime/lpython' python issue2045.py                                                        2 ↵ ──(Mon,Jun26)─┘
Traceback (most recent call last):
  File "/Users/brian/CLionProjects/lpython/lasr/LP-pycharm/issue2045.py", line 8, in <module>
    class Bar :
  File "/Users/brian/CLionProjects/lpython/src/runtime/lpython/lpython.py", line 55, in dataclass
    return py_dataclass(arg)
  File "/Users/brian/mambaforge/envs/lp/lib/python3.10/dataclasses.py", line 1185, in dataclass
    return wrap(cls)
  File "/Users/brian/mambaforge/envs/lp/lib/python3.10/dataclasses.py", line 1176, in wrap
    return _process_class(cls, init, repr, eq, order, unsafe_hash,
  File "/Users/brian/mambaforge/envs/lp/lib/python3.10/dataclasses.py", line 1025, in _process_class
    _init_fn(all_init_fields,
  File "/Users/brian/mambaforge/envs/lp/lib/python3.10/dataclasses.py", line 546, in _init_fn
    raise TypeError(f'non-default argument {f.name!r} '
TypeError: non-default argument 'il' follows default argument

# LPYTHON

(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm)─────────────────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s001)─┐
└─(19:16:36 on brian-lasr ✖ ✹ ✭)──> ~/CLionProjects/lpython/src/bin/lpython -I. issue2045.py                                                          1 ↵ ──(Mon,Jun26)─┘
(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm)─────────────────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s00

Ok, so we'll add the initializer. Now it still fails CPython, and there seems to be no fix because lpython does not actually export field and default_factory:

from lpython import (dataclass, i32,
                     field, default_factory)

@dataclass
class Foo:
    string : str

@dataclass
class Bar :
    foo : Foo = Foo('foo')
    il : list[i32] = field(default_factory=list)

bar : Bar = Bar(Foo('bar'), [1, 2, 3])

run:

# CPYTHON

(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm)─────────────────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s001)─┐
└─(19:20:10 on brian-lasr ✖ ✹ ✭)──> PYTHONPATH='../../src/runtime/lpython' python issue2045.py                                                        1 ↵ ──(Mon,Jun26)─┘
Traceback (most recent call last):
  File "/Users/brian/CLionProjects/lpython/lasr/LP-pycharm/issue2045.py", line 1, in <module>
    from lpython import (dataclass, i32,
ImportError: cannot import name 'field' from 'lpython' (/Users/brian/CLionProjects/lpython/src/runtime/lpython/lpython.py)

# LPYTHON

(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm)─────────────────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s001)─┐
└─(19:20:22 on brian-lasr ✖ ✹ ✭)──> ~/CLionProjects/lpython/src/bin/lpython -I. issue2045.py                                                          1 ↵ ──(Mon,Jun26)─┘
(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm)─────────────────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s001)─┐
└─(19:20:27 on brian-lasr ✖ ✹ ✭)──>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions