From fd3fbcc3bd7d73925e4e573fd64d73ca41603d84 Mon Sep 17 00:00:00 2001 From: Amrita kumari mishra Date: Mon, 8 Dec 2025 09:19:53 +0000 Subject: [PATCH] Fix: Raise SemanticError for unsupported inline class instantiation #2826 --- src/lpython/semantics/python_ast_to_asr.cpp | 26 +++++++++++++++++++++ tests/errors/test_inline_class_error.py | 15 ++++++++++++ tests/reference/pass_inline_class_safe.py | 9 +++++++ 3 files changed, 50 insertions(+) create mode 100644 tests/errors/test_inline_class_error.py create mode 100644 tests/reference/pass_inline_class_safe.py diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 4d116cfce7..b9322ce5a5 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -8488,6 +8488,32 @@ we will have to use something else. void visit_Call(const AST::Call_t &x) { std::string call_name = ""; Vec args; + for (size_t i = 0; i < x.n_args; i++) { + AST::expr_t *arg_expr = x.m_args[i]; + + if (arg_expr->type == AST::exprType::Call) { + AST::Call_t *call_node = (AST::Call_t*)arg_expr; + + if (call_node->m_func->type == AST::exprType::Name) { + AST::Name_t *func_name = (AST::Name_t*)call_node->m_func; + std::string name = std::string(func_name->m_id); + + // Resolve symbol + ASR::symbol_t *sym = current_scope->resolve_symbol(name); + + if (sym) { + sym = ASRUtils::symbol_get_past_external(sym); + + // FIX: Only check for Struct (Python classes are Structs in ASR) + if (sym->type == ASR::symbolType::Struct) { + throw SemanticError("Inline class instantiation (e.g. print(Foo(10))) is not yet supported. " + "Please assign it to a variable first.", + arg_expr->base.loc); + } + } + } + } + } if (AST::is_a(*x.m_func)) { AST::Name_t *n = AST::down_cast(x.m_func); call_name = n->m_id; diff --git a/tests/errors/test_inline_class_error.py b/tests/errors/test_inline_class_error.py new file mode 100644 index 0000000000..c86844e50c --- /dev/null +++ b/tests/errors/test_inline_class_error.py @@ -0,0 +1,15 @@ +class Foo: + def __init__(self: "Foo", x: i32): + self.x: i32 = x + +def my_func(f: Foo): + pass + +def main(): + # This should trigger the SemanticError immediately + print(Foo(10)) + + # This checks the other case (function params) + my_func(Foo(20)) + +main() \ No newline at end of file diff --git a/tests/reference/pass_inline_class_safe.py b/tests/reference/pass_inline_class_safe.py new file mode 100644 index 0000000000..1896271613 --- /dev/null +++ b/tests/reference/pass_inline_class_safe.py @@ -0,0 +1,9 @@ +class Foo: + def __init__(self: "Foo", x: i32): + self.x: i32 = x + +def main(): + a: Foo = Foo(10) + print(a) + +main()