-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[mypyc] Merge more primitive ops #9110
Conversation
oops, something broke mypyc. Had to do a binary search to find out.... |
Turn out this is much more complicated than I assumed... Here's what I find: using mypyc to compile mypy itself, the first assertion fail would happen during codegen the function: def __str__(self) -> str:
a = [] # type: List[str]
for key, value in self.items():
# Filter out the implicit import of builtins.
if isinstance(value, SymbolTableNode):
if (value.fullname != 'builtins' and
(value.fullname or '').split('.')[-1] not in
implicit_module_attrs):
a.append(' ' + str(key) + ' : ' + str(value))
else:
a.append(' <invalid item>')
a = sorted(a)
a.insert(0, 'SymbolTable(')
a[-1] += ')'
return '\n'.join(a) The when building the CallC for the from typing import Dict, List
class Node:
def __init__(self, x: int):
self.x = x
class Table(Dict[str, Node]):
def __str__(self) -> str:
a = [] # type: List[str]
for key, value in self.items():
if value.x > 10:
a.append('greater than 10')
else:
a.append('invalid item')
a = sorted(a)
a.insert(0, 'DummyNode')
return '\n'.join(a) There would be a result_type of So what causes such differences? It seems that the mypy/mypyc/irbuild/expression.py Lines 234 to 240 in ffdbeb3
the builder's types come from the mypy check, I am not sure why these two code snippets have different types on this expression. @JukkaL Updates: Updates 2: CPyL33: ;
cpy_r_r46 = CPyStatic_unicode_6250; /* ' <invalid item>' */
cpy_r_r47 = PyList_Append(cpy_r_a, cpy_r_r46) >= 0;
if (unlikely(!cpy_r_r47)) {
CPy_AddTraceback("mypy/nodes.py", "__str__", 3079, CPyStatic_nodes___globals);
goto CPyL59;
} else
goto CPyL34;
CPyL34: ;
cpy_r_r48 = cpy_r_r47 ? Py_True : Py_False;
goto CPyL35;
CPyL59: ;
CPy_DecRef(cpy_r_a);
CPyTagged_DecRef(cpy_r_r3);
CPy_DecRef(cpy_r_r4);
goto CPyL46; CPyL34 is the box operation from bool to object. |
I suspect that A reasonable way forward would be to ensure that the coercion to Here's a possible simplified test case (didn't verify that it results in the same issue): def f(x: List[str], y: str) -> None:
if isinstance(y, int): # Since int and str are distinct types, mypy things that this will always be false
x.append('x') If you are blocked on this, you can start working on some other issue while we investigate this, such as inlined integer operations. |
Yes exactly it is caused by mypy's report on unreachable code. I haven't checked the detail but in a |
# All ops returning int32/int64 should not be coerced into object. | ||
# Since their result will not be used elsewhere, it's safe to use NULL here | ||
elif is_int32_rprimitive(typ) or is_int64_rprimitive(typ): | ||
self.emit_lines('{}{} = NULL;'.format(declaration, dest)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here's the hack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine for now, but can you create a follow-up issue to properly box these as Python int
objects? It should be easy enough to support, and it could be useful in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, looks good! After this we don't have too many old-style primitives left.
Left one comment about follow-up task.
# All ops returning int32/int64 should not be coerced into object. | ||
# Since their result will not be used elsewhere, it's safe to use NULL here | ||
elif is_int32_rprimitive(typ) or is_int64_rprimitive(typ): | ||
self.emit_lines('{}{} = NULL;'.format(declaration, dest)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine for now, but can you create a follow-up issue to properly box these as Python int
objects? It should be easy enough to support, and it could be useful in the future.
Follows #9110's comment. Using CPython API to box int32/int64 into PyObject*.
relates mypyc/mypyc#734. This PR completes ALL ops of dict, str, list, tuple, set that are supported using current design. The remaining ones would rather need to split into multiple ops(via specializers) or using pointers.