diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 875e1997b515c..69904140fd357 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1047,9 +1047,10 @@ the order that the first of each set of equivalent elements originally appears. If `dim` is specified, returns unique regions of the array `itr` along `dim`. """ @generated function unique{T,N}(A::AbstractArray{T,N}, dim::Int) + inds = inds -> zeros(UInt, inds) quote 1 <= dim <= $N || return copy(A) - hashes = similar(inds->zeros(UInt, inds), indices(A, dim)) + hashes = similar($inds, indices(A, dim)) # Compute hash for each row k = 0 diff --git a/src/alloc.c b/src/alloc.c index 61066a8a65809..ee195fd1c508a 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -485,10 +485,16 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_code_info_t *func = NULL; JL_GC_PUSH4(&ex, &linenum, &sparam_vals, &func); jl_ptls_t ptls = jl_get_ptls_states(); + int last_lineno = jl_lineno; int last_in = ptls->in_pure_callback; + jl_module_t *last_m = ptls->current_module; + jl_module_t *task_last_m = ptls->current_task->current_module; assert(jl_svec_len(linfo->def->sparam_syms) == jl_svec_len(sparam_vals)); JL_TRY { ptls->in_pure_callback = 1; + // need to eval macros in the right module + ptls->current_task->current_module = ptls->current_module = linfo->def->module; + ex = jl_exprn(lambda_sym, 2); int nargs = linfo->def->nargs; @@ -522,18 +528,24 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) ex = newast; } - // need to eval macros in the right module, but not give a warning for the `eval` call unless that results in a call to `eval` - func = (jl_code_info_t*)jl_toplevel_eval_in_warn(linfo->def->module, (jl_value_t*)ex, 1); - assert(jl_is_code_info(func)); + func = (jl_code_info_t*)jl_expand((jl_value_t*)ex); + if (!jl_is_code_info(func)) + jl_error("generated function body is not pure. this likely means it contains a closure or comprehension."); jl_array_t *stmts = (jl_array_t*)func->code; for (i = 0, l = jl_array_len(stmts); i < l; i++) { jl_array_ptr_set(stmts, i, jl_resolve_globals(jl_array_ptr_ref(stmts, i), linfo->def->module)); } ptls->in_pure_callback = last_in; + jl_lineno = last_lineno; + ptls->current_module = last_m; + ptls->current_task->current_module = task_last_m; } JL_CATCH { ptls->in_pure_callback = last_in; + jl_lineno = last_lineno; + ptls->current_module = last_m; + ptls->current_task->current_module = task_last_m; jl_rethrow(); } JL_GC_POP(); diff --git a/src/builtins.c b/src/builtins.c index ab42d879286fc..248b07cf07c89 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -552,51 +552,36 @@ JL_CALLABLE(jl_f__apply) // eval ----------------------------------------------------------------------- JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex) -{ - return jl_toplevel_eval_in_warn(m, ex, 0); -} - -jl_value_t *jl_toplevel_eval_in_warn(jl_module_t *m, jl_value_t *ex, int delay_warn) { jl_ptls_t ptls = jl_get_ptls_states(); - static int jl_warn_on_eval = 0; - int last_delay_warn = jl_warn_on_eval; if (m == NULL) m = jl_main_module; if (jl_is_symbol(ex)) return jl_eval_global_var(m, (jl_sym_t*)ex); - jl_value_t *v=NULL; + if (ptls->in_pure_callback) + jl_error("eval cannot be used in a generated function"); + jl_value_t *v = NULL; int last_lineno = jl_lineno; jl_module_t *last_m = ptls->current_module; jl_module_t *task_last_m = ptls->current_task->current_module; - if (!delay_warn && jl_options.incremental && jl_generating_output()) { + if (jl_options.incremental && jl_generating_output()) { if (m != last_m) { jl_printf(JL_STDERR, "WARNING: eval from module %s to %s: \n", jl_symbol_name(m->name), jl_symbol_name(last_m->name)); jl_static_show(JL_STDERR, ex); jl_printf(JL_STDERR, "\n ** incremental compilation may be broken for this module **\n\n"); } - else if (jl_warn_on_eval) { - jl_printf(JL_STDERR, "WARNING: eval from staged function in module %s: \n", jl_symbol_name(m->name)); - jl_static_show(JL_STDERR, ex); - jl_printf(JL_STDERR, "\n ** incremental compilation may be broken for these modules **\n\n"); - } } - if (ptls->in_pure_callback && !delay_warn) - jl_error("eval cannot be used in a generated function"); JL_TRY { - jl_warn_on_eval = delay_warn && (jl_warn_on_eval || m != last_m); // compute whether a warning was suppressed ptls->current_task->current_module = ptls->current_module = m; v = jl_toplevel_eval(ex); } JL_CATCH { - jl_warn_on_eval = last_delay_warn; jl_lineno = last_lineno; ptls->current_module = last_m; ptls->current_task->current_module = task_last_m; jl_rethrow(); } - jl_warn_on_eval = last_delay_warn; jl_lineno = last_lineno; ptls->current_module = last_m; ptls->current_task->current_module = task_last_m; diff --git a/src/julia_internal.h b/src/julia_internal.h index de3e6fd8b8c20..42f495dfad49c 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -324,8 +324,6 @@ jl_function_t *jl_module_call_func(jl_module_t *m); int jl_is_submodule(jl_module_t *child, jl_module_t *parent); jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded); -jl_value_t *jl_toplevel_eval_in_warn(jl_module_t *m, jl_value_t *ex, - int delay_warn); jl_code_info_t *jl_wrap_expr(jl_value_t *expr); jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e); diff --git a/test/core.jl b/test/core.jl index d69a5b8faa534..a52ed478ba2bc 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4578,3 +4578,12 @@ end fVararg(x) = Vararg{x} gVararg(a::fVararg(Int)) = length(a) @test gVararg(1,2,3,4,5) == 5 + +# issue #18577 +@generated f18577() = quote ()->1 end +@test try + f18577() + false +catch e + (e::ErrorException).msg +end == "generated function body is not pure. this likely means it contains a closure or comprehension." diff --git a/test/staged.jl b/test/staged.jl index 621d866711738..d806300ccd5b9 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -156,7 +156,7 @@ end @generated function _g_f_with_inner(x) :(y->y) end -@test (_g_f_with_inner(1))(8) == 8 +@test_throws ErrorException _g_f_with_inner(1) # @generated functions errors global gf_err_ref = Ref{Int}()