parse_functions keeps module-level functions based on exports.contains_key(name), so a nested
function slips through whenever a same-named module-level symbol is exported, and merge_overloads
then merges the two with winner-takes-all semantics:
def g(): # completely untyped
pass
def outer() -> None:
def g(x: int) -> str: # should be excluded
return str(x)
pyrefly coverage check passes (but it shouldn't):
INFO type coverage 100.00% (3 of 3 typable)
Renaming the nested g to something else, and g is now correctly reported as untyped:
WARN `g` is untyped [coverage-missing]
--> no_collision.py:1:1
|
1 | / def g():
2 | | pass
| |________-
|
ERROR type coverage 50.00% (1 of 2 typable) is below the 100.00% threshold
BindingUndecoratedFunction.outer_funcs already marks nested functions, but parse_functions
never checks it.
parse_functionskeeps module-level functions based onexports.contains_key(name), so a nestedfunction slips through whenever a same-named module-level symbol is exported, and
merge_overloadsthen merges the two with winner-takes-all semantics:
pyrefly coverage checkpasses (but it shouldn't):Renaming the nested
gto something else, andgis now correctly reported as untyped:BindingUndecoratedFunction.outer_funcsalready marks nested functions, butparse_functionsnever checks it.