Nuitka: Error handling immediately-invoked lambda expression with default parameters

Created on 16 Jul 2019  路  4Comments  路  Source: Nuitka/Nuitka

I was testing Nuitka on a few packages, and ran into an issue with a specific lambda construct. I've been able to reproduce it in multiple Nuitka versions, most recently 0.6.5rc4 built off the develop branch. The minimal example is this statement:

(lambda x='hi': print(x))()

Nuitka handles these similar statements without a problem:

(lambda x: print(x))('hi')
func = (lambda x='hi': print(x))
func()
(lambda: print('hi'))()

So as far as I can tell this issue only arises from lambda expressions which:

  1. Provide a default parameter value
  2. Are invoked immediately with no arguments

This is admittedly an edge case, and a weird construct to see in Python code. That said, it runs in all Python 2/3 versions I've tested. With Nuitka, it throws this:

Problem with statement at test.py:7:
-> (lambda x='hi': print(x))()

Nuitka:INFO:Interrupted while working on '<Node 'PYTHON_MAIN_MODULE' with {'filename': 'test.py', 'main_added': False, 'mode': 'compiled'}>'.
Traceback (most recent call last):
  File "/Users/akerrigan/code/Nuitka/nuitka/__main__.py", line 184, in <module>
    main()
  File "/Users/akerrigan/code/Nuitka/nuitka/__main__.py", line 177, in main
    MainControl.main()
  File "/Users/akerrigan/code/Nuitka/nuitka/MainControl.py", line 746, in main
    main_module = createNodeTree(filename=filename)
  File "/Users/akerrigan/code/Nuitka/nuitka/MainControl.py", line 141, in createNodeTree
    Optimization.optimize(main_module.getOutputFilename())
  File "/Users/akerrigan/code/Nuitka/nuitka/optimizations/Optimization.py", line 542, in optimize
    makeOptimizationPass(initial_pass=True)
  File "/Users/akerrigan/code/Nuitka/nuitka/optimizations/Optimization.py", line 456, in makeOptimizationPass
    changed = optimizeModule(current_module)
  File "/Users/akerrigan/code/Nuitka/nuitka/optimizations/Optimization.py", line 167, in optimizeModule
    changed = optimizeCompiledPythonModule(module)
  File "/Users/akerrigan/code/Nuitka/nuitka/optimizations/Optimization.py", line 100, in optimizeCompiledPythonModule
    module.computeModule()
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/ModuleNodes.py", line 489, in computeModule
    trace_collection=self.trace_collection
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/StatementNodes.py", line 165, in computeStatementsSequence
    new_statement = statement.computeStatementsSequence(trace_collection)
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/FrameNodes.py", line 182, in computeStatementsSequence
    new_statement = trace_collection.onStatement(statement=statement)
  File "/Users/akerrigan/code/Nuitka/nuitka/optimizations/TraceCollections.py", line 550, in onStatement
    new_statement, change_tags, change_desc = statement.computeStatement(self)
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/StatementNodes.py", line 229, in computeStatement
    trace_collection.onExpression(expression=self.getExpression())
  File "/Users/akerrigan/code/Nuitka/nuitka/optimizations/TraceCollections.py", line 531, in onExpression
    r = expression.computeExpressionRaw(trace_collection=self)
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/ExpressionBases.py", line 1005, in computeExpressionRaw
    return self.computeExpression(trace_collection=trace_collection)
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/CallNodes.py", line 172, in computeExpression
    trace_collection=trace_collection,
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/FunctionNodes.py", line 708, in computeExpressionCall
    function=self, values=values, source_ref=call_node.getSourceReference()
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/FunctionNodes.py", line 861, in __init__
    source_ref=source_ref,
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/ExpressionBases.py", line 974, in __init__
    ChildrenHavingMixin.__init__(self, values=values)
  File "/Users/akerrigan/code/Nuitka/nuitka/nodes/NodeBases.py", line 526, in __init__
    assert None not in value, name
AssertionError: values

python -m nuitka --version output:

0.6.5rc4
Python: 3.7.3 (default, Mar 27 2019, 09:23:32)
Executable: /usr/local/opt/python/bin/python3.7
OS: Darwin
Arch: x86_64

Installation methods: Python 3.7 via homebrew, Nuitka via pip

bug

All 4 comments

Thanks for your report, this is of course a very valid bug report. As the result of optimization, this ought to be also possibe, but I recall that I disabled some for functions with defaults, which avoids this. I will take care of this to work though. I think defaults ought to be very easy anyway for function inlining, as they can be assigned first, and only then arguments.

There is a workaround on factory branch, effectively disable the optimization for cases where default values are used. The whole optimization needs more work there, few cases are currently dealt with only.

Neat, thank you! Following the effects of the change helps me understand the flow a little better too :).

Released as part of 0.6.6, need to check back on this how to make the optimization work generally

Was this page helpful?
0 / 5 - 0 ratings