Skip to content

Adding switch to disable assertions #7732

@mlhetland

Description

@mlhetland

After a discussion on Julia-Users, it seems to me that at least some might agree with me that being able to turn off assertions could be a good idea. This is permitted in most languages, it seems. My suggestion is to follow the example of D, which I believe has made some sensible decisions on assertions and DbC in general. Their solution is to split assertions into two types, named assert and enforce. They then have a command-line switch named --release that turns off assert but leaves enforce in place. If we adopt such a switch, with an accessor similar to isinteractive(), it can be used also by others, similar to (but the negation of) the __debug__ variable in Python, which is set to True only if the -O switch is not supplied.

My suggestion is:

  • Add the switch --release at the Julia level (i.e., in client.jl) with a subsequently available accessor isrelease(), which is exported, so it can also be used by others (though this is an ancillary benefit).
  • Rename assert to enforce and @assert to @enforce.
  • Introduce new versions of assert and @assert that use isrelease() to determine whether to become a no-op or to delegate to enforce and @enforce, respectively. This will not entirely eliminate the cost of calls to assert, of course—one will still need to evaluate the arguments and execute the if-statement, but it will eliminate the cost (and the functionality) of @assert in release code.

The idea, then, is to use assert and @assert more for testing purposes, debugging and for checking for programming errors, and to use enforce and @enforce for error handling and input checking, and for any other kind of assertions one would want to keep in the code, regardless of release status.

I have made a stab at implementing the switch, function and macro. Because the switch only takes effect once client.jl is loaded, I have renamed the uses of assert to enforce in base/ (renamed all uses, for consistency, though not strictly necessary), but I left the uses in test/ alone. (I have updated repl.c but not docs, manpage or helpdb.jl, for example. And I haven't added any tests, as I didn't find any for the original assertion functionality, and I'm not sure what infrastructure you'd want to use to test command-line switches…)

The new function/macro are defined as follows—which I believe is not entirely correct…

assert(x) = isrelease() ? nothing : enforce(x)
macro assert(ex,msgs...)
    if isrelease()
        :nothing
    else
        :(@enforce(($ex),($msgs)...))
    end
end

It works for my simple ad hoc tests, but fails in, for example, test/bitarray.jl, where a call to @assert occurs inside another macro with an argument also named ex. I then get complaints on ex not existing. So I guess my quoting mojo isn't quite up to snuff, but I'm guessing this should be easy to fix? (Just calling @enforce gives me the wrong kind of return value, as far as I can see.)

Anyone interested in this? Should I submit a WIP pull request?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions