lpython
lpython copied to clipboard
Improper mutable list in dataclass initializer should error, not throw
offending code:
from lpython import dataclass, i32
@dataclass
class foo:
bar : list[i32] = [] ######### INCORRECT ###########
run:
# CPYTHON
(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm/Issue2031)───────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s012)─┐
└─(16:52:15 on brian-lasr ✹ ✚ ✭)──> PYTHONPATH='../../../src/runtime/lpython' python issue2031.py ──(Sun,Jun25)─┘
Traceback (most recent call last):
File "/Users/brian/CLionProjects/lpython/lasr/LP-pycharm/Issue2031/issue2031.py", line 4, in <module>
class foo:
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 956, in _process_class
cls_fields.append(_get_field(cls, name, type, kw_only))
File "/Users/brian/mambaforge/envs/lp/lib/python3.10/dataclasses.py", line 813, in _get_field
raise ValueError(f'mutable default {type(f.default)} for field '
ValueError: mutable default <class 'list'> for field bar is not allowed: use default_factory
# LPYTHON
(lp) ┌─(~/CLionProjects/lpython/lasr/LP-pycharm/Issue2031)───────────────────────────────────────────────────────────────────────────────────────────────(brian@Golf37:s012)─┐
└─(16:52:22 on brian-lasr ✹ ✚ ✭)──> ~/CLionProjects/lpython/src/bin/lpython -I. issue2031.py 1 ↵ ──(Sun,Jun25)─┘
Internal Compiler Error: Unhandled exception
Traceback (most recent call last):
File "/Users/brian/CLionProjects/lpython/src/bin/lpython.cpp", line 1844
err = compile_python_to_object_file(arg_file, tmp_o, runtime_library_dir,
File "/Users/brian/CLionProjects/lpython/src/bin/lpython.cpp", line 783
r1 = LCompilers::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options,
File "/Users/brian/CLionProjects/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 7520
auto res = symbol_table_visitor(al, lm, *ast_m, diagnostics, main_module,
File "/Users/brian/CLionProjects/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 4542
v.visit_Module(ast);
File "/Users/brian/CLionProjects/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 3865
visit_stmt(*x.m_body[i]);
File "/Users/brian/CLionProjects/lpython/src/lpython/python_ast.h", line 1883
void visit_stmt(const stmt_t &b) { visit_stmt_t(b, self()); }
File "/Users/brian/CLionProjects/lpython/src/lpython/python_ast.h", line 1752
case stmtType::AsyncFunctionDef: { v.visit_AsyncFunctionDef((const AsyncFunctionDef_t &)x); return; }
File "/Users/brian/CLionProjects/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 3096
visit_ClassMembers(x, member_names, struct_dependencies, false, class_abi);
File "/Users/brian/CLionProjects/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 2900
visit_AnnAssignUtil(*ann_assign, var_name, false, init_expr, abi);
File "/Users/brian/CLionProjects/lpython/src/lpython/semantics/python_ast_to_asr.cpp", line 2799
this->visit_expr(*x.m_value);
File "/Users/brian/CLionProjects/lpython/src/lpython/python_ast.h", line 1910
void visit_expr(const expr_t &b) { visit_expr_t(b, self()); }
File "/Users/brian/CLionProjects/lpython/src/lpython/python_ast.h", line 1814
case exprType::Name: { v.visit_Name((const Name_t &)x); return; }
File "/Users/brian/CLionProjects/lpython/src/lpython/python_ast.h", line 1942
void visit_List(const List_t & /* x */) { throw LCompilersException("visit_List() not implemented"); }
LCompilersException: visit_List() not implemented
Looks like we DO have field and default_factory ! GREAT!
can you assign this issue to me?
I need a little help here to work with. I went a little through the python_ast_to_asr.cpp file and I am think I need to handle the error here instead of throwing. I am not sure about this please confirm
void visit_List(const AST::List_t &x) {
Vec<ASR::expr_t*> list;
list.reserve(al, x.n_elts + 1);
ASR::ttype_t *type = nullptr;
ASR::expr_t *expr = nullptr;
if( x.n_elts > 0 ) {
this->visit_expr(*x.m_elts[0]);
expr = ASRUtils::EXPR(tmp);
type = ASRUtils::expr_type(expr);
list.push_back(al, expr);
for (size_t i = 1; i < x.n_elts; i++) {
this->visit_expr(*x.m_elts[i]);
expr = ASRUtils::EXPR(tmp);
if (!ASRUtils::check_equal_type(ASRUtils::expr_type(expr), type)) {
// Handle the error instead of throwing ?
throw SemanticError("All List elements must be of the same type for now",
x.base.base.loc);
}
list.push_back(al, expr);
}
} else {
if( assign_asr_target == nullptr ) {
tmp = nullptr;
return ;
}
type = ASRUtils::get_contained_type(
ASRUtils::type_get_past_const(ASRUtils::expr_type(assign_asr_target)));
}
ASR::ttype_t* list_type = ASRUtils::TYPE(ASR::make_List_t(al, x.base.base.loc, type));
tmp = ASR::make_ListConstant_t(al, x.base.base.loc, list.p,
list.size(), list_type);
}
Also how can I compile lpython code?
I want to reproduce the output for this code locally
from lpython import dataclass, i32
@dataclass
class foo:
bar : list[i32] = [] ######### INCORRECT ###########