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:
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
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