diff --git a/base/boot.jl b/base/boot.jl index 056b14fa5d0ac..2dc19528e178e 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -413,6 +413,8 @@ struct InitError <: WrappedException error end +struct PrecompilableError <: Exception end + String(s::String) = s # no constructor yet const Cvoid = Nothing diff --git a/base/loading.jl b/base/loading.jl index 9a3a922298f1e..95b83e84aad15 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1745,7 +1745,7 @@ function include_dependency(path::AbstractString) end # we throw PrecompilableError when a module doesn't want to be precompiled -struct PrecompilableError <: Exception end +import Core: PrecompilableError function show(io::IO, ex::PrecompilableError) print(io, "Error when precompiling module, potentially caused by a __precompile__(false) declaration in the module.") end diff --git a/src/gf.c b/src/gf.c index fffeb928a1889..5013706030777 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1572,8 +1572,10 @@ static void method_overwrite(jl_typemap_entry_t *newentry, jl_method_t *oldvalue jl_printf(s, ".\n"); jl_uv_flush(s); } - if (jl_generating_output()) - jl_error("Method overwriting is not permitted during Module precompile."); + if (jl_generating_output()) { + jl_printf(JL_STDERR, "ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation.\n"); + jl_throw(jl_precompilable_error); + } } static void update_max_args(jl_methtable_t *mt, jl_value_t *type) diff --git a/src/jl_exported_data.inc b/src/jl_exported_data.inc index b6b9774c1538e..1a843c71f0e1e 100644 --- a/src/jl_exported_data.inc +++ b/src/jl_exported_data.inc @@ -145,6 +145,7 @@ XX(jl_weakref_type) \ XX(jl_libdl_module) \ XX(jl_libdl_dlopen_func) \ + XX(jl_precompilable_error) \ // Data symbols that are defined inside the public libjulia #define JL_EXPORTED_DATA_SYMBOLS(XX) \ diff --git a/src/jltypes.c b/src/jltypes.c index c7c7d213c5317..a30d746bbb320 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3510,6 +3510,7 @@ void post_boot_hooks(void) jl_loaderror_type = (jl_datatype_t*)core("LoadError"); jl_initerror_type = (jl_datatype_t*)core("InitError"); jl_missingcodeerror_type = (jl_datatype_t*)core("MissingCodeError"); + jl_precompilable_error = jl_new_struct_uninit((jl_datatype_t*)core("PrecompilableError")); jl_pair_type = core("Pair"); jl_kwcall_func = core("kwcall"); jl_kwcall_mt = ((jl_datatype_t*)jl_typeof(jl_kwcall_func))->name->mt; diff --git a/src/julia.h b/src/julia.h index 5198bcab5a2bd..d728458f50180 100644 --- a/src/julia.h +++ b/src/julia.h @@ -837,6 +837,7 @@ extern JL_DLLIMPORT jl_value_t *jl_readonlymemory_exception JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_value_t *jl_diverror_exception JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_value_t *jl_undefref_exception JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_value_t *jl_interrupt_exception JL_GLOBALLY_ROOTED; +extern JL_DLLIMPORT jl_value_t *jl_precompilable_error JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_datatype_t *jl_boundserror_type JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_value_t *jl_an_empty_vec_any JL_GLOBALLY_ROOTED; extern JL_DLLIMPORT jl_value_t *jl_an_empty_memory_any JL_GLOBALLY_ROOTED; diff --git a/src/staticdata.c b/src/staticdata.c index 42a5fdb63b63e..52a354b4933d7 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -98,7 +98,7 @@ extern "C" { // TODO: put WeakRefs on the weak_refs list during deserialization // TODO: handle finalizers -#define NUM_TAGS 174 +#define NUM_TAGS 175 // An array of references that need to be restored from the sysimg // This is a manually constructed dual of the gvars array, which would be produced by codegen for Julia code, for C. @@ -237,6 +237,7 @@ jl_value_t **const*const get_tags(void) { INSERT_TAG(jl_readonlymemory_exception); INSERT_TAG(jl_atomicerror_type); INSERT_TAG(jl_missingcodeerror_type); + INSERT_TAG(jl_precompilable_error); // other special values INSERT_TAG(jl_emptysvec); diff --git a/test/precompile.jl b/test/precompile.jl index 051b750fa7fdf..1ac3999947736 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -571,6 +571,16 @@ precompile_test_harness(false) do dir @test Base.compilecache(Base.PkgId("Baz")) == Base.PrecompilableError() # due to __precompile__(false) + OverwriteMethodError_file = joinpath(dir, "OverwriteMethodError.jl") + write(OverwriteMethodError_file, + """ + module OverwriteMethodError + Base.:(+)(x::Bool, y::Bool) = false + end + """) + + @test Base.compilecache(Base.PkgId("OverwriteMethodError")) == Base.PrecompilableError() # due to piracy + UseBaz_file = joinpath(dir, "UseBaz.jl") write(UseBaz_file, """