Skip to content

Commit

Permalink
Merge pull request JuliaLang#12576 from phobon/init_exceptions
Browse files Browse the repository at this point in the history
Remove exception catching for __init__ functions, add InitError exception type
  • Loading branch information
jakebolewski committed Aug 18, 2015
2 parents b24590e + 5898d2e commit 92deb0a
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 17 deletions.
21 changes: 15 additions & 6 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ type KeyError <: Exception
key
end

type LoadError <: Exception
file::AbstractString
line::Int
error
end

type MethodError <: Exception
f
args
Expand All @@ -52,6 +46,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, ())


Expand Down
10 changes: 10 additions & 0 deletions base/docs/helpdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13646,6 +13646,16 @@ An error occurred while ``include``\ ing, ``require``\ ing, or ``using`` a file.
"""
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
::
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export
InvalidStateException,
KeyError,
LoadError,
InitError,
MethodError,
NullException,
ParseError,
Expand Down
2 changes: 1 addition & 1 deletion base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

# Call __precompile__ at the top of a file to force it to be precompiled (true), or
Expand Down
7 changes: 7 additions & 0 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions doc/manual/control-flow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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` |
Expand Down
1 change: 1 addition & 0 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ DLLEXPORT void jl_get_system_hooks(void)
jl_argumenterror_type = (jl_datatype_t*)basemod("ArgumentError");
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");
}

Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 8 additions & 3 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
}

Expand Down
26 changes: 19 additions & 7 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex)
jl_argumenterror_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
Expand Down Expand Up @@ -204,12 +205,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;
Expand Down Expand Up @@ -584,8 +591,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();
Expand Down
8 changes: 8 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 92deb0a

Please sign in to comment.