Bug
PNot in PythonRuntimeLaurelPart.lean is unsound for None and DictStrAny inputs. It falls through to exception(UndefinedError(...)) for these types, but Python's not operator works on all types (it's equivalent to not bool(x)) and never raises an exception for non-exception inputs.
Affected cases
| Expression |
Python behavior |
Strata (PNot) result |
not None |
True |
❌ exception(UndefinedError(...)) |
not {} |
True |
❌ exception(UndefinedError(...)) |
PNot currently handles bool, int, float, str, and ListAny, but is missing branches for None and DictStrAny.
Related issue in Any_to_bool
Any_to_bool (around line 309) has a similar gap — it handles None and DictStrAny but is missing float. These two functions should be kept in sync since not x is semantically not bool(x).
Proposed fix
- Add
None and DictStrAny branches to PNot
- Change the
else branch from exception to hole (to be safe for types not yet modeled, e.g. datetime, bytes, ClassInstance)
- Add the missing
float branch to Any_to_bool
- Align
PNot and Any_to_bool so they cover the same set of types
Sketch for PNot:
function PNot (v: Any) : Any
{
if Any..isexception(v) then v
else if Any..isfrom_bool(v) then from_bool(!(Any..as_bool!(v)))
else if Any..isfrom_int(v) then from_bool(!(Any..as_int!(v) == 0))
else if Any..isfrom_float(v) then from_bool(!(Any..as_float!(v) == 0.0))
else if Any..isfrom_str(v) then from_bool(!(Any..as_string!(v) == ""))
else if Any..isfrom_ListAny(v) then from_bool(!(List_len(Any..as_ListAny!(v)) == 0))
else if Any..isfrom_None(v) then from_bool(true)
else if Any..isfrom_DictStrAny(v) then from_bool(!(Any..as_Dict!(v) == DictStrAny_empty()))
else hole
};
Context
Discovered during review of #926 (bitwise operators PR). See this review thread for the full discussion.
Bug
PNotinPythonRuntimeLaurelPart.leanis unsound forNoneandDictStrAnyinputs. It falls through toexception(UndefinedError(...))for these types, but Python'snotoperator works on all types (it's equivalent tonot bool(x)) and never raises an exception for non-exception inputs.Affected cases
PNot) resultnot NoneTrueexception(UndefinedError(...))not {}Trueexception(UndefinedError(...))PNotcurrently handlesbool,int,float,str, andListAny, but is missing branches forNoneandDictStrAny.Related issue in
Any_to_boolAny_to_bool(around line 309) has a similar gap — it handlesNoneandDictStrAnybut is missingfloat. These two functions should be kept in sync sincenot xis semanticallynot bool(x).Proposed fix
NoneandDictStrAnybranches toPNotelsebranch fromexceptiontohole(to be safe for types not yet modeled, e.g.datetime,bytes,ClassInstance)floatbranch toAny_to_boolPNotandAny_to_boolso they cover the same set of typesSketch for
PNot:Context
Discovered during review of #926 (bitwise operators PR). See this review thread for the full discussion.