From 3cd52ef1de5aba3838a0024c9296ecb2633f2b74 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Sat, 14 Sep 2024 14:40:10 -0500 Subject: [PATCH 01/16] Add compat entry for `Base.donotdelete` (#55773) (cherry picked from commit 346f38bceabf3dab1d3912fe822a663735c91d4a) --- base/docs/basedocs.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index b45560287edd0..c6c59f496ea88 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -3299,6 +3299,9 @@ unused and delete the entire benchmark code). !!! compat "Julia 1.8" This method was added in Julia 1.8. +!!! compat "Julia 1.8" + This method was added in Julia 1.8. + # Examples ```julia From 07fc290ba74d2702d787e0fe9715ca6756923e71 Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Fri, 11 Oct 2024 23:16:26 +0800 Subject: [PATCH 02/16] Subtype: some performance tuning. (#56007) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main motivation of this PR is to fix #55807. dc689fe8700f70f4a4e2dbaaf270f26b87e79e04 tries to remove the slow `may_contain_union_decision` check by re-organizing the code path. Now the fast path has been removed and most of its optimization has been integrated into the preserved slow path. Since the slow path stores all inner ∃ decisions on the outer most R stack, there might be overflow risk. aee69a41441b4306ba3ee5e845bc96cb45d9b327 should fix that concern. The reported MWE now becomes ```julia 0.000002 seconds 0.000040 seconds (105 allocations: 4.828 KiB, 52.00% compilation time) 0.000023 seconds (105 allocations: 4.828 KiB, 49.36% compilation time) 0.000026 seconds (105 allocations: 4.828 KiB, 50.38% compilation time) 0.000027 seconds (105 allocations: 4.828 KiB, 54.95% compilation time) 0.000019 seconds (106 allocations: 4.922 KiB, 49.73% compilation time) 0.000024 seconds (105 allocations: 4.828 KiB, 52.24% compilation time) ``` Local bench also shows that 72855cd slightly accelerates `OmniPackage.jl`'s loading ```julia julia> @time using OmniPackage # v1.11rc4 20.525278 seconds (25.36 M allocations: 1.606 GiB, 8.48% gc time, 12.89% compilation time: 77% of which was recompilation) # v1.11rc4+aee69a4+72855cd 19.527871 seconds (24.92 M allocations: 1.593 GiB, 8.88% gc time, 15.13% compilation time: 82% of which was recompilation) ``` (cherry picked from commit f3a36d74eeb1f8c6439affcc33e2a304550dc217) --- src/subtype.c | 298 +++++++++++++++++++++++++++++--------------------- 1 file changed, 173 insertions(+), 125 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index f183cc9da21a9..5b326237e0dd2 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -39,20 +39,24 @@ extern "C" { // Union type decision points are discovered while the algorithm works. // If a new Union decision is encountered, the `more` flag is set to tell // the forall/exists loop to grow the stack. -// TODO: the stack probably needs to be artificially large because of some -// deeper problem (see #21191) and could be shrunk once that is fixed + +typedef struct jl_bits_stack_t { + uint32_t data[16]; + struct jl_bits_stack_t *next; +} jl_bits_stack_t; + typedef struct { int16_t depth; int16_t more; int16_t used; - uint32_t stack[100]; // stack of bits represented as a bit vector + jl_bits_stack_t stack; } jl_unionstate_t; typedef struct { int16_t depth; int16_t more; int16_t used; - void *stack; + uint8_t *stack; } jl_saved_unionstate_t; // Linked list storing the type variable environment. A new jl_varbinding_t @@ -120,37 +124,111 @@ static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) JL_GLOBALLY_ROOTED J } #endif +// union-stack tools + static int statestack_get(jl_unionstate_t *st, int i) JL_NOTSAFEPOINT { - assert(i >= 0 && i < sizeof(st->stack) * 8); + assert(i >= 0 && i <= 32767); // limited by the depth bit. // get the `i`th bit in an array of 32-bit words - return (st->stack[i>>5] & (1u<<(i&31))) != 0; + jl_bits_stack_t *stack = &st->stack; + while (i >= sizeof(stack->data) * 8) { + // We should have set this bit. + assert(stack->next); + stack = stack->next; + i -= sizeof(stack->data) * 8; + } + return (stack->data[i>>5] & (1u<<(i&31))) != 0; } static void statestack_set(jl_unionstate_t *st, int i, int val) JL_NOTSAFEPOINT { - assert(i >= 0 && i < sizeof(st->stack) * 8); + assert(i >= 0 && i <= 32767); // limited by the depth bit. + jl_bits_stack_t *stack = &st->stack; + while (i >= sizeof(stack->data) * 8) { + if (__unlikely(stack->next == NULL)) { + stack->next = (jl_bits_stack_t *)malloc(sizeof(jl_bits_stack_t)); + stack->next->next = NULL; + } + stack = stack->next; + i -= sizeof(stack->data) * 8; + } if (val) - st->stack[i>>5] |= (1u<<(i&31)); + stack->data[i>>5] |= (1u<<(i&31)); else - st->stack[i>>5] &= ~(1u<<(i&31)); + stack->data[i>>5] &= ~(1u<<(i&31)); +} + +#define has_next_union_state(e, R) ((((R) ? &(e)->Runions : &(e)->Lunions)->more) != 0) + +static int next_union_state(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT +{ + jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; + if (state->more == 0) + return 0; + // reset `used` and let `pick_union_decision` clean the stack. + state->used = state->more; + statestack_set(state, state->used - 1, 1); + return 1; +} + +static int pick_union_decision(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT +{ + jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; + if (state->depth >= state->used) { + statestack_set(state, state->used, 0); + state->used++; + } + int ui = statestack_get(state, state->depth); + state->depth++; + if (ui == 0) + state->more = state->depth; // memorize that this was the deepest available choice + return ui; } -#define push_unionstate(saved, src) \ - do { \ - (saved)->depth = (src)->depth; \ - (saved)->more = (src)->more; \ - (saved)->used = (src)->used; \ - (saved)->stack = alloca(((src)->used+7)/8); \ - memcpy((saved)->stack, &(src)->stack, ((src)->used+7)/8); \ +static jl_value_t *pick_union_element(jl_value_t *u JL_PROPAGATES_ROOT, jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT +{ + do { + if (pick_union_decision(e, R)) + u = ((jl_uniontype_t*)u)->b; + else + u = ((jl_uniontype_t*)u)->a; + } while (jl_is_uniontype(u)); + return u; +} + +#define push_unionstate(saved, src) \ + do { \ + (saved)->depth = (src)->depth; \ + (saved)->more = (src)->more; \ + (saved)->used = (src)->used; \ + jl_bits_stack_t *srcstack = &(src)->stack; \ + int pushbits = ((saved)->used+7)/8; \ + (saved)->stack = (uint8_t *)alloca(pushbits); \ + for (int n = 0; n < pushbits; n += sizeof(srcstack->data)) { \ + assert(srcstack != NULL); \ + int rest = pushbits - n; \ + if (rest > sizeof(srcstack->data)) \ + rest = sizeof(srcstack->data); \ + memcpy(&(saved)->stack[n], &srcstack->data, rest); \ + srcstack = srcstack->next; \ + } \ } while (0); -#define pop_unionstate(dst, saved) \ - do { \ - (dst)->depth = (saved)->depth; \ - (dst)->more = (saved)->more; \ - (dst)->used = (saved)->used; \ - memcpy(&(dst)->stack, (saved)->stack, ((saved)->used+7)/8); \ +#define pop_unionstate(dst, saved) \ + do { \ + (dst)->depth = (saved)->depth; \ + (dst)->more = (saved)->more; \ + (dst)->used = (saved)->used; \ + jl_bits_stack_t *dststack = &(dst)->stack; \ + int popbits = ((saved)->used+7)/8; \ + for (int n = 0; n < popbits; n += sizeof(dststack->data)) { \ + assert(dststack != NULL); \ + int rest = popbits - n; \ + if (rest > sizeof(dststack->data)) \ + rest = sizeof(dststack->data); \ + memcpy(&dststack->data, &(saved)->stack[n], rest); \ + dststack = dststack->next; \ + } \ } while (0); static int current_env_length(jl_stenv_t *e) @@ -252,6 +330,18 @@ static void free_env(jl_savedenv_t *se) JL_NOTSAFEPOINT se->buf = NULL; } +static void free_stenv(jl_stenv_t *e) JL_NOTSAFEPOINT +{ + for (int R = 0; R < 2; R++) { + jl_bits_stack_t *temp = R ? e->Runions.stack.next : e->Lunions.stack.next; + while (temp != NULL) { + jl_bits_stack_t *next = temp->next; + free(temp); + temp = next; + } + } +} + static void restore_env(jl_stenv_t *e, jl_savedenv_t *se, int root) JL_NOTSAFEPOINT { jl_value_t **roots = NULL; @@ -574,44 +664,6 @@ static jl_value_t *simple_meet(jl_value_t *a, jl_value_t *b, int overesi) static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param); -#define has_next_union_state(e, R) ((((R) ? &(e)->Runions : &(e)->Lunions)->more) != 0) - -static int next_union_state(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT -{ - jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; - if (state->more == 0) - return 0; - // reset `used` and let `pick_union_decision` clean the stack. - state->used = state->more; - statestack_set(state, state->used - 1, 1); - return 1; -} - -static int pick_union_decision(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT -{ - jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; - if (state->depth >= state->used) { - statestack_set(state, state->used, 0); - state->used++; - } - int ui = statestack_get(state, state->depth); - state->depth++; - if (ui == 0) - state->more = state->depth; // memorize that this was the deepest available choice - return ui; -} - -static jl_value_t *pick_union_element(jl_value_t *u JL_PROPAGATES_ROOT, jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT -{ - do { - if (pick_union_decision(e, R)) - u = ((jl_uniontype_t*)u)->b; - else - u = ((jl_uniontype_t*)u)->a; - } while (jl_is_uniontype(u)); - return u; -} - static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int limit_slow); // subtype for variable bounds consistency check. needs its own forall/exists environment. @@ -1474,37 +1526,12 @@ static int is_definite_length_tuple_type(jl_value_t *x) return k == JL_VARARG_NONE || k == JL_VARARG_INT; } -static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int *count, int *noRmore); - -static int may_contain_union_decision(jl_value_t *x, jl_stenv_t *e, jl_typeenv_t *log) JL_NOTSAFEPOINT +static int is_exists_typevar(jl_value_t *x, jl_stenv_t *e) { - if (x == NULL || x == (jl_value_t*)jl_any_type || x == jl_bottom_type) - return 0; - if (jl_is_unionall(x)) - return may_contain_union_decision(((jl_unionall_t *)x)->body, e, log); - if (jl_is_datatype(x)) { - jl_datatype_t *xd = (jl_datatype_t *)x; - for (int i = 0; i < jl_nparams(xd); i++) { - jl_value_t *param = jl_tparam(xd, i); - if (jl_is_vararg(param)) - param = jl_unwrap_vararg(param); - if (may_contain_union_decision(param, e, log)) - return 1; - } - return 0; - } if (!jl_is_typevar(x)) - return jl_is_type(x); - jl_typeenv_t *t = log; - while (t != NULL) { - if (x == (jl_value_t *)t->var) - return 1; - t = t->prev; - } - jl_typeenv_t newlog = { (jl_tvar_t*)x, NULL, log }; - jl_varbinding_t *xb = lookup(e, (jl_tvar_t *)x); - return may_contain_union_decision(xb ? xb->lb : ((jl_tvar_t *)x)->lb, e, &newlog) || - may_contain_union_decision(xb ? xb->ub : ((jl_tvar_t *)x)->ub, e, &newlog); + return 0; + jl_varbinding_t *vb = lookup(e, (jl_tvar_t *)x); + return vb && vb->right; } static int has_exists_typevar(jl_value_t *x, jl_stenv_t *e) JL_NOTSAFEPOINT @@ -1535,31 +1562,9 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t int kindy = !jl_has_free_typevars(y); if (kindx && kindy) return jl_subtype(x, y); - if (may_contain_union_decision(y, e, NULL) && pick_union_decision(e, 1) == 0) { - jl_saved_unionstate_t oldRunions; push_unionstate(&oldRunions, &e->Runions); - e->Lunions.used = e->Runions.used = 0; - e->Lunions.depth = e->Runions.depth = 0; - e->Lunions.more = e->Runions.more = 0; - int count = 0, noRmore = 0; - sub = _forall_exists_subtype(x, y, e, param, &count, &noRmore); - pop_unionstate(&e->Runions, &oldRunions); - // We could skip the slow path safely if - // 1) `_∀_∃_subtype` has tested all cases - // 2) `_∀_∃_subtype` returns 1 && `x` and `y` contain no ∃ typevar - // Once `limit_slow == 1`, also skip it if - // 1) `_∀_∃_subtype` returns 0 - // 2) the left `Union` looks big - // TODO: `limit_slow` ignores complexity from inner `local_∀_exists_subtype`. - if (limit_slow == -1) - limit_slow = kindx || kindy; - int skip = noRmore || (limit_slow && (count > 3 || !sub)) || - (sub && (kindx || !has_exists_typevar(x, e)) && - (kindy || !has_exists_typevar(y, e))); - if (skip) - e->Runions.more = oldRmore; - } - else { - // slow path + int has_exists = (!kindx && has_exists_typevar(x, e)) || + (!kindy && has_exists_typevar(y, e)); + if (has_exists && (is_exists_typevar(x, e) != is_exists_typevar(y, e))) { e->Lunions.used = 0; while (1) { e->Lunions.more = 0; @@ -1568,7 +1573,51 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t if (!sub || !next_union_state(e, 0)) break; } + return sub; } + if (limit_slow == -1) + limit_slow = kindx || kindy; + jl_savedenv_t se; + save_env(e, &se, has_exists); + int count, limited = 0, ini_count = 0; + jl_saved_unionstate_t latestLunions = {0, 0, 0, NULL}; + while (1) { + count = ini_count; + if (ini_count == 0) + e->Lunions.used = 0; + else + pop_unionstate(&e->Lunions, &latestLunions); + while (1) { + e->Lunions.more = 0; + e->Lunions.depth = 0; + if (count < 4) count++; + sub = subtype(x, y, e, param); + if (limit_slow && count == 4) + limited = 1; + if (!sub || !next_union_state(e, 0)) + break; + if (limited || !has_exists || e->Runions.more == oldRmore) { + // re-save env and freeze the ∃decision for previous ∀Union + // Note: We could ignore the rest `∃Union` decisions if `x` and `y` + // contain no ∃ typevar, as they have no effect on env. + ini_count = count; + push_unionstate(&latestLunions, &e->Lunions); + re_save_env(e, &se, has_exists); + e->Runions.more = oldRmore; + } + } + if (sub || e->Runions.more == oldRmore) + break; + assert(e->Runions.more > oldRmore); + next_union_state(e, 1); + restore_env(e, &se, has_exists); // also restore Rdepth here + e->Runions.more = oldRmore; + } + if (!sub) + assert(e->Runions.more == oldRmore); + else if (limited || !has_exists) + e->Runions.more = oldRmore; + free_env(&se); return sub; } @@ -1680,7 +1729,7 @@ static int exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, jl_savede } } -static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int *count, int *noRmore) +static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) { // The depth recursion has the following shape, after simplification: // ∀₁ @@ -1692,12 +1741,8 @@ static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, i e->Lunions.used = 0; int sub; - if (count) *count = 0; - if (noRmore) *noRmore = 1; while (1) { sub = exists_subtype(x, y, e, &se, param); - if (count) *count = (*count < 4) ? *count + 1 : 4; - if (noRmore) *noRmore = *noRmore && e->Runions.more == 0; if (!sub || !next_union_state(e, 0)) break; re_save_env(e, &se, 1); @@ -1707,11 +1752,6 @@ static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, i return sub; } -static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) -{ - return _forall_exists_subtype(x, y, e, param, NULL, NULL); -} - static void init_stenv(jl_stenv_t *e, jl_value_t **env, int envsz) { e->vars = NULL; @@ -1731,6 +1771,8 @@ static void init_stenv(jl_stenv_t *e, jl_value_t **env, int envsz) e->Lunions.depth = 0; e->Runions.depth = 0; e->Lunions.more = 0; e->Runions.more = 0; e->Lunions.used = 0; e->Runions.used = 0; + e->Lunions.stack.next = NULL; + e->Runions.stack.next = NULL; } // subtyping entry points @@ -2160,6 +2202,7 @@ JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, } init_stenv(&e, env, envsz); int subtype = forall_exists_subtype(x, y, &e, 0); + free_stenv(&e); assert(obvious_subtype == 3 || obvious_subtype == subtype || jl_has_free_typevars(x) || jl_has_free_typevars(y)); #ifndef NDEBUG if (obvious_subtype == 0 || (obvious_subtype == 1 && envsz == 0)) @@ -2252,6 +2295,7 @@ JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) { init_stenv(&e, NULL, 0); int subtype = forall_exists_subtype(a, b, &e, 0); + free_stenv(&e); assert(subtype_ab == 3 || subtype_ab == subtype || jl_has_free_typevars(a) || jl_has_free_typevars(b)); #ifndef NDEBUG if (subtype_ab != 0 && subtype_ab != 1) // ensures that running in a debugger doesn't change the result @@ -2268,6 +2312,7 @@ JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) { init_stenv(&e, NULL, 0); int subtype = forall_exists_subtype(b, a, &e, 0); + free_stenv(&e); assert(subtype_ba == 3 || subtype_ba == subtype || jl_has_free_typevars(a) || jl_has_free_typevars(b)); #ifndef NDEBUG if (subtype_ba != 0 && subtype_ba != 1) // ensures that running in a debugger doesn't change the result @@ -4061,7 +4106,9 @@ static jl_value_t *intersect_types(jl_value_t *x, jl_value_t *y, int emptiness_o init_stenv(&e, NULL, 0); e.intersection = e.ignore_free = 1; e.emptiness_only = emptiness_only; - return intersect_all(x, y, &e); + jl_value_t *ans = intersect_all(x, y, &e); + free_stenv(&e); + return ans; } JL_DLLEXPORT jl_value_t *jl_intersect_types(jl_value_t *x, jl_value_t *y) @@ -4238,6 +4285,7 @@ jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t * memset(env, 0, szb*sizeof(void*)); e.envsz = szb; *ans = intersect_all(a, b, &e); + free_stenv(&e); if (*ans == jl_bottom_type) goto bot; // TODO: code dealing with method signatures is not able to handle unions, so if // `a` and `b` are both tuples, we need to be careful and may not return a union, From fcb138ba69af4f1e3ee8529840d814604b4bad10 Mon Sep 17 00:00:00 2001 From: Aravindh Krishnamoorthy Date: Mon, 28 Oct 2024 12:32:21 +0100 Subject: [PATCH 03/16] Fix `log_quasitriu` for internal scaling `s=0` (#56311) This PR is a potential fix for #54833. ## Description The function https://github.com/JuliaLang/julia/blob/2a06376c18afd7ec875335070743dcebcd85dee7/stdlib/LinearAlgebra/src/triangular.jl#L2220 computes $\boldsymbol{A}^{\dfrac{1}{2^s}} - \boldsymbol{I}$ for a real-valued $2\times 2$ matrix $\boldsymbol{A}$ using Algorithm 5.1 in [R1]. However, the algorithm in [R1] as well as the above function do not handle the case $s=0.$ This fix extends the function to compute $\boldsymbol{A}^{\dfrac{1}{2^s}} - \boldsymbol{I} \Bigg|_{s=0} = \boldsymbol{A} - \boldsymbol{I}.$ ## Checklist - [X] Fix code: `stdlib\LinearAlgebra\src\triangular.jl` in function `_sqrt_pow_diag_block_2x2!(A, A0, s)`. - [X] Add test case: `stdlib\LinearAlgebra\test\triangular.jl`. - [X] Update `NEWS.md`. - [X] Testing and self review. | Tag | Reference | | --- | --- | | [R1] | Al-Mohy, Awad H. and Higham, Nicholas J. "Improved Inverse Scaling and Squaring Algorithms for the Matrix Logarithm", 2011, url: https://eprints.maths.manchester.ac.uk/1687/1/paper11.pdf | --------- Co-authored-by: Daniel Karrasch Co-authored-by: Oscar Smith (cherry picked from commit 2cdfe062952c3a1168da7545a10bfa0ec205b4db) --- stdlib/LinearAlgebra/test/triangular.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/stdlib/LinearAlgebra/test/triangular.jl b/stdlib/LinearAlgebra/test/triangular.jl index b337f3c1cf8d9..c0d86caa0f6b8 100644 --- a/stdlib/LinearAlgebra/test/triangular.jl +++ b/stdlib/LinearAlgebra/test/triangular.jl @@ -905,4 +905,14 @@ end @test exp(log(M)) ≈ M end +@testset "log_quasitriu with internal scaling s=0 (issue #54833)" begin + M = [0.9949357359852791 -0.015567763143324862 -0.09091193493947397 -0.03994428739762443 0.07338356301650806; + 0.011813655598647289 0.9968988574699793 -0.06204555000202496 0.04694097614450692 0.09028834462782365; + 0.092737943594701 0.059546719185135925 0.9935850721633324 0.025348893985651405 -0.018530261590167685; + 0.0369187299165628 -0.04903571106913449 -0.025962938675946543 0.9977767446862031 0.12901494726320517; + 0.0 0.0 0.0 0.0 1.0] + + @test exp(log(M)) ≈ M +end + end # module TestTriangular From ecfa806ee56047a8ab949e45c105dd59905f427f Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Thu, 23 Jan 2025 09:51:06 -0500 Subject: [PATCH 04/16] REPL: Handle message from `complete_methods!` when max methods is hit (#57138) (cherry picked from commit 88c71dd2164030ef9563a57ef3f1072581d8efca) --- stdlib/REPL/src/REPLCompletions.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 8b9a552071ea8..8de1cefa06e4a 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -961,6 +961,9 @@ function complete_keyword_argument(partial, last_idx, context_module) last_word = partial[wordrange] # the word to complete kwargs = Set{String}() for m in methods + # if MAX_METHOD_COMPLETIONS is hit a single TextCompletion is return by complete_methods! with an explanation + # which can be ignored here + m isa TextCompletion && continue m::MethodCompletion possible_kwargs = Base.kwarg_decl(m.method) current_kwarg_candidates = String[] From ce106dd4dea5fe1e731ba1317293378bb908046f Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Fri, 31 Jan 2025 14:25:57 -0500 Subject: [PATCH 05/16] =?UTF-8?q?=F0=9F=A4=96=20[backports-release-1.10]?= =?UTF-8?q?=20Bump=20the=20Pkg=20stdlib=20from=206390ea92b=20to=200b3af459?= =?UTF-8?q?2=20(#57225)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: IanButterworth <1694067+IanButterworth@users.noreply.github.com> --- .../Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/md5 | 1 + .../Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/sha512 | 1 + .../Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 | 1 - .../Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/md5 create mode 100644 deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 diff --git a/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/md5 b/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/md5 new file mode 100644 index 0000000000000..4a0ebe571c2f4 --- /dev/null +++ b/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/md5 @@ -0,0 +1 @@ +7269046040e860f243cf379ad1b4291d diff --git a/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/sha512 b/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/sha512 new file mode 100644 index 0000000000000..46348fa21d5a3 --- /dev/null +++ b/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/sha512 @@ -0,0 +1 @@ +31853a2d083a576ddacf2e0318fc5f3ca982b8b7ce2da88ce0fb20617ff2e4adcb3973bcf0d793d131f61104418da0471dd23f7912c65e406881d76f2e0b6914 diff --git a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 b/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 deleted file mode 100644 index 8132509853c1a..0000000000000 --- a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -220272702d818b059c86d96e5d7b6483 diff --git a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 b/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 deleted file mode 100644 index 38f3fc48e8ffb..0000000000000 --- a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -f87ae5aee2c875028cca1b6a3a2a6b494317c20b204ee25b0f62e4fa44ad7d74833e0d16ed0fe90747ed81bc1d075427f24f8820573b74335574ceaae14fda5b diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index fd91f6e800f38..1fa2db36f0cb9 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = release-1.10 -PKG_SHA1 = 6390ea92bf585e182c96cb5db7529c067874e5f5 +PKG_SHA1 = 0b3af4592d7158d4cba1132a9cc9df15e8e51706 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From bd8c582da3755c13d99d1d5f48458418a91e20ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Thu, 6 Feb 2025 00:21:50 +0000 Subject: [PATCH 06/16] [OpenLibm_jll] Update to new build which includes patch to fix stack Ref: #57250. --- deps/checksums/openlibm | 64 ++++++++++---------- deps/openlibm.mk | 9 ++- deps/patches/openlibm-stack-markings.patch | 69 ++++++++++++++++++++++ stdlib/OpenLibm_jll/Project.toml | 2 +- 4 files changed, 110 insertions(+), 34 deletions(-) create mode 100644 deps/patches/openlibm-stack-markings.patch diff --git a/deps/checksums/openlibm b/deps/checksums/openlibm index 452abb133c671..22d35d23ea7aa 100644 --- a/deps/checksums/openlibm +++ b/deps/checksums/openlibm @@ -1,34 +1,34 @@ -OpenLibm.v0.8.1+2.aarch64-apple-darwin.tar.gz/md5/9ce53048e8944f6edff44f75b731229c -OpenLibm.v0.8.1+2.aarch64-apple-darwin.tar.gz/sha512/3a14e28db0656b47a473e19ca0afae1f8b72dd01e108d6b6cb52dc24fc03e4a43db867616b375369e82177bb274fbcfeb8f24b488ee68871e8da8463e9090adf -OpenLibm.v0.8.1+2.aarch64-linux-gnu.tar.gz/md5/8b284fe2905c3e5315291f5e5f27ca8b -OpenLibm.v0.8.1+2.aarch64-linux-gnu.tar.gz/sha512/d326181349ee7f74b73611cd71f933e93c38c11d6db9a1cd4fee49d1ac06c7f244f4cfc6ab373dd52909064117405b3d4fa39e5c626464c066ab53f1cd26dc4a -OpenLibm.v0.8.1+2.aarch64-linux-musl.tar.gz/md5/dc40ad1f2e53a3b914dcca364b6ead77 -OpenLibm.v0.8.1+2.aarch64-linux-musl.tar.gz/sha512/3779d8cd23c5987a15666e2160e40f5a6fc5e7d350c9e3c86d8af8c99515a8cb1f3b5e8438dae0f3cf0b5e1cb2c0cb74c5dd5a06c65e0c2a2382d86dacfaf9fb -OpenLibm.v0.8.1+2.armv6l-linux-gnueabihf.tar.gz/md5/7c9e56f6124b85e7dee74601f8c16abd -OpenLibm.v0.8.1+2.armv6l-linux-gnueabihf.tar.gz/sha512/a78e15177992025462d334a9d5b10b9c7f6710d77ac36056fe7a1cc3bc3fada87f16696366578cfa5f325d5f746639c41c5d80b4885814014d29556d63bd4c7c -OpenLibm.v0.8.1+2.armv6l-linux-musleabihf.tar.gz/md5/78d9e3178fdf93a35f7d2b0b00753dc6 -OpenLibm.v0.8.1+2.armv6l-linux-musleabihf.tar.gz/sha512/ff7b78786f7035eaa08770ddf7d4eb2984595a318c3ac4dfbe4091ca398e00638df2e77bc2ab5fd159defd0927d4fe46b7e824cf055fbae4860bfa12347e8c5b -OpenLibm.v0.8.1+2.armv7l-linux-gnueabihf.tar.gz/md5/7c9e56f6124b85e7dee74601f8c16abd -OpenLibm.v0.8.1+2.armv7l-linux-gnueabihf.tar.gz/sha512/a78e15177992025462d334a9d5b10b9c7f6710d77ac36056fe7a1cc3bc3fada87f16696366578cfa5f325d5f746639c41c5d80b4885814014d29556d63bd4c7c -OpenLibm.v0.8.1+2.armv7l-linux-musleabihf.tar.gz/md5/78d9e3178fdf93a35f7d2b0b00753dc6 -OpenLibm.v0.8.1+2.armv7l-linux-musleabihf.tar.gz/sha512/ff7b78786f7035eaa08770ddf7d4eb2984595a318c3ac4dfbe4091ca398e00638df2e77bc2ab5fd159defd0927d4fe46b7e824cf055fbae4860bfa12347e8c5b -OpenLibm.v0.8.1+2.i686-linux-gnu.tar.gz/md5/e9942dca99f024ae27876ea5ab1592a9 -OpenLibm.v0.8.1+2.i686-linux-gnu.tar.gz/sha512/406e39894a643bf99c493585fa631800bbbcd6c36aaa9e677de772f7ceaed93b462fdf797235174e22baf2f34c26527f400e282061954b34f05b389acaba1e29 -OpenLibm.v0.8.1+2.i686-linux-musl.tar.gz/md5/0037f2e2113282d49967eba72f215c4b -OpenLibm.v0.8.1+2.i686-linux-musl.tar.gz/sha512/96666332a814232084340791384505acf964064dba4f7b62db51a7ae4416237decb40318dc07b9a041547fd4ff77f204f42bc5c7f029e590af1ee1dd6196d843 -OpenLibm.v0.8.1+2.i686-w64-mingw32.tar.gz/md5/73193f2e5149d07008902adfbf1b74b2 -OpenLibm.v0.8.1+2.i686-w64-mingw32.tar.gz/sha512/e8202b59b8f922bcc908b8b8e6687a674faa701689f5c6175d83fea0bcc5d73f74bed37660e60406f37873dab1d8489e0fd1506294791adfa61a069555eababf -OpenLibm.v0.8.1+2.powerpc64le-linux-gnu.tar.gz/md5/01997fb48464f94f59f4708bd26eabc3 -OpenLibm.v0.8.1+2.powerpc64le-linux-gnu.tar.gz/sha512/1e1d8901fd3aab0948be5c387b8d5bd0db12766fe00bf800ee3100aa0d5973c7aa03ef9c9b4e34942e5e2b46b64035d7f8d7b070113db031d4611f2a7dd02ca3 -OpenLibm.v0.8.1+2.x86_64-apple-darwin.tar.gz/md5/6cb5a472d6c1446acfca11bb8f7283d6 -OpenLibm.v0.8.1+2.x86_64-apple-darwin.tar.gz/sha512/e52f399002544d94536c3bda742d3cc5b0995929d656eeb0e808954fb800fd8e5cfc0ab57279fbccab44fc33a1207ab345d78e685d519ff7f02cca8f554b9c06 -OpenLibm.v0.8.1+2.x86_64-linux-gnu.tar.gz/md5/e1c7dc61e98d5b8aa68de3462a2620a4 -OpenLibm.v0.8.1+2.x86_64-linux-gnu.tar.gz/sha512/fe6d74a2522d75374b87ac9746d444d75a768e069f24f3fbfc6a140aa9d073fa54e8899861f839e647b9261e660c5f2b5555f52fab39ef84a74685b632e89df9 -OpenLibm.v0.8.1+2.x86_64-linux-musl.tar.gz/md5/5fe8eb59d21732a80f432720419324b3 -OpenLibm.v0.8.1+2.x86_64-linux-musl.tar.gz/sha512/0d1b22ca01eda89caa1832b63b1d7ddafe0fedf5906680e817100e2176cbbae95f576409706a9ea1834bc692b72009f4fd244586df30228d18e626bf25fc040a -OpenLibm.v0.8.1+2.x86_64-unknown-freebsd.tar.gz/md5/2bcdf32fdef91433763e32be029814d9 -OpenLibm.v0.8.1+2.x86_64-unknown-freebsd.tar.gz/sha512/97854736fc8c797abd5a5c331e5795dfa9124ac108a76fc2bcac518f5750a08884717d611bb98222b13387bcd27e1c3f4ec841547859e87fafbbe8c7dcd7381a -OpenLibm.v0.8.1+2.x86_64-w64-mingw32.tar.gz/md5/e22079c6e610c9543cca0fb88495d989 -OpenLibm.v0.8.1+2.x86_64-w64-mingw32.tar.gz/sha512/67081bcf360a62eee3928bd1b9d5302ed29b4a176245721723692d5ef938a828379617847308f26a2c7bc0cb2d0dce129d4b8c65c0446c611126894c0aaa5ea8 +OpenLibm.v0.8.1+4.aarch64-apple-darwin.tar.gz/md5/f7f8947d276e50b58db7530e050062fd +OpenLibm.v0.8.1+4.aarch64-apple-darwin.tar.gz/sha512/9e28c02d1aa98fdff8e637c9d1a577325d76c098bc89837b5bd3a50ec05647ab8379893a7945d570907b82ef9446804a0065403b6ddec8ede4cb9b0acf5b27ea +OpenLibm.v0.8.1+4.aarch64-linux-gnu.tar.gz/md5/bf9e4bc08aa8488319724b9a3011be8b +OpenLibm.v0.8.1+4.aarch64-linux-gnu.tar.gz/sha512/773263ff709fbdbd07cde5049372175f7cf8fefa26a5fae0fdc48990886911e8c9bcfdb8b05158f38621c79a17e445ad73d41cc4186f6d9df84a3e8232a8a17d +OpenLibm.v0.8.1+4.aarch64-linux-musl.tar.gz/md5/eab078c285039562f65f8fc1d8d62fd9 +OpenLibm.v0.8.1+4.aarch64-linux-musl.tar.gz/sha512/c0b818d728f85ef1ed4231dc2a3bc78e95de9186829d12012b168505b6d6505e4732a379c67a5a3c37e40e048bbaadabc00d153383347e9f606fc9731ebb26d5 +OpenLibm.v0.8.1+4.armv6l-linux-gnueabihf.tar.gz/md5/c76f4ca7bbcd276e5769bd73bee00966 +OpenLibm.v0.8.1+4.armv6l-linux-gnueabihf.tar.gz/sha512/0a711684d1289c747ecadeee0fa1c8ca6067727a5ab5d531f7c30f998c8ee04803c6712067426c939f50698c15104724214eaa3953e522a6dc210c39954f2727 +OpenLibm.v0.8.1+4.armv6l-linux-musleabihf.tar.gz/md5/e072d09a671f98bede25cb0bd00a2fd4 +OpenLibm.v0.8.1+4.armv6l-linux-musleabihf.tar.gz/sha512/37a741e5f66ca4dc8c9358376afb562c7d2a1bb1fcbde2c9b555001a4e6faffc0446b5faff33aead192d4b2fc8cd45c8261b06cc40abec73e39dc63da932b8ab +OpenLibm.v0.8.1+4.armv7l-linux-gnueabihf.tar.gz/md5/c76f4ca7bbcd276e5769bd73bee00966 +OpenLibm.v0.8.1+4.armv7l-linux-gnueabihf.tar.gz/sha512/0a711684d1289c747ecadeee0fa1c8ca6067727a5ab5d531f7c30f998c8ee04803c6712067426c939f50698c15104724214eaa3953e522a6dc210c39954f2727 +OpenLibm.v0.8.1+4.armv7l-linux-musleabihf.tar.gz/md5/e072d09a671f98bede25cb0bd00a2fd4 +OpenLibm.v0.8.1+4.armv7l-linux-musleabihf.tar.gz/sha512/37a741e5f66ca4dc8c9358376afb562c7d2a1bb1fcbde2c9b555001a4e6faffc0446b5faff33aead192d4b2fc8cd45c8261b06cc40abec73e39dc63da932b8ab +OpenLibm.v0.8.1+4.i686-linux-gnu.tar.gz/md5/d8602652f0f347a16e39a869eb2ccb83 +OpenLibm.v0.8.1+4.i686-linux-gnu.tar.gz/sha512/b140032c96497c7e6626751b799598bd54f687af3976bc43ac7ddb6f490527dca64fd44a125da2f54d8ca3679ad53d2700d412ec4c2ddcfe7bfbfe719c0cfc05 +OpenLibm.v0.8.1+4.i686-linux-musl.tar.gz/md5/5d20637487e85b529e3901d129b586a7 +OpenLibm.v0.8.1+4.i686-linux-musl.tar.gz/sha512/b83742801cdfee62bf14bf66f4d20e42219899d431ab335c23f2943c00363c82ee2ab1b853ec421eb825dbe65899fc8f3a3c91c3d86c5e4891c60ddc981d0831 +OpenLibm.v0.8.1+4.i686-w64-mingw32.tar.gz/md5/6ba08a1d5b3aa21fa58618f9ea2a9b8d +OpenLibm.v0.8.1+4.i686-w64-mingw32.tar.gz/sha512/63bed0bc519fa87abae157b53f439f8b452720090780f306b62ff802b8f8ddc4b546899aad5b3e91dacdc3439b7a10a36080d34f09f072719f766c3cdb0baa82 +OpenLibm.v0.8.1+4.powerpc64le-linux-gnu.tar.gz/md5/c9c690ff59b202763ee901f22a798d69 +OpenLibm.v0.8.1+4.powerpc64le-linux-gnu.tar.gz/sha512/83a1e37a62dcff357836385f55f9410cf49b10445c8320b62381359557306c97f11773c508e816fb0bbd4de372b6666833e960921959b6dbb4c7c954e230004a +OpenLibm.v0.8.1+4.x86_64-apple-darwin.tar.gz/md5/bbe8f7a039ad3f07baca340112ea2e65 +OpenLibm.v0.8.1+4.x86_64-apple-darwin.tar.gz/sha512/89e578b7e8e56e7152c9f5881fbf51b33833f8e2143126212e60db262de5641573f33dea5b810575a39e21ec4fbaaa307a049d42e06970c7d4e052b97622938a +OpenLibm.v0.8.1+4.x86_64-linux-gnu.tar.gz/md5/94f42c769349c92987ed3bd9f35d96e0 +OpenLibm.v0.8.1+4.x86_64-linux-gnu.tar.gz/sha512/5e901618da26aa6f0f7d05ed1e5c538aea88cadb59b0efc7213203f1714e85aa0b6f0d463f2a4d367d2a8af36e37e7c353fdefbb98599fdc5bc182a6b93e4348 +OpenLibm.v0.8.1+4.x86_64-linux-musl.tar.gz/md5/462b9dfebd341f0c8bb33ba72f99f769 +OpenLibm.v0.8.1+4.x86_64-linux-musl.tar.gz/sha512/df84815a282a065e8fa33aa35ee29166a1119cd776f8812073e55521ca8c94f4bca679206b8a67ef69edbbb6ba6fca520d81626f687ca353a63146c4858ced80 +OpenLibm.v0.8.1+4.x86_64-unknown-freebsd.tar.gz/md5/f3642b29670e6216056a13f5da9e87b8 +OpenLibm.v0.8.1+4.x86_64-unknown-freebsd.tar.gz/sha512/613242d2f24b1dcc4b2bfd6f22ad66e9889f618ee685b50d9fdf33b9f3798fe503fc9e278f291118db70bacd54bd475f12554a4a56c60c369222fd23b3c5ba22 +OpenLibm.v0.8.1+4.x86_64-w64-mingw32.tar.gz/md5/59381a874c86a5ad5f3fb3b206587f64 +OpenLibm.v0.8.1+4.x86_64-w64-mingw32.tar.gz/sha512/3a8dd3ef46f15f78a34bdc37c5e26dcbf8522625457aa7c52dca21cbb967c5e39257216e5fc203ff57c9171b6c0f2e2ee9d6216c43b0254008f0e91318bb5f0e openlibm-ae2d91698508701c83cab83714d42a1146dccf85.tar.gz/md5/19408d70bf042a109e1c267a53740089 openlibm-ae2d91698508701c83cab83714d42a1146dccf85.tar.gz/sha512/9597fdcbc4af8369e6eecc3f8e86f251661cc64d236578f3ee8a6b39e77a47951446e1a0fe1151513da153e7ed17bf39aa5a36c32153d0d0400232bed2839e22 diff --git a/deps/openlibm.mk b/deps/openlibm.mk index f99cdade47b91..0656ede2a9c8b 100644 --- a/deps/openlibm.mk +++ b/deps/openlibm.mk @@ -6,7 +6,14 @@ $(eval $(call git-external,openlibm,OPENLIBM,,,$(BUILDDIR))) OPENLIBM_FLAGS := ARCH="$(ARCH)" REAL_ARCH="$(MARCH)" CC="$(CC)" FC="$(FC)" AR="$(AR)" OS="$(OS)" USECLANG=$(USECLANG) USEGCC=$(USEGCC) -$(BUILDDIR)/$(OPENLIBM_SRC_DIR)/build-compiled: $(BUILDDIR)/$(OPENLIBM_SRC_DIR)/source-extracted + +$(BUILDDIR)/$(OPENLIBM_SRC_DIR)/source-extracted/openlibm-stack-markings.patch-applied: $(BUILDDIR)/$(OPENLIBM_SRC_DIR)/source-extracted + mkdir -p $(dir $@) + cd $(SRCCACHE)/openlibm-$(OPENLIBM_VER) && \ + patch -p1 -f < $(SRCDIR)/patches/openlibm-stack-markings.patch + echo 1 > $@ + +$(BUILDDIR)/$(OPENLIBM_SRC_DIR)/build-compiled: $(BUILDDIR)/$(OPENLIBM_SRC_DIR)/source-extracted/openlibm-stack-markings.patch-applied $(MAKE) -C $(dir $<) $(OPENLIBM_FLAGS) $(MAKE_COMMON) echo 1 > $@ diff --git a/deps/patches/openlibm-stack-markings.patch b/deps/patches/openlibm-stack-markings.patch new file mode 100644 index 0000000000000..57bc7f4f28b7b --- /dev/null +++ b/deps/patches/openlibm-stack-markings.patch @@ -0,0 +1,69 @@ +From e2482c959e584d52c032af63d1073d2a4e57c345 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jakov=20Smoli=C4=87?= +Date: Mon, 5 Aug 2024 00:12:41 +0200 +Subject: [PATCH] Add stack markings for GNU to fmod assembly files (#307) + +This adds stack markings to the missing fmod .S files, otherwise the +final libopenlibm object file gets marked with an executable stack. + +Output when compiling from source on Gentoo Linux: + +``` + * QA Notice: The following files contain writable and executable sections + * Files with such sections will not work properly (or at all!) on some + * architectures/operating systems. A bug should be filed at + * https://bugs.gentoo.org/ to make sure the issue is fixed. + * For more information, see: + * + * https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart + * + * Please include the following list of files in your report: + * Note: Bugs should be filed for the respective maintainers + * of the package in question and not hardened@gentoo.org. + * RWX --- --- usr/lib64/libopenlibm.so.4.0 +``` +--- + amd64/e_fmod.S | 5 +++++ + amd64/e_fmodf.S | 5 +++++ + amd64/e_fmodl.S | 5 +++++ + 3 files changed, 15 insertions(+) + +diff --git a/amd64/e_fmod.S b/amd64/e_fmod.S +index 37cae391..d2c8ecd9 100644 +--- a/amd64/e_fmod.S ++++ b/amd64/e_fmod.S +@@ -49,3 +49,8 @@ ENTRY(fmod) + fstp %st + ret + END(fmod) ++ ++/* Enable stack protection */ ++#if defined(__ELF__) ++.section .note.GNU-stack,"",%progbits ++#endif +diff --git a/amd64/e_fmodf.S b/amd64/e_fmodf.S +index 197892e8..b045e735 100644 +--- a/amd64/e_fmodf.S ++++ b/amd64/e_fmodf.S +@@ -19,3 +19,8 @@ ENTRY(fmodf) + fstp %st + ret + END(fmodf) ++ ++/* Enable stack protection */ ++#if defined(__ELF__) ++.section .note.GNU-stack,"",%progbits ++#endif +diff --git a/amd64/e_fmodl.S b/amd64/e_fmodl.S +index 64be92f1..cab539d5 100644 +--- a/amd64/e_fmodl.S ++++ b/amd64/e_fmodl.S +@@ -45,3 +45,8 @@ ENTRY(fmodl) + fstp %st(1) + ret + END(fmodl) ++ ++/* Enable stack protection */ ++#if defined(__ELF__) ++.section .note.GNU-stack,"",%progbits ++#endif diff --git a/stdlib/OpenLibm_jll/Project.toml b/stdlib/OpenLibm_jll/Project.toml index f6162f402bfcf..c5ba7fe77b651 100644 --- a/stdlib/OpenLibm_jll/Project.toml +++ b/stdlib/OpenLibm_jll/Project.toml @@ -1,6 +1,6 @@ name = "OpenLibm_jll" uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.1+2" +version = "0.8.1+4" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" From 957cd4ca828aabd5404dc489d8aabfa39ddb4d0e Mon Sep 17 00:00:00 2001 From: Neven Sajko <4944410+nsajko@users.noreply.github.com> Date: Mon, 10 Feb 2025 08:49:50 +0100 Subject: [PATCH 07/16] backport 1.10: fix handling of unknown setting in `@constprop`, fix error message (#57320) Backport of PR #56946 to v1.10. Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> (cherry picked from commit a3f336fd713ff9723073f4543dd5b7c43cfb399e) --- base/expr.jl | 3 ++- test/misc.jl | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/base/expr.jl b/base/expr.jl index 75e54a2249508..284beed95c9a4 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -388,13 +388,14 @@ macro constprop(setting) end function constprop_setting(@nospecialize setting) + s = setting isa(setting, QuoteNode) && (setting = setting.value) if setting === :aggressive return :aggressive_constprop elseif setting === :none return :no_constprop end - throw(ArgumentError(LazyString("@constprop "), setting, "not supported")) + throw(ArgumentError(LazyString("`Base.@constprop ", s, "` not supported"))) end """ diff --git a/test/misc.jl b/test/misc.jl index 79b684badf1e0..c4a12c4db8e7d 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -1402,3 +1402,15 @@ end GC.gc(true); yield() @test in_fin[] end + +@testset "`@constprop`, `@assume_effects` handling of an unknown setting" begin + for x ∈ ("constprop", "assume_effects") + try + eval(Meta.parse("Base.@$x :unknown f() = 3")) + error("unexpectedly reached") + catch e + e::LoadError + @test e.error isa ArgumentError + end + end +end From 096c7df754dd49c1a7e346a22e8bd36b07740dde Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Sat, 8 Feb 2025 21:36:34 -0300 Subject: [PATCH 08/16] Make ptls allocations at least 128 byte aligned (#57310) Fixes https://github.com/JuliaLang/julia/issues/54560#issuecomment-2439710448 (cherry picked from commit 79e98e3b89da5e57f829ccde21b576be9fc8ea1b) --- src/threading.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/threading.c b/src/threading.c index 67617da0951dd..622825c76f364 100644 --- a/src/threading.c +++ b/src/threading.c @@ -345,7 +345,17 @@ jl_ptls_t jl_init_threadtls(int16_t tid) #endif if (jl_get_pgcstack() != NULL) abort(); - jl_ptls_t ptls = (jl_ptls_t)calloc(1, sizeof(jl_tls_states_t)); + jl_ptls_t ptls; +#if defined(_OS_WINDOWS_) + ptls = _aligned_malloc(sizeof(jl_tls_states_t), alignof(jl_tls_states_t)); + if (ptls == NULL) + abort(); +#else + if (posix_memalign((void**)&ptls, alignof(jl_tls_states_t), sizeof(jl_tls_states_t))) + abort(); +#endif + memset(ptls, 0, sizeof(jl_tls_states_t)); + #ifndef _OS_WINDOWS_ pthread_setspecific(jl_task_exit_key, (void*)ptls); #endif From 5bf46f48e11b06fa42c1d0abf28db779164d477b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 8 Aug 2024 15:18:11 -0400 Subject: [PATCH 09/16] handle unbound vars in NTuple fields Comparing objects by `==` will happily answer nonsense for malformed type comparisons, such as `unwrap_unionall(A) == A`. Avoid forming that query. Additionally, need to recourse through Vararg when examining type structure to make decisions. Fix #55076 Fix #55189 --- src/builtins.c | 6 ++++++ src/jltypes.c | 4 ++-- test/core.jl | 7 +++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index 2fd57059f8ac2..a8285aab99953 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1707,6 +1707,12 @@ static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layou if (jl_is_uniontype(p)) return references_name(((jl_uniontype_t*)p)->a, name, affects_layout) || references_name(((jl_uniontype_t*)p)->b, name, affects_layout); + if (jl_is_vararg(p)) { + jl_value_t *T = ((jl_vararg_t*)p)->T; + jl_value_t *N = ((jl_vararg_t*)p)->N; + return (T && references_name(T, name, affects_layout)) || + (N && references_name(N, name, affects_layout)); + } if (jl_is_unionall(p)) return references_name((jl_value_t*)((jl_unionall_t*)p)->var->lb, name, 0) || references_name((jl_value_t*)((jl_unionall_t*)p)->var->ub, name, 0) || diff --git a/src/jltypes.c b/src/jltypes.c index dd26d1df06625..ee1684d0d4b05 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1936,7 +1936,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value // normalize types equal to wrappers (prepare for Typeofwrapper) jl_value_t *tw = extract_wrapper(pi); if (tw && tw != pi && (tn != jl_type_typename || jl_typeof(pi) == jl_typeof(tw)) && - jl_types_equal(pi, tw)) { + !jl_has_free_typevars(pi) && jl_types_equal(pi, tw)) { iparams[i] = tw; if (p) jl_gc_wb(p, tw); } @@ -2569,7 +2569,7 @@ jl_vararg_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n, int check, int nothrow if (valid) { t = normalize_unionalls(t); jl_value_t *tw = extract_wrapper(t); - if (tw && t != tw && jl_types_equal(t, tw)) + if (tw && t != tw && !jl_has_free_typevars(t) && jl_types_equal(t, tw)) t = tw; } } diff --git a/test/core.jl b/test/core.jl index 1321fb825e814..1938e0801a100 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7467,6 +7467,13 @@ struct A43411{S, T} end @test isbitstype(A43411{(:a,), Tuple{Int}}) +# issue #55189 +struct A55189{N} + children::NTuple{N,A55189{N}} +end +@test fieldtype(A55189{2}, 1) === Tuple{A55189{2}, A55189{2}} +@assert !isbitstype(A55189{2}) + # issue #44614 struct T44614_1{T} m::T From cc0dc3dea7a2435d4be5265685a423e2706e4d4f Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Tue, 10 Dec 2024 03:51:46 -0500 Subject: [PATCH 10/16] Fix test report alignment (#56789) (cherry picked from commit 32ea18ecfb545c6abae8013d133d683987b9e323) --- stdlib/Test/src/Test.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 622c696b383a0..3493cfc5e2bd9 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1135,7 +1135,7 @@ function print_test_results(ts::DefaultTestSet, depth_pad=0) duration_width = max(length("Time"), length(duration)) # Calculate the alignment of the test result counts by # recursively walking the tree of test sets - align = max(get_alignment(ts, 0), length("Test Summary:")) + align = max(get_alignment(ts, depth_pad), textwidth("Test Summary:")) # Print the outer test set header once pad = total == 0 ? "" : " " printstyled(rpad("Test Summary:", align, " "), " |", pad; bold=true) From fd41d5e91d883764b7d87aca8e897c61a2fa8418 Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:29:48 -0500 Subject: [PATCH 11/16] Miscellaneous `Meta.partially_inline!` fixes (#56813) This fixes up a couple of conspicuous problems I noticed when reviewing I'm unsure we should have accepted this pass in Base to begin with... It should at least be re-written to error on unexpected IR elements (instead of performing an invalid transform silently), but the real problem is that this pass is out-of-pipeline and so it doesn't run on most user code and we have much worse coverage compared to passes in the main Compiler. (cherry picked from commit c1db3a419699a92c29ce2aff7547019eec3045a4) --- base/meta.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/base/meta.jl b/base/meta.jl index 171ae574ab5ec..99683aac38a99 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -364,6 +364,19 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any}, x.edges .+= slot_offset return x end + if isa(x, Core.UpsilonNode) + if !isdefined(x, :val) + return x + end + return Core.UpsilonNode( + _partially_inline!(x.val, slot_replacements, type_signature, static_param_values, + slot_offset, statement_offset, boundscheck), + ) + end + if isa(x, Core.PhiCNode) + _partially_inline!(x.values, slot_replacements, type_signature, static_param_values, + slot_offset, statement_offset, boundscheck) + end if isa(x, Core.ReturnNode) # Unreachable doesn't have val defined if !isdefined(x, :val) From 09704c7ade881e1ccd7c741d456d02e7bd112349 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Fri, 3 Jan 2025 14:20:00 -0300 Subject: [PATCH 12/16] Make sure we don't promise alignments that are larger than the heap alignment to LLVM (#56938) Fixes https://github.com/JuliaLang/julia/issues/56937 --------- Co-authored-by: Oscar Smith (cherry picked from commit 1e2758e753cf1b1f710492cdb558550b9982266f) --- src/codegen.cpp | 2 ++ src/datatype.c | 2 ++ test/compiler/codegen.jl | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 1968050c3bd34..20a6240a926d0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7715,6 +7715,8 @@ static jl_llvm_functions_t Type *RT = Arg->getParamStructRetType(); TypeSize sz = DL.getTypeAllocSize(RT); Align al = DL.getPrefTypeAlign(RT); + if (al > MAX_ALIGN) + al = Align(MAX_ALIGN); param.addAttribute(Attribute::NonNull); // The `dereferenceable` below does not imply `nonnull` for non addrspace(0) pointers. param.addDereferenceableAttr(sz); diff --git a/src/datatype.c b/src/datatype.c index 905959fb80e0a..3e8de1d59f33b 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -648,6 +648,8 @@ void jl_compute_field_offsets(jl_datatype_t *st) if (al > alignm) alignm = al; } + if (alignm > MAX_ALIGN) + alignm = MAX_ALIGN; // We cannot guarantee alignments over 16 bytes because that's what our heap is aligned as if (LLT_ALIGN(sz, alignm) > sz) { haspadding = 1; sz = LLT_ALIGN(sz, alignm); diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 00aae0e748bc9..21cf2e8fca5db 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -873,3 +873,9 @@ end # Core.getptls() special handling @test !occursin("call ptr @jlplt", get_llvm(Core.getptls, Tuple{})) #It should lower to a direct load of the ptls and not a ccall + + +struct Vec56937 x::NTuple{8, VecElement{Int}} end + +x56937 = Ref(Vec56937(ntuple(_->VecElement(1),8))) +@test x56937[].x[1] == VecElement{Int}(1) # shouldn't crash From 9103718691c0d71a47d84341d9732695fae3807b Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Thu, 9 Jan 2025 23:24:49 -0300 Subject: [PATCH 13/16] Make write(IO, Char) actually return the amount of printed bytes instead of the attempted written bytes. (#56980) (cherry picked from commit 6ac351a9890272db959396a77254c8b4b807d69f) --- base/io.jl | 5 ++--- test/iobuffer.jl | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/base/io.jl b/base/io.jl index bf58493ad27ff..5159b2e5f5208 100644 --- a/base/io.jl +++ b/base/io.jl @@ -747,11 +747,10 @@ end function write(io::IO, c::Char) u = bswap(reinterpret(UInt32, c)) - n = 1 + n = 0 while true - write(io, u % UInt8) + n += write(io, u % UInt8) (u >>= 8) == 0 && return n - n += 1 end end # write(io, ::AbstractChar) is not defined: implementations diff --git a/test/iobuffer.jl b/test/iobuffer.jl index ec77903b4a5b8..9726007b87f7e 100644 --- a/test/iobuffer.jl +++ b/test/iobuffer.jl @@ -357,3 +357,9 @@ end seek(io,0) @test Base.read_sub(io,v,1,1) == [1,0] end + +@testset "Writing Char to full buffer" begin + io = IOBuffer(;maxsize=1) + write(io, 'a') + @test write(io, 'a') == 0 +end From 1895479fd0c89e63abb772eb4b6b00519c74f1a8 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 27 Sep 2023 11:31:25 +0200 Subject: [PATCH 14/16] inference: avoid inferring unreachable code methods (#51317) (cherry picked from commit 0a82b71681028d6b1a49d580496f28ebc214a21e) --- base/compiler/abstractinterpretation.jl | 57 +++++++----- base/compiler/abstractlattice.jl | 8 +- base/compiler/optimize.jl | 2 +- base/compiler/ssair/inlining.jl | 2 +- base/compiler/ssair/passes.jl | 2 +- base/compiler/tfuncs.jl | 117 ++++++++++++------------ base/compiler/typelattice.jl | 4 +- base/compiler/typeutils.jl | 17 ++-- test/compiler/inference.jl | 21 +++++ test/compiler/inline.jl | 27 ------ 10 files changed, 137 insertions(+), 120 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 1bdba2a5d8924..5dcc7b849e59f 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -506,7 +506,10 @@ function abstract_call_method(interp::AbstractInterpreter, return MethodCallResult(Any, false, false, nothing, Effects()) end sigtuple = unwrap_unionall(sig) - sigtuple isa DataType || return MethodCallResult(Any, false, false, nothing, Effects()) + sigtuple isa DataType || + return MethodCallResult(Any, false, false, nothing, Effects()) + all(@nospecialize(x) -> valid_as_lattice(unwrapva(x), true), sigtuple.parameters) || + return MethodCallResult(Union{}, false, false, nothing, EFFECTS_THROWS) # catch bad type intersections early if is_nospecializeinfer(method) sig = get_nospecializeinfer_sig(method, sig, sparams) @@ -1385,25 +1388,35 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft) end if isa(tti, Union) utis = uniontypes(tti) - if any(@nospecialize(t) -> !isa(t, DataType) || !(t <: Tuple) || !isknownlength(t), utis) - return AbstractIterationResult(Any[Vararg{Any}], nothing, Effects()) - end - ltp = length((utis[1]::DataType).parameters) - for t in utis - if length((t::DataType).parameters) != ltp - return AbstractIterationResult(Any[Vararg{Any}], nothing) + # refine the Union to remove elements that are not valid tags for objects + filter!(@nospecialize(x) -> valid_as_lattice(x, true), utis) + if length(utis) == 0 + return AbstractIterationResult(Any[], nothing) # oops, this statement was actually unreachable + elseif length(utis) == 1 + tti = utis[1] + tti0 = rewrap_unionall(tti, tti0) + else + if any(@nospecialize(t) -> !isa(t, DataType) || !(t <: Tuple) || !isknownlength(t), utis) + return AbstractIterationResult(Any[Vararg{Any}], nothing, Effects()) end - end - result = Any[ Union{} for _ in 1:ltp ] - for t in utis - tps = (t::DataType).parameters - _all(valid_as_lattice, tps) || continue - for j in 1:ltp - result[j] = tmerge(result[j], rewrap_unionall(tps[j], tti0)) + ltp = length((utis[1]::DataType).parameters) + for t in utis + if length((t::DataType).parameters) != ltp + return AbstractIterationResult(Any[Vararg{Any}], nothing) + end + end + result = Any[ Union{} for _ in 1:ltp ] + for t in utis + tps = (t::DataType).parameters + for j in 1:ltp + @assert valid_as_lattice(tps[j], true) + result[j] = tmerge(result[j], rewrap_unionall(tps[j], tti0)) + end end + return AbstractIterationResult(result, nothing) end - return AbstractIterationResult(result, nothing) - elseif tti0 <: Tuple + end + if tti0 <: Tuple if isa(tti0, DataType) return AbstractIterationResult(Any[ p for p in tti0.parameters ], nothing) elseif !isa(tti, DataType) @@ -1667,7 +1680,7 @@ end return isa_condition(xt, ty, max_union_splitting) end @inline function isa_condition(@nospecialize(xt), @nospecialize(ty), max_union_splitting::Int) - tty_ub, isexact_tty = instanceof_tfunc(ty) + tty_ub, isexact_tty = instanceof_tfunc(ty, true) tty = widenconst(xt) if isexact_tty && !isa(tty_ub, TypeVar) tty_lb = tty_ub # TODO: this would be wrong if !isexact_tty, but instanceof_tfunc doesn't preserve this info @@ -1677,7 +1690,7 @@ end # `typeintersect` may be unable narrow down `Type`-type thentype = tty_ub end - valid_as_lattice(thentype) || (thentype = Bottom) + valid_as_lattice(thentype, true) || (thentype = Bottom) elsetype = typesubtract(tty, tty_lb, max_union_splitting) return ConditionalTypes(thentype, elsetype) end @@ -1923,7 +1936,7 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn ft′ = argtype_by_index(argtypes, 2) ft = widenconst(ft′) ft === Bottom && return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo()) - (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, 3)) + (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, 3), false) isexact || return CallMeta(Any, Effects(), NoCallInfo()) unwrapped = unwrap_unionall(types) if types === Bottom || !(unwrapped isa DataType) || unwrapped.name !== Tuple.name @@ -2380,7 +2393,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp (; rt, effects) = abstract_eval_call(interp, e, vtypes, sv) t = rt elseif ehead === :new - t, isexact = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv)) + t, isexact = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv), true) ut = unwrap_unionall(t) consistent = ALWAYS_FALSE nothrow = false @@ -2444,7 +2457,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp end effects = Effects(EFFECTS_TOTAL; consistent, nothrow) elseif ehead === :splatnew - t, isexact = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv)) + t, isexact = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv), true) nothrow = false # TODO: More precision if length(e.args) == 2 && isconcretedispatch(t) && !ismutabletype(t) at = abstract_eval_value(interp, e.args[2], vtypes, sv) diff --git a/base/compiler/abstractlattice.jl b/base/compiler/abstractlattice.jl index 3c6c874a9a09c..42c7579698b21 100644 --- a/base/compiler/abstractlattice.jl +++ b/base/compiler/abstractlattice.jl @@ -98,8 +98,10 @@ is_valid_lattice_norec(::InferenceLattice, @nospecialize(elem)) = isa(elem, Limi """ tmeet(𝕃::AbstractLattice, a, b::Type) -Compute the lattice meet of lattice elements `a` and `b` over the lattice `𝕃`. -If `𝕃` is `JLTypeLattice`, this is equivalent to type intersection. +Compute the lattice meet of lattice elements `a` and `b` over the lattice `𝕃`, +dropping any results that will not be inhabited at runtime. +If `𝕃` is `JLTypeLattice`, this is equivalent to type intersection plus the +elimination of results that have no concrete subtypes. Note that currently `b` is restricted to being a type (interpreted as a lattice element in the `JLTypeLattice` sub-lattice of `𝕃`). """ @@ -107,7 +109,7 @@ function tmeet end function tmeet(::JLTypeLattice, @nospecialize(a::Type), @nospecialize(b::Type)) ti = typeintersect(a, b) - valid_as_lattice(ti) || return Bottom + valid_as_lattice(ti, true) || return Bottom return ti end diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 3a8de06811cc2..28c10b75c158a 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -305,7 +305,7 @@ function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospe elseif head === :new_opaque_closure length(args) < 4 && return (false, false, false) typ = argextype(args[1], src) - typ, isexact = instanceof_tfunc(typ) + typ, isexact = instanceof_tfunc(typ, true) isexact || return (false, false, false) ⊑(𝕃ₒ, typ, Tuple) || return (false, false, false) rt_lb = argextype(args[2], src) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 75e63f5c6b2e4..ed6e90d0bdbf5 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -1202,7 +1202,7 @@ function handle_invoke_call!(todo::Vector{Pair{Int,Any}}, end function invoke_signature(argtypes::Vector{Any}) - ft, argtyps = widenconst(argtypes[2]), instanceof_tfunc(widenconst(argtypes[3]))[1] + ft, argtyps = widenconst(argtypes[2]), instanceof_tfunc(widenconst(argtypes[3]), false)[1] return rewrap_unionall(Tuple{ft, unwrap_unionall(argtyps).parameters...}, argtyps) end diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index afdc0fd0b9ab2..46a93009429b3 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -1705,7 +1705,7 @@ function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing) else if is_known_call(stmt, typeassert, compact) && length(stmt.args) == 3 # nullify safe `typeassert` calls - ty, isexact = instanceof_tfunc(argextype(stmt.args[3], compact)) + ty, isexact = instanceof_tfunc(argextype(stmt.args[3], compact), true) if isexact && ⊑(𝕃ₒ, argextype(stmt.args[2], compact), ty) compact[idx] = nothing continue diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index e2773752c68e6..6153765a713a4 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -95,9 +95,9 @@ add_tfunc(throw, 1, 1, @nospecs((𝕃::AbstractLattice, x)->Bottom), 0) # if isexact is false, the actual runtime type may (will) be a subtype of t # if isconcrete is true, the actual runtime type is definitely concrete (unreachable if not valid as a typeof) # if istype is true, the actual runtime value will definitely be a type (e.g. this is false for Union{Type{Int}, Int}) -function instanceof_tfunc(@nospecialize(t), @nospecialize(troot) = t) +function instanceof_tfunc(@nospecialize(t), astag::Bool=false, @nospecialize(troot) = t) if isa(t, Const) - if isa(t.val, Type) && valid_as_lattice(t.val) + if isa(t.val, Type) && valid_as_lattice(t.val, astag) return t.val, true, isconcretetype(t.val), true end return Bottom, true, false, false # runtime throws on non-Type @@ -110,7 +110,7 @@ function instanceof_tfunc(@nospecialize(t), @nospecialize(troot) = t) return Bottom, true, false, false # literal Bottom or non-Type elseif isType(t) tp = t.parameters[1] - valid_as_lattice(tp) || return Bottom, true, false, false # runtime unreachable / throws on non-Type + valid_as_lattice(tp, astag) || return Bottom, true, false, false # runtime unreachable / throws on non-Type if troot isa UnionAll # Free `TypeVar`s inside `Type` has violated the "diagonal" rule. # Widen them before `UnionAll` rewraping to relax concrete constraint. @@ -119,7 +119,7 @@ function instanceof_tfunc(@nospecialize(t), @nospecialize(troot) = t) return tp, !has_free_typevars(tp), isconcretetype(tp), true elseif isa(t, UnionAll) t′ = unwrap_unionall(t) - t′′, isexact, isconcrete, istype = instanceof_tfunc(t′, rewrap_unionall(t, troot)) + t′′, isexact, isconcrete, istype = instanceof_tfunc(t′, astag, rewrap_unionall(t, troot)) tr = rewrap_unionall(t′′, t) if t′′ isa DataType && t′′.name !== Tuple.name && !has_free_typevars(tr) # a real instance must be within the declared bounds of the type, @@ -134,8 +134,8 @@ function instanceof_tfunc(@nospecialize(t), @nospecialize(troot) = t) end return tr, isexact, isconcrete, istype elseif isa(t, Union) - ta, isexact_a, isconcrete_a, istype_a = instanceof_tfunc(unwraptv(t.a), troot) - tb, isexact_b, isconcrete_b, istype_b = instanceof_tfunc(unwraptv(t.b), troot) + ta, isexact_a, isconcrete_a, istype_a = instanceof_tfunc(unwraptv(t.a), astag, troot) + tb, isexact_b, isconcrete_b, istype_b = instanceof_tfunc(unwraptv(t.b), astag, troot) isconcrete = isconcrete_a && isconcrete_b istype = istype_a && istype_b # most users already handle the Union case, so here we assume that @@ -155,9 +155,9 @@ end # ---------- @nospecs bitcast_tfunc(𝕃::AbstractLattice, t, x) = bitcast_tfunc(widenlattice(𝕃), t, x) -@nospecs bitcast_tfunc(::JLTypeLattice, t, x) = instanceof_tfunc(t)[1] +@nospecs bitcast_tfunc(::JLTypeLattice, t, x) = instanceof_tfunc(t, true)[1] @nospecs conversion_tfunc(𝕃::AbstractLattice, t, x) = conversion_tfunc(widenlattice(𝕃), t, x) -@nospecs conversion_tfunc(::JLTypeLattice, t, x) = instanceof_tfunc(t)[1] +@nospecs conversion_tfunc(::JLTypeLattice, t, x) = instanceof_tfunc(t, true)[1] add_tfunc(bitcast, 2, 2, bitcast_tfunc, 1) add_tfunc(sext_int, 2, 2, conversion_tfunc, 1) @@ -275,7 +275,7 @@ add_tfunc(checked_umul_int, 2, 2, chk_tfunc, 10) # ----------- @nospecs function llvmcall_tfunc(𝕃::AbstractLattice, fptr, rt, at, a...) - return instanceof_tfunc(rt)[1] + return instanceof_tfunc(rt, true)[1] end add_tfunc(Core.Intrinsics.llvmcall, 3, INT_INF, llvmcall_tfunc, 10) @@ -445,7 +445,7 @@ function sizeof_nothrow(@nospecialize(x)) return sizeof_nothrow(rewrap_unionall(xu.a, x)) && sizeof_nothrow(rewrap_unionall(xu.b, x)) end - t, exact, isconcrete = instanceof_tfunc(x) + t, exact, isconcrete = instanceof_tfunc(x, false) if t === Bottom # x must be an instance (not a Type) or is the Bottom type object x = widenconst(x) @@ -497,7 +497,7 @@ end end # Core.sizeof operates on either a type or a value. First check which # case we're in. - t, exact = instanceof_tfunc(x) + t, exact = instanceof_tfunc(x, false) if t !== Bottom # The value corresponding to `x` at runtime could be a type. # Normalize the query to ask about that type. @@ -657,7 +657,7 @@ function pointer_eltype(@nospecialize(ptr)) unw = unwrap_unionall(a) if isa(unw, DataType) && unw.name === Ptr.body.name T = unw.parameters[1] - valid_as_lattice(T) || return Bottom + valid_as_lattice(T, true) || return Bottom return rewrap_unionall(T, a) end end @@ -689,7 +689,7 @@ end if isa(unw, DataType) && unw.name === Ptr.body.name T = unw.parameters[1] # note: we could sometimes refine this to a PartialStruct if we analyzed `op(T, T)::T` - valid_as_lattice(T) || return Bottom + valid_as_lattice(T, true) || return Bottom return rewrap_unionall(Pair{T, T}, a) end end @@ -701,7 +701,7 @@ end unw = unwrap_unionall(a) if isa(unw, DataType) && unw.name === Ptr.body.name T = unw.parameters[1] - valid_as_lattice(T) || return Bottom + valid_as_lattice(T, true) || return Bottom return rewrap_unionall(ccall(:jl_apply_cmpswap_type, Any, (Any,), T), a) end end @@ -805,7 +805,7 @@ end add_tfunc(typeof, 1, 1, typeof_tfunc, 1) @nospecs function typeassert_tfunc(𝕃::AbstractLattice, v, t) - t = instanceof_tfunc(t)[1] + t = instanceof_tfunc(t, true)[1] t === Any && return v return tmeet(𝕃, v, t) end @@ -813,7 +813,7 @@ add_tfunc(typeassert, 2, 2, typeassert_tfunc, 4) @nospecs function typeassert_nothrow(𝕃::AbstractLattice, v, t) ⊑ = Core.Compiler.:⊑(𝕃) - # ty, exact = instanceof_tfunc(t) + # ty, exact = instanceof_tfunc(t, true) # return exact && v ⊑ ty if (isType(t) && !has_free_typevars(t) && v ⊑ t.parameters[1]) || (isa(t, Const) && isa(t.val, Type) && v ⊑ t.val) @@ -823,7 +823,7 @@ add_tfunc(typeassert, 2, 2, typeassert_tfunc, 4) end @nospecs function isa_tfunc(𝕃::AbstractLattice, v, tt) - t, isexact = instanceof_tfunc(tt) + t, isexact = instanceof_tfunc(tt, true) if t === Bottom # check if t could be equivalent to typeof(Bottom), since that's valid in `isa`, but the set of `v` is empty # if `t` cannot have instances, it's also invalid on the RHS of isa @@ -863,8 +863,8 @@ add_tfunc(isa, 2, 2, isa_tfunc, 1) end @nospecs function subtype_tfunc(𝕃::AbstractLattice, a, b) - a, isexact_a = instanceof_tfunc(a) - b, isexact_b = instanceof_tfunc(b) + a, isexact_a = instanceof_tfunc(a, false) + b, isexact_b = instanceof_tfunc(b, false) if !has_free_typevars(a) && !has_free_typevars(b) if a <: b if isexact_b || a === Bottom @@ -1216,31 +1216,36 @@ end return Bottom end if nf == 1 - return rewrap_unionall(unwrapva(ftypes[1]), s00) - end - # union together types of all fields - t = Bottom - for i in 1:nf - _ft = ftypes[i] - setfield && isconst(s, i) && continue - t = tmerge(t, rewrap_unionall(unwrapva(_ft), s00)) - t === Any && break + fld = 1 + else + # union together types of all fields + t = Bottom + for i in 1:nf + _ft = unwrapva(ftypes[i]) + valid_as_lattice(_ft, true) || continue + setfield && isconst(s, i) && continue + t = tmerge(t, rewrap_unionall(_ft, s00)) + t === Any && break + end + return t end - return t + else + fld = _getfield_fieldindex(s, name) + fld === nothing && return Bottom end - fld = _getfield_fieldindex(s, name) - fld === nothing && return Bottom if s <: Tuple && fld >= nf && isvarargtype(ftypes[nf]) - return rewrap_unionall(unwrapva(ftypes[nf]), s00) - end - if fld < 1 || fld > nf - return Bottom - elseif setfield && isconst(s, fld) - return Bottom - end - R = ftypes[fld] - if isempty(s.parameters) - return R + R = unwrapva(ftypes[nf]) + else + if fld < 1 || fld > nf + return Bottom + elseif setfield && isconst(s, fld) + return Bottom + end + R = ftypes[fld] + valid_as_lattice(R, true) || return Bottom + if isempty(s.parameters) + return R + end end return rewrap_unionall(R, s00) end @@ -1375,7 +1380,7 @@ end T = _fieldtype_tfunc(𝕃, o, f, isconcretetype(o)) T === Bottom && return Bottom PT = Const(Pair) - return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T, T))[1] + return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T, T), true)[1] end function abstract_modifyfield!(interp::AbstractInterpreter, argtypes::Vector{Any}, si::StmtInfo, sv::AbsIntState) nargs = length(argtypes) @@ -1417,7 +1422,7 @@ end T = _fieldtype_tfunc(𝕃, o, f, isconcretetype(o)) T === Bottom && return Bottom PT = Const(ccall(:jl_apply_cmpswap_type, Any, (Any,), T) where T) - return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T))[1] + return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T), true)[1] end # we could use tuple_tfunc instead of widenconst, but `o` is mutable, so that is unlikely to be beneficial @@ -1449,7 +1454,7 @@ add_tfunc(replacefield!, 4, 6, replacefield!_tfunc, 3) fieldtype_nothrow(𝕃, rewrap_unionall(su.b, s0), name) end - s, exact = instanceof_tfunc(s0) + s, exact = instanceof_tfunc(s0, false) s === Bottom && return false # always return _fieldtype_nothrow(s, exact, name) end @@ -1514,7 +1519,7 @@ end fieldtype_tfunc(𝕃, rewrap_unionall(su.b, s0), name)) end - s, exact = instanceof_tfunc(s0) + s, exact = instanceof_tfunc(s0, false) s === Bottom && return Bottom return _fieldtype_tfunc(𝕃, s, name, exact) end @@ -1527,8 +1532,8 @@ end tb0 = _fieldtype_tfunc(𝕃, rewrap_unionall(u.b, s), name, exact) ta0 ⊑ tb0 && return tb0 tb0 ⊑ ta0 && return ta0 - ta, exacta, _, istypea = instanceof_tfunc(ta0) - tb, exactb, _, istypeb = instanceof_tfunc(tb0) + ta, exacta, _, istypea = instanceof_tfunc(ta0, false) + tb, exactb, _, istypeb = instanceof_tfunc(tb0, false) if exact && exacta && exactb return Const(Union{ta, tb}) end @@ -1662,7 +1667,7 @@ function apply_type_nothrow(𝕃::AbstractLattice, argtypes::Vector{Any}, @nospe return false end else - T, exact, _, istype = instanceof_tfunc(ai) + T, exact, _, istype = instanceof_tfunc(ai, false) if T === Bottom if !(u.var.lb === Union{} && u.var.ub === Any) return false @@ -1726,9 +1731,7 @@ const _tvarnames = Symbol[:_A, :_B, :_C, :_D, :_E, :_F, :_G, :_H, :_I, :_J, :_K, end end if largs == 1 # Union{T} --> T - u1 = typeintersect(widenconst(args[1]), Union{Type,TypeVar}) - valid_as_lattice(u1) || return Bottom - return u1 + return tmeet(widenconst(args[1]), Union{Type,TypeVar}) end hasnonType && return Type ty = Union{} @@ -1813,7 +1816,7 @@ const _tvarnames = Symbol[:_A, :_B, :_C, :_D, :_E, :_F, :_G, :_H, :_I, :_J, :_K, elseif !isT # if we didn't have isType to compute ub directly, try to use instanceof_tfunc to refine this guess ai_w = widenconst(ai) - ub = ai_w isa Type && ai_w <: Type ? instanceof_tfunc(ai)[1] : Any + ub = ai_w isa Type && ai_w <: Type ? instanceof_tfunc(ai, false)[1] : Any end if istuple # in the last parameter of a Tuple type, if the upper bound is Any @@ -2012,7 +2015,7 @@ function array_elmtype(@nospecialize ary) end if isa(a, DataType) T = a.parameters[1] - valid_as_lattice(T) || return Bottom + valid_as_lattice(T, true) || return Bottom return rewrap_unionall(T, a0) end end @@ -2542,7 +2545,7 @@ function intrinsic_nothrow(f::IntrinsicFunction, argtypes::Vector{Any}) return argtypes[1] ⊑ Array end if f === Intrinsics.bitcast - ty, isexact, isconcrete = instanceof_tfunc(argtypes[1]) + ty, isexact, isconcrete = instanceof_tfunc(argtypes[1], true) xty = widenconst(argtypes[2]) return isconcrete && isprimitivetype(ty) && isprimitivetype(xty) && Core.sizeof(ty) === Core.sizeof(xty) end @@ -2551,12 +2554,12 @@ function intrinsic_nothrow(f::IntrinsicFunction, argtypes::Vector{Any}) Intrinsics.sitofp, Intrinsics.fptrunc, Intrinsics.fpext) # If !isconcrete, `ty` may be Union{} at runtime even if we have # isprimitivetype(ty). - ty, isexact, isconcrete = instanceof_tfunc(argtypes[1]) + ty, isexact, isconcrete = instanceof_tfunc(argtypes[1], true) xty = widenconst(argtypes[2]) return isconcrete && isprimitivetype(ty) && isprimitivetype(xty) end if f === Intrinsics.have_fma - ty, isexact, isconcrete = instanceof_tfunc(argtypes[1]) + ty, isexact, isconcrete = instanceof_tfunc(argtypes[1], true) return isconcrete && isprimitivetype(ty) end # The remaining intrinsics are math/bits/comparison intrinsics. They work on all @@ -2746,7 +2749,7 @@ function _hasmethod_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, sv else return CallMeta(Any, Effects(), NoCallInfo()) end - (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, typeidx)) + (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, typeidx), false) isexact || return CallMeta(Bool, Effects(), NoCallInfo()) unwrapped = unwrap_unionall(types) if types === Bottom || !(unwrapped isa DataType) || unwrapped.name !== Tuple.name diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index 324f2b600cc44..df6022609d612 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -607,7 +607,7 @@ end if ti === widev return v end - valid_as_lattice(ti) || return Bottom + valid_as_lattice(ti, true) || return Bottom if widev <: Tuple new_fields = Vector{Any}(undef, length(v.fields)) for i = 1:length(new_fields) @@ -631,7 +631,7 @@ end return v end ti = typeintersect(widev, t) - valid_as_lattice(ti) || return Bottom + valid_as_lattice(ti, true) || return Bottom return PartialOpaque(ti, v.env, v.parent, v.source) end return tmeet(widenlattice(lattice), v, t) diff --git a/base/compiler/typeutils.jl b/base/compiler/typeutils.jl index 2ecc077228264..5479f835d4c5d 100644 --- a/base/compiler/typeutils.jl +++ b/base/compiler/typeutils.jl @@ -95,12 +95,13 @@ end has_concrete_subtype(d::DataType) = d.flags & 0x0020 == 0x0020 # n.b. often computed only after setting the type and layout fields -# determine whether x is a valid lattice element tag +# determine whether x is a valid lattice element # For example, Type{v} is not valid if v is a value -# Accepts TypeVars also, since it assumes the user will rewrap it correctly -function valid_as_lattice(@nospecialize(x)) +# Accepts TypeVars and has_free_typevar also, since it assumes the user will rewrap it correctly +# If astag is true, then also requires that it be a possible type tag for a valid object +function valid_as_lattice(@nospecialize(x), astag::Bool=false) x === Bottom && false - x isa TypeVar && return valid_as_lattice(x.ub) + x isa TypeVar && return valid_as_lattice(x.ub, astag) x isa UnionAll && (x = unwrap_unionall(x)) if x isa Union # the Union constructor ensures this (and we'll recheck after @@ -111,6 +112,9 @@ function valid_as_lattice(@nospecialize(x)) if isType(x) p = x.parameters[1] p isa Type || p isa TypeVar || return false + elseif astag && isstructtype(x) + datatype_fieldtypes(x) # force computation of has_concrete_subtype to be updated now + return has_concrete_subtype(x) end return true end @@ -149,6 +153,7 @@ function compatible_vatuple(a::DataType, b::DataType) end # return an upper-bound on type `a` with type `b` removed +# and also any contents that are not valid type tags on any objects # such that `return <: a` && `Union{return, b} == Union{a, b}` function typesubtract(@nospecialize(a), @nospecialize(b), max_union_splitting::Int) if a <: b && isnotbrokensubtype(a, b) @@ -158,8 +163,8 @@ function typesubtract(@nospecialize(a), @nospecialize(b), max_union_splitting::I if isa(ua, Union) uua = typesubtract(rewrap_unionall(ua.a, a), b, max_union_splitting) uub = typesubtract(rewrap_unionall(ua.b, a), b, max_union_splitting) - return Union{valid_as_lattice(uua) ? uua : Union{}, - valid_as_lattice(uub) ? uub : Union{}} + return Union{valid_as_lattice(uua, true) ? uua : Union{}, + valid_as_lattice(uub, true) ? uub : Union{}} elseif a isa DataType ub = unwrap_unionall(b) if ub isa DataType diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index c61a756a0b6a7..a18b3f52a7685 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5172,3 +5172,24 @@ end) === Union{} @test only(Base.Base.return_types() do TypeVar(:Issue56248, Any, 1) end) === Union{} + +# issue 51228 +global whatever_unknown_value51228 +f51228() = f51228(whatever_unknown_value51228) +f51228(x) = 1 +f51228(::Vararg{T,T}) where {T} = "2" +@test only(Base.return_types(f51228, ())) == Int + +struct A51317 + b::Tuple{1} + A1() = new() +end +struct An51317 + a::Int + b::Tuple{1} + An51317() = new() +end +@test only(Base.return_types((x,f) -> getfield(x, f), (A51317, Symbol))) === Union{} +@test only(Base.return_types((x,f) -> getfield(x, f), (An51317, Symbol))) === Int +@test only(Base.return_types(x -> getfield(x, :b), (A51317,))) === Union{} +@test only(Base.return_types(x -> getfield(x, :b), (An51317,))) === Union{} diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 780a5424a29c2..7ab3589c725f9 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -1642,33 +1642,6 @@ function oc_capture_oc(z) end @test fully_eliminated(oc_capture_oc, (Int,)) -@eval struct OldVal{T} - x::T - (OV::Type{OldVal{T}})() where T = $(Expr(:new, :OV)) -end -with_unmatched_typeparam1(x::OldVal{i}) where {i} = i -with_unmatched_typeparam2() = [ Base.donotdelete(OldVal{i}()) for i in 1:10000 ] -function with_unmatched_typeparam3() - f(x::OldVal{i}) where {i} = i - r = 0 - for i = 1:10000 - r += f(OldVal{i}()) - end - return r -end - -@testset "Inlining with unmatched type parameters" begin - let src = code_typed1(with_unmatched_typeparam1, (Any,)) - @test !any(@nospecialize(x) -> isexpr(x, :call) && length(x.args) == 1, src.code) - end - let src = code_typed1(with_unmatched_typeparam2) - @test !any(@nospecialize(x) -> isexpr(x, :call) && length(x.args) == 1, src.code) - end - let src = code_typed1(with_unmatched_typeparam3) - @test !any(@nospecialize(x) -> isexpr(x, :call) && length(x.args) == 1, src.code) - end -end - function twice_sitofp(x::Int, y::Int) x = Base.sitofp(Float64, x) y = Base.sitofp(Float64, y) From 4226f1e698b41e1d0537bc1845beb6eee1d612c0 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 21 Jan 2025 13:12:05 -0500 Subject: [PATCH 15/16] inference: ensure inferring reachable code methods (#57088) PR #51317 was a bit over-eager about inferring inferring unreachable code methods. Filter out the Vararg case, since that can be handled by simply removing it instead of discarding the whole call. Fixes #56628 (cherry picked from commit eb9f24c8ceb964464939775e164366939755393c) --- base/compiler/abstractinterpretation.jl | 4 +++- base/compiler/ssair/inlining.jl | 5 +++-- base/compiler/tfuncs.jl | 4 ++++ base/compiler/typeutils.jl | 7 ++++++- test/compiler/inference.jl | 6 ++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 5dcc7b849e59f..49149fde59691 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -243,6 +243,7 @@ function find_matching_methods(𝕃::AbstractLattice, for i in 1:length(split_argtypes) arg_n = split_argtypes[i]::Vector{Any} sig_n = argtypes_to_type(arg_n) + sig_n === Bottom && continue mt = ccall(:jl_method_table_for, Any, (Any,), sig_n) mt === nothing && return FailedMethodMatch("Could not identify method table for call") mt = mt::MethodTable @@ -508,7 +509,7 @@ function abstract_call_method(interp::AbstractInterpreter, sigtuple = unwrap_unionall(sig) sigtuple isa DataType || return MethodCallResult(Any, false, false, nothing, Effects()) - all(@nospecialize(x) -> valid_as_lattice(unwrapva(x), true), sigtuple.parameters) || + all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), sigtuple.parameters) || return MethodCallResult(Union{}, false, false, nothing, EFFECTS_THROWS) # catch bad type intersections early if is_nospecializeinfer(method) @@ -2166,6 +2167,7 @@ function abstract_call_unknown(interp::AbstractInterpreter, @nospecialize(ft), end # non-constant function, but the number of arguments is known and the `f` is not a builtin or intrinsic atype = argtypes_to_type(arginfo.argtypes) + atype === Bottom && return CallMeta(Union{}, Union{}, EFFECTS_THROWS, NoCallInfo()) # accidentally unreachable return abstract_call_gf_by_type(interp, nothing, arginfo, si, atype, sv, max_methods) end diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index ed6e90d0bdbf5..1302d81e23427 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -1450,8 +1450,9 @@ function handle_call!(todo::Vector{Pair{Int,Any}}, cases = compute_inlining_cases(info, flag, sig, state) cases === nothing && return nothing cases, all_covered, joint_effects = cases - handle_cases!(todo, ir, idx, stmt, argtypes_to_type(sig.argtypes), cases, - all_covered, joint_effects) + atype = argtypes_to_type(sig.argtypes) + atype === Union{} && return nothing # accidentally actually unreachable + handle_cases!(todo, ir, idx, stmt, atype, cases, all_covered, joint_effects) end function handle_match!(cases::Vector{InliningCase}, diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 6153765a713a4..da3b40c709079 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -2697,6 +2697,10 @@ function abstract_applicable(interp::AbstractInterpreter, argtypes::Vector{Any}, isvarargtype(argtypes[2]) && return CallMeta(Bool, EFFECTS_UNKNOWN, NoCallInfo()) argtypes = argtypes[2:end] atype = argtypes_to_type(argtypes) + if atype === Union{} + rt = Union{} # accidentally unreachable code + return CallMeta(rt, EFFECTS_TOTAL, NoCallInfo()) + end matches = find_matching_methods(typeinf_lattice(interp), argtypes, atype, method_table(interp), InferenceParams(interp).max_union_splitting, max_methods) if isa(matches, FailedMethodMatch) diff --git a/base/compiler/typeutils.jl b/base/compiler/typeutils.jl index 5479f835d4c5d..4d2a2c1a5015a 100644 --- a/base/compiler/typeutils.jl +++ b/base/compiler/typeutils.jl @@ -54,7 +54,12 @@ has_extended_info(@nospecialize x) = (!isa(x, Type) && !isvarargtype(x)) || isTy # certain combinations of `a` and `b` where one/both isa/are `Union`/`UnionAll` type(s)s. isnotbrokensubtype(@nospecialize(a), @nospecialize(b)) = (!iskindtype(b) || !isType(a) || hasuniquerep(a.parameters[1]) || b <: a) -argtypes_to_type(argtypes::Array{Any,1}) = Tuple{anymap(@nospecialize(a) -> isvarargtype(a) ? a : widenconst(a), argtypes)...} +function argtypes_to_type(argtypes::Array{Any,1}) + argtypes = anymap(@nospecialize(a) -> isvarargtype(a) ? a : widenconst(a), argtypes) + filter!(@nospecialize(x) -> !isvarargtype(x) || valid_as_lattice(unwrapva(x), true), argtypes) + all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), argtypes) || return Bottom + return Tuple{argtypes...} +end function isknownlength(t::DataType) isvatuple(t) || return true diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index a18b3f52a7685..916756eb6bfb7 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5193,3 +5193,9 @@ end @test only(Base.return_types((x,f) -> getfield(x, f), (An51317, Symbol))) === Int @test only(Base.return_types(x -> getfield(x, :b), (A51317,))) === Union{} @test only(Base.return_types(x -> getfield(x, :b), (An51317,))) === Union{} + +# issue #56628 +@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}} ]) === Tuple{Int, UnitRange{Int}} +@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}}, Float64 ]) === Tuple{Int, UnitRange{Int}, Float64} +@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}}, Float64, Tuple{2} ]) === Union{} +@test Base.return_types(Tuple{Tuple{Int, Vararg{Pair{Any, Union{}}}}},) do x; Returns(true)(x...); end |> only === Bool From 92f03a477583846bfbcc017c43ab7b1fdba53a98 Mon Sep 17 00:00:00 2001 From: Kristoffer Date: Thu, 20 Feb 2025 10:30:15 +0100 Subject: [PATCH 16/16] Revert "Make sure we don't promise alignments that are larger than the heap alignment to LLVM (#56938)" This reverts commit 09704c7ade881e1ccd7c741d456d02e7bd112349. --- src/codegen.cpp | 2 -- src/datatype.c | 2 -- test/compiler/codegen.jl | 6 ------ 3 files changed, 10 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 20a6240a926d0..1968050c3bd34 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7715,8 +7715,6 @@ static jl_llvm_functions_t Type *RT = Arg->getParamStructRetType(); TypeSize sz = DL.getTypeAllocSize(RT); Align al = DL.getPrefTypeAlign(RT); - if (al > MAX_ALIGN) - al = Align(MAX_ALIGN); param.addAttribute(Attribute::NonNull); // The `dereferenceable` below does not imply `nonnull` for non addrspace(0) pointers. param.addDereferenceableAttr(sz); diff --git a/src/datatype.c b/src/datatype.c index 3e8de1d59f33b..905959fb80e0a 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -648,8 +648,6 @@ void jl_compute_field_offsets(jl_datatype_t *st) if (al > alignm) alignm = al; } - if (alignm > MAX_ALIGN) - alignm = MAX_ALIGN; // We cannot guarantee alignments over 16 bytes because that's what our heap is aligned as if (LLT_ALIGN(sz, alignm) > sz) { haspadding = 1; sz = LLT_ALIGN(sz, alignm); diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 21cf2e8fca5db..00aae0e748bc9 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -873,9 +873,3 @@ end # Core.getptls() special handling @test !occursin("call ptr @jlplt", get_llvm(Core.getptls, Tuple{})) #It should lower to a direct load of the ptls and not a ccall - - -struct Vec56937 x::NTuple{8, VecElement{Int}} end - -x56937 = Ref(Vec56937(ntuple(_->VecElement(1),8))) -@test x56937[].x[1] == VecElement{Int}(1) # shouldn't crash