diff --git a/base/base.jl b/base/base.jl index ba6105d8a9166..18cdf4e4d8f39 100644 --- a/base/base.jl +++ b/base/base.jl @@ -34,12 +34,6 @@ type KeyError <: Exception key end -type LoadError <: Exception - file::AbstractString - line::Int - error -end - type MethodError <: Exception f args @@ -59,6 +53,21 @@ type AssertionError <: Exception AssertionError(msg) = new(msg) end +#Generic wrapping of arbitrary exceptions +#Subtypes should put the exception in an 'error' field +abstract WrappedException <: Exception + +type LoadError <: WrappedException + file::AbstractString + line::Int + error +end + +type InitError <: WrappedException + mod::Symbol + error +end + ccall(:jl_get_system_hooks, Void, ()) diff --git a/base/docs/helpdb.jl b/base/docs/helpdb.jl index 23de1416594b3..7b2e24b48134d 100644 --- a/base/docs/helpdb.jl +++ b/base/docs/helpdb.jl @@ -13646,6 +13646,16 @@ An error occurred while `including`, `requiring`, or `using` a file. The error s """ LoadError +doc""" +```rst +:: + InitError(mod::Symbol, error) + +An error occurred when running a module's `__init__` function. The actual error thrown is available in the `.error` field. +``` +""" +InitError + doc""" ```rst :: diff --git a/base/exports.jl b/base/exports.jl index cf3f19fb1568d..fb91694411578 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -164,6 +164,7 @@ export InvalidStateException, KeyError, LoadError, + InitError, MethodError, NullException, ParseError, diff --git a/base/loading.jl b/base/loading.jl index 6ebed3a36fe24..1a98ad70084fb 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -145,7 +145,7 @@ function show(io::IO, ex::PrecompilableError) end end precompilableerror(ex::PrecompilableError, c) = ex.isprecompilable == c -precompilableerror(ex::LoadError, c) = precompilableerror(ex.error, c) +precompilableerror(ex::WrappedException, c) = precompilableerror(ex.error, c) precompilableerror(ex, c) = false # put at the top of a file to force it to be precompiled (true), or diff --git a/base/replutil.jl b/base/replutil.jl index cf17842432862..7ea18fdc20531 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -93,6 +93,13 @@ function showerror(io::IO, ex::LoadError, bt; backtrace=true) end showerror(io::IO, ex::LoadError) = showerror(io, ex, []) +function showerror(io::IO, ex::InitError, bt; backtrace=true) + print(io, "InitError: ") + showerror(io, ex.error, bt, backtrace=backtrace) + print(io, "\nduring initialization of module $(ex.mod)") +end +showerror(io::IO, ex::InitError) = showerror(io, ex, []) + function showerror(io::IO, ex::DomainError, bt; backtrace=true) print(io, "DomainError:") for b in bt diff --git a/doc/manual/control-flow.rst b/doc/manual/control-flow.rst index e425f4f69568d..d54c409fc9967 100644 --- a/doc/manual/control-flow.rst +++ b/doc/manual/control-flow.rst @@ -619,6 +619,8 @@ built-in :exc:`Exception`\ s listed below all interrupt the normal flow of contr +------------------------------+ | :exc:`InexactError` | +------------------------------+ +| :exc:`InitError` | ++------------------------------+ | :exc:`InterruptException` | +------------------------------+ | :exc:`InvalidStateException` | diff --git a/src/alloc.c b/src/alloc.c index c6d57c5953d4e..c871578daa727 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -55,6 +55,7 @@ jl_datatype_t *jl_argumenterror_type; jl_datatype_t *jl_typeerror_type; jl_datatype_t *jl_methoderror_type; jl_datatype_t *jl_loaderror_type; +jl_datatype_t *jl_initerror_type; jl_datatype_t *jl_undefvarerror_type; jl_datatype_t *jl_ref_type; jl_datatype_t *jl_pointer_type; diff --git a/src/init.c b/src/init.c index 2e643a7c143df..86137a7d6caef 100644 --- a/src/init.c +++ b/src/init.c @@ -734,6 +734,7 @@ DLLEXPORT void jl_get_system_hooks(void) jl_typeerror_type = (jl_datatype_t*)basemod("TypeError"); jl_methoderror_type = (jl_datatype_t*)basemod("MethodError"); jl_loaderror_type = (jl_datatype_t*)basemod("LoadError"); + jl_initerror_type = (jl_datatype_t*)basemod("InitError"); jl_complex_type = (jl_datatype_t*)basemod("Complex"); } diff --git a/src/julia.h b/src/julia.h index 90867328d1562..0812e44ae3587 100644 --- a/src/julia.h +++ b/src/julia.h @@ -393,6 +393,7 @@ extern DLLEXPORT jl_datatype_t *jl_utf8_string_type; extern DLLEXPORT jl_datatype_t *jl_errorexception_type; extern DLLEXPORT jl_datatype_t *jl_argumenterror_type; extern DLLEXPORT jl_datatype_t *jl_loaderror_type; +extern DLLEXPORT jl_datatype_t *jl_initerror_type; extern DLLEXPORT jl_datatype_t *jl_typeerror_type; extern DLLEXPORT jl_datatype_t *jl_methoderror_type; extern DLLEXPORT jl_datatype_t *jl_undefvarerror_type; diff --git a/src/module.c b/src/module.c index 2e71e043a3796..ee7261fe99b2d 100644 --- a/src/module.c +++ b/src/module.c @@ -542,9 +542,14 @@ void jl_module_run_initializer(jl_module_t *m) jl_apply(f, NULL, 0); } JL_CATCH { - jl_printf(JL_STDERR, "WARNING: error initializing module %s:\n", m->name->name); - jl_static_show(JL_STDERR, jl_exception_in_transit); - jl_printf(JL_STDERR, "\n"); + if (jl_initerror_type == NULL) { + jl_rethrow(); + } + else { + jl_rethrow_other(jl_new_struct(jl_initerror_type, m->name, + jl_exception_in_transit)); + jl_printf(JL_STDERR, "\n"); + } } } diff --git a/src/toplevel.c b/src/toplevel.c index 44bdd83092ac1..afe8297cfafed 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -141,6 +141,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) jl_typeerror_type = NULL; jl_methoderror_type = NULL; jl_loaderror_type = NULL; + jl_initerror_type = NULL; jl_current_task->tls = jl_nothing; // may contain an entry for :SOURCE_FILE that is not valid in the new base } // export all modules from Main @@ -205,12 +206,18 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) arraylist_push(&module_stack, newm); if (outermost == NULL || jl_current_module == jl_main_module) { - size_t i, l=module_stack.len; - for(i = stackidx; i < l; i++) { - jl_module_load_time_initialize((jl_module_t*)module_stack.items[i]); + JL_TRY { + size_t i, l=module_stack.len; + for(i = stackidx; i < l; i++) { + jl_module_load_time_initialize((jl_module_t*)module_stack.items[i]); + } + assert(module_stack.len == l); + module_stack.len = stackidx; + } + JL_CATCH { + module_stack.len = stackidx; + jl_rethrow(); } - assert(module_stack.len == l); - module_stack.len = stackidx; } return (jl_value_t*)newm; @@ -585,8 +592,13 @@ jl_value_t *jl_parse_eval_all(const char *fname, size_t len) jl_rethrow(); } else { - jl_rethrow_other(jl_new_struct(jl_loaderror_type, fn, ln, - jl_exception_in_transit)); + if(jl_typeis(jl_exception_in_transit, jl_initerror_type)) { + jl_rethrow(); + } + else { + jl_rethrow_other(jl_new_struct(jl_loaderror_type, fn, ln, + jl_exception_in_transit)); + } } } jl_stop_parsing(); diff --git a/test/core.jl b/test/core.jl index 94e4ad40f08c2..620c109a1407f 100644 --- a/test/core.jl +++ b/test/core.jl @@ -672,6 +672,14 @@ end @test names(Module(:anonymous), true, true) != [:anonymous] @test names(Module(:anonymous, false), true, true) == [:anonymous] +# exception from __init__() +@test_throws InitError include_string( + """ + module TestInitError + __init__() = error() + end + """) + # issue #7307 function test7307(a, ret) try