Skip to content

[mypyc] Fix some nondeterminism caused by iterating over sets/dicts #7594

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

Merged
merged 1 commit into from
Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[mypyc] Fix some nondeterminism caused by iterating over sets/dicts
Tested by compiling mypy and comparing outputs on Python 3.5.
  • Loading branch information
msullivan committed Oct 1, 2019
commit 981febd19034493a3aa100c62c866097562e67bb
3 changes: 2 additions & 1 deletion mypyc/emitclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ def wrapper_slot(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:

def generate_slots(cl: ClassIR, table: SlotTable, emitter: Emitter) -> Dict[str, str]:
fields = OrderedDict() # type: Dict[str, str]
for name, (slot, generator) in table.items():
# Sort for determinism on Python 3.5
for name, (slot, generator) in sorted(table.items()):
method = cl.get_method(name)
if method:
fields[slot] = generator(cl, method, emitter)
Expand Down
3 changes: 2 additions & 1 deletion mypyc/emitwrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ def generate_dunder_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:

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

Expand Down
5 changes: 3 additions & 2 deletions mypyc/genops.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ def __init__(self) -> None:
self.type_to_ir = {} # type: Dict[TypeInfo, ClassIR]
self.func_to_decl = {} # type: Dict[SymbolNode, FuncDecl]
# Maps integer, float, and unicode literals to a static name
self.literals = {} # type: LiteralsMap
self.literals = OrderedDict() # type: LiteralsMap

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

if self.fn_info.fitem in self.free_variables:
for var in self.free_variables[self.fn_info.fitem]:
# Sort the variables to keep things deterministic
for var in sorted(self.free_variables[self.fn_info.fitem], key=lambda x: x.name()):
if isinstance(var, Var):
rtype = self.type_to_rtype(var.type)
self.add_var_to_env_class(var, rtype, env_for_func, reassign=False)
Expand Down
6 changes: 3 additions & 3 deletions mypyc/prebuildvisitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def __init__(self) -> None:
self.prop_setters = set() # type: Set[FuncDef]
# A map from any function that contains nested functions to
# a set of all the functions that are nested within it.
self.encapsulating_funcs = dict() # type: Dict[FuncItem, Set[FuncItem]]
self.encapsulating_funcs = {} # type: Dict[FuncItem, List[FuncItem]]
# A map from a nested func to it's parent/encapsulating func.
self.nested_funcs = dict() # type: Dict[FuncItem, FuncItem]
self.nested_funcs = {} # type: Dict[FuncItem, FuncItem]
self.funcs_to_decorators = {} # type: Dict[FuncDef, List[Expression]]

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

Expand Down
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