Skip to content
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

Move error.jl docs inline; add example to catch_backtrace() #18961

Closed
wants to merge 2 commits into from
Closed
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
52 changes: 0 additions & 52 deletions base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,6 @@

# Base

"""
systemerror(sysfunc, iftrue)

Raises a `SystemError` for `errno` with the descriptive string `sysfunc` if `iftrue` is `true`
"""
systemerror

"""
fill!(A, x)

Expand Down Expand Up @@ -176,13 +169,6 @@ julia> [1 2 3] .* [1 2 3]
"""
Base.:(.*)

"""
backtrace()

Get a backtrace object for the current program point.
"""
backtrace

"""
-(x)

Expand Down Expand Up @@ -290,14 +276,6 @@ Neither `convert` nor `cconvert` should take a Julia object and turn it into a `
"""
cconvert

"""
assert(cond)

Throw an [`AssertionError`](:obj:`AssertionError`) if `cond` is `false`.
Also available as the macro `@assert expr`.
"""
assert

"""
sech(x)

Expand Down Expand Up @@ -2155,13 +2133,6 @@ Show a descriptive representation of an exception object.
"""
showerror

"""
error(message::AbstractString)

Raise an `ErrorException` with the given message.
"""
error

"""
sqrtm(A)

Expand Down Expand Up @@ -2538,14 +2509,6 @@ This is intended to be called using `do` block syntax:
"""
get!(f::Function,collection,key)

"""
@assert cond [text]

Throw an `AssertionError` if `cond` is `false`. Preferred syntax for writing assertions.
Message `text` is optionally displayed upon assertion failure.
"""
:@assert

"""
deserialize(stream)

Expand Down Expand Up @@ -2587,14 +2550,6 @@ Cumulative product of `A` along a dimension, storing the result in `B`. The dime
"""
cumprod!

"""
rethrow([e])

Throw an object without changing the current exception backtrace. The default argument is
the current exception (if called within a `catch` block).
"""
rethrow

"""
!(x)

Expand Down Expand Up @@ -2799,13 +2754,6 @@ garbage answers, in the same manner as C.
"""
unsafe_load

"""
catch_backtrace()

Get the backtrace of the current exception, for use within `catch` blocks.
"""
catch_backtrace

"""
cos(x)

Expand Down
59 changes: 59 additions & 0 deletions base/error.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,83 @@

## native julia error handling ##

"""
error(message::AbstractString)

Raise an `ErrorException` with the given message.
"""
error(s::AbstractString) = throw(ErrorException(s))
error(s...) = throw(ErrorException(Main.Base.string(s...)))

"""
rethrow([e])

Throw an object without changing the current exception backtrace. The default argument is
the current exception (if called within a `catch` block).
"""
rethrow() = ccall(:jl_rethrow, Bottom, ())
rethrow(e) = ccall(:jl_rethrow_other, Bottom, (Any,), e)

"""
backtrace()

Get a backtrace object for the current program point.
"""
backtrace() = ccall(:jl_backtrace_from_here, Array{Ptr{Void},1}, (Int32,), false)

"""
catch_backtrace()

Get the backtrace of the current exception, for use within `catch` blocks.
The backtrace is represented as an `Array{Ptr{Void}}` of addresses, so [`showerror`](:func:`showerror`)
may be helpful for displaying the backtrace in a human-readable format.

# Example

```jldoctest
julia> f(x) = try
sqrt(x)
catch y
bt = catch_backtrace()
showerror(STDOUT, y, bt)
end;

julia> f(-1)
DomainError:
in f(::Int64) at ./REPL[24]:2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this doctest pass like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I made a mistake. As you suggested earlier, the output from running doctests is different from what you get at the repl.

Additionally, it looks like I need to add a println() statement to get the doctest to pass. For example,

julia> f(x) = try
           sqrt(x)
       catch y
           bt = catch_backtrace()
           showerror(STDOUT, y, bt)
           println()
       end;

julia> f(-1)
DomainError:
 in f(::Int64) at ./none:2
 in eval(::Module, ::Any) at ./boot.jl:236
...

and

julia> f(x) = try
           sqrt(x)
       catch y
           bt = catch_backtrace()
           showerror(STDOUT, y, bt)
       end;

julia> f(-1); println()
DomainError:
 in f(::Int64) at ./none:2
 in eval(::Module, ::Any) at ./boot.jl:236
...

pass, but they fail when I remove println(). Do you think either of the above is an adequate solution?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's strange. what does running the doctests say for "got" without the println ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buffering issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tkelman Excluding the system dependent info from "got", I see

File "stdlib/base.rst", line 1234, in default
Failed example:
    f(-1)
Expected:
    DomainError:
     in f(::Int64) at ./none:2
     in eval(::Module, ::Any) at ./boot.jl:236
    ...
Got:
    DomainError:
     in f(::Int64) at ./none:2
     in eval(::Module, ::Any) at ./boot.jl:236

I haven't been able to identify additional or missing whitespace as the problem.

@yuyichao Sorry, what do you mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's

Excluding the system dependent info from "got", I see

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was referring to output that included local paths. The full output is:

Got:
    DomainError:
     in f(::Int64) at ./none:2
     in eval(::Module, ::Any) at ./boot.jl:236
     in eval(::Module, ::Any) at /Users/jane/Applications/julia/usr/lib/julia/sys.dylib:?
     in eval_user_input(::Any, ::Bool) at ./client.jl:123
     in eval_user_input(::Any, ::Bool) at /Users/jane/Applications/julia/usr/lib/julia/sys.dylib:?
     in eval(::Module, ::Any) at ./boot.jl:236
     in eval(::Module, ::Any) at /Users/jane/Applications/julia/usr/lib/julia/sys.dylib:?
     in eval_user_input(::Any, ::Bool) at ./client.jl:123
     in eval_user_input(::Any, ::Bool) at /Users/jane/Applications/julia/usr/lib/julia/sys.dylib:?
     in _start() at ./client.jl:372
     in _start() at /Users/jane/Applications/julia/usr/lib/julia/sys.dylib:?**

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should be included since it at least means what tony said won't work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the doctest system specifically removes those, but I'm not sure where that happens

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should be included since it at least means what tony said won't work.

This doctest fails even when I include the full output listed for "got".

After formatting this doctest several different ways, the only solutions I found involved adding calls to println(). I suspect there may be a bug in the way the doctest system is parsing this code block, but I did not find anything suspicious after going through what I could find of the documentation code. If there aren't other suggestions for things I might try, then I think I will move on to other fronts. Please let me know if you'd like me to convert this doctest to a regular code block or make some other modification. Thanks! :)

in eval(::Module, ::Any) at ./boot.jl:236
...
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the output of calling say f(-1) is repeatable, is it worth doctesting?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output seems system dependent. I get

DomainError: in f(::Int64) at ./REPL[49]:2 in eval(::Module, ::Any) at ./boot.jl:238 in eval(::Module, ::Any) at /Users/jane/Applications/julia/usr/lib/julia/sys.dylib:? in eval_user_input(::Any, ::Base.REPL.REPLBackend) at ./REPL.jl:66 in macro expansion at ./REPL.jl:97 [inlined] in (::Base.REPL.##3#4{Base.REPL.REPLBackend})() at ./event.jl:65

Is there a work-around/way to exclude local paths so I can include a doctest?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think those eval backtrace lines always get filtered out of doctest outputs so don't need to be included (they also might be different if run from repl vs a script)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the doctest without eval backtrace lines!

"""
catch_backtrace() = ccall(:jl_get_backtrace, Array{Ptr{Void},1}, ())

## keyword arg lowering generates calls to this ##
kwerr(kw, args...) = throw(MethodError(typeof(args[1]).name.mt.kwsorter, (kw,args...)))

## system error handling ##
"""
systemerror(sysfunc, iftrue)

Raises a `SystemError` for `errno` with the descriptive string `sysfunc` if `iftrue` is `true`.
"""
systemerror(p, b::Bool; extrainfo=nothing) = b ? throw(Main.Base.SystemError(string(p), Libc.errno(), extrainfo)) : nothing

## assertion functions and macros ##

"""
assert(cond)

Throw an [`AssertionError`](:obj:`AssertionError`) if `cond` is `false`.
Also available as the macro `@assert expr`.
"""
assert(x) = x ? nothing : throw(Main.Base.AssertionError())

"""
@assert cond [text]

Throw an `AssertionError` if `cond` is `false`. Preferred syntax for writing assertions.
Message `text` is optionally displayed upon assertion failure.
"""
macro assert(ex, msgs...)
msg = isempty(msgs) ? ex : msgs[1]
if !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
Expand Down
2 changes: 1 addition & 1 deletion base/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ Body:

julia> @inferred f(1,2,3)
ERROR: return type Int64 does not match inferred return type Union{Float64,Int64}
in error(::String) at ./error.jl:21
in error(::String) at ./error.jl:26
...

julia> @inferred max(1,2)
Expand Down
2 changes: 1 addition & 1 deletion doc/manual/control-flow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ execution:

julia> error("Hi"); 1+1
ERROR: Hi
in error(::String) at ./error.jl:21
in error(::String) at ./error.jl:26
...


Expand Down
19 changes: 18 additions & 1 deletion doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,24 @@ Errors

.. Docstring generated from Julia source

Get the backtrace of the current exception, for use within ``catch`` blocks.
Get the backtrace of the current exception, for use within ``catch`` blocks. The backtrace is represented as an ``Array{Ptr{Void}}`` of addresses, so :func:`showerror` may be helpful for displaying the backtrace in a human-readable format.

**Example**

.. doctest::

julia> f(x) = try
sqrt(x)
catch y
bt = catch_backtrace()
showerror(STDOUT, y, bt)
end;

julia> f(-1)
DomainError:
in f(::Int64) at ./REPL[24]:2
in eval(::Module, ::Any) at ./boot.jl:236
...

.. function:: assert(cond)

Expand Down
2 changes: 1 addition & 1 deletion doc/stdlib/c.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@

.. Docstring generated from Julia source

Raises a ``SystemError`` for ``errno`` with the descriptive string ``sysfunc`` if ``iftrue`` is ``true``
Raises a ``SystemError`` for ``errno`` with the descriptive string ``sysfunc`` if ``iftrue`` is ``true``\ .

.. data:: Ptr{T}

Expand Down
2 changes: 1 addition & 1 deletion doc/stdlib/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ Mathematical Operators

.. Docstring generated from Julia source

Equivalent to ``!is(x, y)``\ .
Equivalent to ``!(x === y)``\ .

.. _<:
.. function:: <(x, y)
Expand Down
2 changes: 1 addition & 1 deletion doc/stdlib/test.rst
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ writing new tests.

julia> @inferred f(1,2,3)
ERROR: return type Int64 does not match inferred return type Union{Float64,Int64}
in error(::String) at ./error.jl:21
in error(::String) at ./error.jl:26
...

julia> @inferred max(1,2)
Expand Down