Skip to content

Commit bd0271b

Browse files
authored
[mypyc] Fix some nondeterminism caused by iterating over sets/dicts (python#7594)
Tested by compiling mypy and comparing outputs on Python 3.5.
1 parent 8b86349 commit bd0271b

File tree

4 files changed

+10
-7
lines changed

4 files changed

+10
-7
lines changed

mypyc/emitclass.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ def wrapper_slot(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:
6969

7070
def generate_slots(cl: ClassIR, table: SlotTable, emitter: Emitter) -> Dict[str, str]:
7171
fields = OrderedDict() # type: Dict[str, str]
72-
for name, (slot, generator) in table.items():
72+
# Sort for determinism on Python 3.5
73+
for name, (slot, generator) in sorted(table.items()):
7374
method = cl.get_method(name)
7475
if method:
7576
fields[slot] = generator(cl, method, emitter)

mypyc/emitwrapper.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ def generate_dunder_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:
127127

128128
def generate_richcompare_wrapper(cl: ClassIR, emitter: Emitter) -> Optional[str]:
129129
"""Generates a wrapper for richcompare dunder methods."""
130-
matches = [name for name in RICHCOMPARE_OPS if cl.has_method(name)]
130+
# Sort for determinism on Python 3.5
131+
matches = sorted([name for name in RICHCOMPARE_OPS if cl.has_method(name)])
131132
if not matches:
132133
return None
133134

mypyc/genops.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ def __init__(self) -> None:
361361
self.type_to_ir = {} # type: Dict[TypeInfo, ClassIR]
362362
self.func_to_decl = {} # type: Dict[SymbolNode, FuncDecl]
363363
# Maps integer, float, and unicode literals to a static name
364-
self.literals = {} # type: LiteralsMap
364+
self.literals = OrderedDict() # type: LiteralsMap
365365

366366
def type_to_rtype(self, typ: Optional[Type]) -> RType:
367367
if typ is None:
@@ -1873,7 +1873,8 @@ def c() -> None:
18731873
env_for_func = self.fn_info.callable_class
18741874

18751875
if self.fn_info.fitem in self.free_variables:
1876-
for var in self.free_variables[self.fn_info.fitem]:
1876+
# Sort the variables to keep things deterministic
1877+
for var in sorted(self.free_variables[self.fn_info.fitem], key=lambda x: x.name()):
18771878
if isinstance(var, Var):
18781879
rtype = self.type_to_rtype(var.type)
18791880
self.add_var_to_env_class(var, rtype, env_for_func, reassign=False)

mypyc/prebuildvisitor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ def __init__(self) -> None:
2727
self.prop_setters = set() # type: Set[FuncDef]
2828
# A map from any function that contains nested functions to
2929
# a set of all the functions that are nested within it.
30-
self.encapsulating_funcs = dict() # type: Dict[FuncItem, Set[FuncItem]]
30+
self.encapsulating_funcs = {} # type: Dict[FuncItem, List[FuncItem]]
3131
# A map from a nested func to it's parent/encapsulating func.
32-
self.nested_funcs = dict() # type: Dict[FuncItem, FuncItem]
32+
self.nested_funcs = {} # type: Dict[FuncItem, FuncItem]
3333
self.funcs_to_decorators = {} # type: Dict[FuncDef, List[Expression]]
3434

3535
def add_free_variable(self, symbol: SymbolNode) -> None:
@@ -57,7 +57,7 @@ def visit_func(self, func: FuncItem) -> None:
5757
# being a nested function.
5858
if self.funcs:
5959
# Add the new func to the set of nested funcs within the func at top of the func stack.
60-
self.encapsulating_funcs.setdefault(self.funcs[-1], set()).add(func)
60+
self.encapsulating_funcs.setdefault(self.funcs[-1], []).append(func)
6161
# Add the func at top of the func stack as the parent of new func.
6262
self.nested_funcs[func] = self.funcs[-1]
6363

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy