@@ -107,6 +107,12 @@ jl_array_t *jl_get_loaded_modules(void)
107107 return NULL ;
108108}
109109
110+ static int jl_is__toplevel__mod (jl_module_t * mod )
111+ {
112+ return jl_base_module &&
113+ (jl_value_t * )mod == jl_get_global (jl_base_module , jl_symbol ("__toplevel__" ));
114+ }
115+
110116// TODO: add locks around global state mutation operations
111117jl_value_t * jl_eval_module_expr (jl_module_t * parent_module , jl_expr_t * ex )
112118{
@@ -133,8 +139,7 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex)
133139
134140 // copy parent environment info into submodule
135141 newm -> uuid = parent_module -> uuid ;
136- if (jl_base_module &&
137- (jl_value_t * )parent_module == jl_get_global (jl_base_module , jl_symbol ("__toplevel__" ))) {
142+ if (jl_is__toplevel__mod (parent_module )) {
138143 newm -> parent = newm ;
139144 jl_register_root_module (newm );
140145 }
@@ -827,25 +832,33 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_module_t *m, jl_value_t *v)
827832 return jl_toplevel_eval_flex (m , v , 1 , 0 );
828833}
829834
835+ // Check module `m` is open for `eval/include`, or throw an error.
836+ void jl_check_open_for (jl_module_t * m , const char * funcname )
837+ {
838+ if (jl_options .incremental && jl_generating_output ()) {
839+ if (!ptrhash_has (& jl_current_modules , (void * )m ) && !jl_is__toplevel__mod (m )) {
840+ if (m != jl_main_module ) { // TODO: this was grand-fathered in
841+ const char * name = jl_symbol_name (m -> name );
842+ jl_errorf ("Evaluation into the closed module `%s` breaks incremental compilation "
843+ "because the side effects will not be permanent. "
844+ "This is likely due to some other module mutating `%s` with `%s` during "
845+ "precompilation - don't do this." , name , name , funcname );
846+ }
847+ }
848+ }
849+ }
850+
830851JL_DLLEXPORT jl_value_t * jl_toplevel_eval_in (jl_module_t * m , jl_value_t * ex )
831852{
832853 jl_ptls_t ptls = jl_get_ptls_states ();
833854 if (ptls -> in_pure_callback )
834855 jl_error ("eval cannot be used in a generated function" );
856+ jl_check_open_for (m , "eval" );
835857 jl_value_t * v = NULL ;
836858 int last_lineno = jl_lineno ;
837859 const char * last_filename = jl_filename ;
838860 jl_lineno = 1 ;
839861 jl_filename = "none" ;
840- if (jl_options .incremental && jl_generating_output ()) {
841- if (!ptrhash_has (& jl_current_modules , (void * )m )) {
842- if (m != jl_main_module ) { // TODO: this was grand-fathered in
843- jl_printf (JL_STDERR , "WARNING: eval into closed module %s:\n" , jl_symbol_name (m -> name ));
844- jl_static_show (JL_STDERR , ex );
845- jl_printf (JL_STDERR , "\n ** incremental compilation may be fatally broken for this module **\n\n" );
846- }
847- }
848- }
849862 JL_TRY {
850863 v = jl_toplevel_eval (m , ex );
851864 }
0 commit comments