Skip to content

Commit c1f5037

Browse files
committed
bpart: Give a warning when accessing a backdated const binding
This implements the strategy proposed in #57102 (comment). Example: ``` julia> function foo(i) eval(:(const x = $i)) x end foo (generic function with 1 method) julia> foo(1) WARNING: Detected access to binding Main.x in a world prior to its definition world. Julia 1.12 has introduced more strict world age semantics for global bindings. !!! This code may malfunction under Revise. !!! This code will error in future versions of Julia. Hint: Add an appropriate `invokelatest` around the access to this binding. 1 ``` The warning is triggered once per binding to avoid spamming for repeated access.
1 parent 61e8f1d commit c1f5037

15 files changed

+114
-45
lines changed

Compiler/src/Compiler.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ using Core: ABIOverride, Builtin, CodeInstance, IntrinsicFunction, MethodInstanc
4949

5050
using Base
5151
using Base: @_foldable_meta, @_gc_preserve_begin, @_gc_preserve_end, @nospecializeinfer,
52-
BINDING_KIND_GLOBAL, BINDING_KIND_UNDEF_CONST, Base, BitVector, Bottom, Callable, DataTypeFieldDesc,
52+
BINDING_KIND_GLOBAL, BINDING_KIND_UNDEF_CONST, BINDING_KIND_BACKDATED_CONST,
53+
Base, BitVector, Bottom, Callable, DataTypeFieldDesc,
5354
EffectsOverride, Filter, Generator, IteratorSize, JLOptions, NUM_EFFECTS_OVERRIDES,
5455
OneTo, Ordering, RefValue, SizeUnknown, _NAMEDTUPLE_NAME,
5556
_array_for, _bits_findnext, _methods_by_ftype, _uniontypes, all, allocatedinline, any,

Compiler/src/abstractinterpretation.jl

+5
Original file line numberDiff line numberDiff line change
@@ -3524,6 +3524,11 @@ function abstract_eval_partition_load(interp::AbstractInterpreter, partition::Co
35243524
end
35253525

35263526
if is_defined_const_binding(kind)
3527+
if kind == BINDING_KIND_BACKDATED_CONST
3528+
# Infer this as guard. We do not want a later const definition to retroactively improve
3529+
# inference results in an earlier world.
3530+
return RTEffects(Any, UndefVarError, generic_getglobal_effects)
3531+
end
35273532
rt = Const(partition_restriction(partition))
35283533
return RTEffects(rt, Union{}, Effects(EFFECTS_TOTAL, inaccessiblememonly=is_mutation_free_argtype(rt) ? ALWAYS_TRUE : ALWAYS_FALSE))
35293534
end

Compiler/src/ssair/slot2ssa.jl

-4
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ function fixemup!(@specialize(slot_filter), @specialize(rename_slot), ir::IRCode
137137
return nothing
138138
end
139139
op[] = x
140-
elseif isa(val, GlobalRef) && !(isdefined(val.mod, val.name) && isconst(val.mod, val.name))
141-
typ = typ_for_val(val, ci, ir, idx, Any[])
142-
new_inst = NewInstruction(val, typ)
143-
op[] = NewSSAValue(insert_node!(ir, idx, new_inst).id - length(ir.stmts))
144140
elseif isexpr(val, :static_parameter)
145141
ty = typ_for_val(val, ci, ir, idx, Any[])
146142
if isa(ty, Const)

Compiler/test/invalidation.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ let mi = Base.method_instance(basic_caller, (Float64,))
5555
end
5656

5757
# this redefinition below should invalidate the cache
58-
const BASIC_CALLER_WORLD = Base.get_world_counter()
58+
const BASIC_CALLER_WORLD = Base.get_world_counter()+1
5959
basic_callee(x) = x, x
6060
@test !isdefined(Base.method_instance(basic_callee, (Float64,)), :cache)
6161
let mi = Base.method_instance(basic_caller, (Float64,))

base/Base_compiler.jl

+4
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ using .Order
257257
include("coreir.jl")
258258
include("invalidation.jl")
259259

260+
# Because lowering inserts direct references, it is mandatory for this binding
261+
# to exist before we start inferring code.
262+
function string end
263+
260264
# For OS specific stuff
261265
# We need to strcat things here, before strings are really defined
262266
function strcat(x::String, y::String)

base/boot.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,8 @@ macro __doc__(x)
717717
end
718718

719719
isbasicdoc(@nospecialize x) = (isa(x, Expr) && x.head === :.) || isa(x, Union{QuoteNode, Symbol})
720-
iscallexpr(ex::Expr) = (isa(ex, Expr) && ex.head === :where) ? iscallexpr(ex.args[1]) : (isa(ex, Expr) && ex.head === :call)
720+
firstarg(arg1, args...) = arg1
721+
iscallexpr(ex::Expr) = (isa(ex, Expr) && ex.head === :where) ? iscallexpr(firstarg(ex.args...)) : (isa(ex, Expr) && ex.head === :call)
721722
iscallexpr(ex) = false
722723
function ignoredoc(source, mod, str, expr)
723724
(isbasicdoc(expr) || iscallexpr(expr)) && return Expr(:escape, nothing)

base/docs/bindings.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ end
1616

1717
bindingexpr(x) = Expr(:call, Binding, splitexpr(x)...)
1818

19-
defined(b::Binding) = isdefined(b.mod, b.var)
20-
resolve(b::Binding) = getfield(b.mod, b.var)
19+
defined(b::Binding) = invokelatest(isdefined, b.mod, b.var)
20+
resolve(b::Binding) = invokelatest(getfield, b.mod, b.var)
2121

2222
function splitexpr(x::Expr)
2323
isexpr(x, :macrocall) ? splitexpr(x.args[1]) :

base/runtime_internals.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ const BINDING_KIND_FAILED = 0x6
229229
const BINDING_KIND_DECLARED = 0x7
230230
const BINDING_KIND_GUARD = 0x8
231231
const BINDING_KIND_UNDEF_CONST = 0x9
232+
const BINDING_KIND_BACKDATED_CONST = 0xa
232233

233-
is_defined_const_binding(kind::UInt8) = (kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT)
234+
is_defined_const_binding(kind::UInt8) = (kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT || kind == BINDING_KIND_BACKDATED_CONST)
234235
is_some_const_binding(kind::UInt8) = (is_defined_const_binding(kind) || kind == BINDING_KIND_UNDEF_CONST)
235236
is_some_imported(kind::UInt8) = (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_EXPLICIT || kind == BINDING_KIND_IMPORTED)
236237
is_some_guard(kind::UInt8) = (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED || kind == BINDING_KIND_UNDEF_CONST)

base/show.jl

+9-6
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,8 @@ function show_function(io::IO, f::Function, compact::Bool, fallback::Function)
542542
fallback(io, f)
543543
elseif compact
544544
print(io, mt.name)
545-
elseif isdefined(mt, :module) && isdefined(mt.module, mt.name) &&
546-
getfield(mt.module, mt.name) === f
545+
elseif isdefined(mt, :module) && isdefinedglobal(mt.module, mt.name) &&
546+
getglobal(mt.module, mt.name) === f
547547
# this used to call the removed internal function `is_exported_from_stdlib`, which effectively
548548
# just checked for exports from Core and Base.
549549
mod = get(io, :module, UsesCoreAndBaseOnly)
@@ -1025,15 +1025,15 @@ function isvisible(sym::Symbol, parent::Module, from::Module)
10251025
from_owner = ccall(:jl_binding_owner, Ptr{Cvoid}, (Any, Any), from, sym)
10261026
return owner !== C_NULL && from_owner === owner &&
10271027
!isdeprecated(parent, sym) &&
1028-
isdefined(from, sym) # if we're going to return true, force binding resolution
1028+
isdefinedglobal(from, sym) # if we're going to return true, force binding resolution
10291029
end
10301030

10311031
function is_global_function(tn::Core.TypeName, globname::Union{Symbol,Nothing})
10321032
if globname !== nothing
10331033
globname_str = string(globname::Symbol)
10341034
if ('#' globname_str && '@' globname_str && isdefined(tn, :module) &&
1035-
isbindingresolved(tn.module, globname) && isdefined(tn.module, globname) &&
1036-
isconcretetype(tn.wrapper) && isa(getfield(tn.module, globname), tn.wrapper))
1035+
isbindingresolved(tn.module, globname) && isdefinedglobal(tn.module, globname) &&
1036+
isconcretetype(tn.wrapper) && isa(getglobal(tn.module, globname), tn.wrapper))
10371037
return true
10381038
end
10391039
end
@@ -3364,7 +3364,10 @@ function print_partition(io::IO, partition::Core.BindingPartition)
33643364
end
33653365
print(io, " - ")
33663366
kind = binding_kind(partition)
3367-
if is_defined_const_binding(kind)
3367+
if kind == BINDING_KIND_BACKDATED_CONST
3368+
print(io, "backdated constant binding to ")
3369+
print(io, partition_restriction(partition))
3370+
elseif is_defined_const_binding(kind)
33683371
print(io, "constant binding to ")
33693372
print(io, partition_restriction(partition))
33703373
elseif kind == BINDING_KIND_UNDEF_CONST

src/codegen.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -3467,7 +3467,8 @@ static jl_cgval_t emit_globalref(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *
34673467
break;
34683468
pku = jl_atomic_load_acquire(&bpart->restriction);
34693469
}
3470-
if (bpart && jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
3470+
enum jl_partition_kind kind = decode_restriction_kind(pku);
3471+
if (bpart && (jl_bkind_is_some_constant(kind) && kind != BINDING_KIND_BACKDATED_CONST)) {
34713472
jl_value_t *constval = decode_restriction_value(pku);
34723473
if (!constval) {
34733474
undef_var_error_ifnot(ctx, ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0), name, (jl_value_t*)mod);

src/julia.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,10 @@ enum jl_partition_kind {
647647
// Undef Constant: This binding partition is a constant declared using `const`, but
648648
// without a value.
649649
// ->restriction is NULL
650-
BINDING_KIND_UNDEF_CONST = 0x9
650+
BINDING_KIND_UNDEF_CONST = 0x9,
651+
// Backated constant. A constant that was backdated for compatibility. In all other
652+
// ways equivalent to BINDING_KIND_CONST, but prints a warning on access
653+
BINDING_KIND_BACKDATED_CONST = 0xa,
651654
};
652655

653656
#ifdef _P64
@@ -693,7 +696,7 @@ typedef struct _jl_binding_t {
693696
jl_globalref_t *globalref; // cached GlobalRef for this binding
694697
_Atomic(jl_value_t*) value;
695698
_Atomic(jl_binding_partition_t*) partitions;
696-
uint8_t declared:1;
699+
uint8_t did_print_backdate_admonition:1;
697700
uint8_t exportp:1; // `public foo` sets `publicp`, `export foo` sets both `publicp` and `exportp`
698701
uint8_t publicp:1; // exportp without publicp is not allowed.
699702
uint8_t deprecated:2; // 0=not deprecated, 1=renamed, 2=moved to another package

src/julia_internal.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,10 @@ EXTERN_INLINE_DECLARE enum jl_partition_kind decode_restriction_kind(jl_ptr_kind
933933
if (bits == BINDING_KIND_CONST) {
934934
return BINDING_KIND_UNDEF_CONST;
935935
}
936+
} else {
937+
if (bits == BINDING_KIND_DECLARED) {
938+
return BINDING_KIND_BACKDATED_CONST;
939+
}
936940
}
937941

938942
return (enum jl_partition_kind)bits;
@@ -956,12 +960,14 @@ STATIC_INLINE jl_ptr_kind_union_t encode_restriction(jl_value_t *val, enum jl_pa
956960
#ifdef _P64
957961
if (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED || kind == BINDING_KIND_UNDEF_CONST)
958962
assert(val == NULL);
959-
else if (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_CONST)
963+
else if (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_CONST || kind == BINDING_KIND_BACKDATED_CONST)
960964
assert(val != NULL);
961965
if (kind == BINDING_KIND_GUARD)
962966
kind = BINDING_KIND_IMPLICIT;
963967
else if (kind == BINDING_KIND_UNDEF_CONST)
964968
kind = BINDING_KIND_CONST;
969+
else if (kind == BINDING_KIND_BACKDATED_CONST)
970+
kind = BINDING_KIND_DECLARED;
965971
assert((((uintptr_t)val) & 0x7) == 0);
966972
return ((jl_ptr_kind_union_t)val) | kind;
967973
#else
@@ -975,7 +981,7 @@ STATIC_INLINE int jl_bkind_is_some_import(enum jl_partition_kind kind) JL_NOTSAF
975981
}
976982

977983
STATIC_INLINE int jl_bkind_is_some_constant(enum jl_partition_kind kind) JL_NOTSAFEPOINT {
978-
return kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT || kind == BINDING_KIND_UNDEF_CONST;
984+
return kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT || kind == BINDING_KIND_UNDEF_CONST || kind == BINDING_KIND_BACKDATED_CONST;
979985
}
980986

981987
STATIC_INLINE int jl_bkind_is_defined_constant(enum jl_partition_kind kind) JL_NOTSAFEPOINT {

src/module.c

+62-15
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ static jl_binding_t *new_binding(jl_module_t *mod, jl_sym_t *name)
241241
b->exportp = 0;
242242
b->publicp = 0;
243243
b->deprecated = 0;
244+
b->did_print_backdate_admonition = 0;
244245
JL_GC_PUSH1(&b);
245246
b->globalref = jl_new_globalref(mod, name, b);
246247
jl_gc_wb(b, b->globalref);
@@ -322,36 +323,64 @@ JL_DLLEXPORT jl_module_t *jl_get_module_of_binding(jl_module_t *m, jl_sym_t *var
322323
return b->globalref->mod; // TODO: deprecate this?
323324
}
324325

326+
static NOINLINE void print_backdate_admonition(jl_binding_t *b)
327+
{
328+
jl_printf(JL_STDERR,
329+
"WARNING: Detected access to binding `%s.%s` in a world prior to its definition world.\n"
330+
" Julia 1.12 has introduced more strict world age semantics for global bindings.\n"
331+
" !!! This code may malfunction under Revise.\n"
332+
" !!! This code will error in future versions of Julia.\n"
333+
"Hint: Add an appropriate `invokelatest` around the access to this binding.\n",
334+
jl_symbol_name(b->globalref->mod->name), jl_symbol_name(b->globalref->name));
335+
b->did_print_backdate_admonition = 1;
336+
}
337+
338+
static inline void check_backdated_binding(jl_binding_t *b, enum jl_partition_kind kind)
339+
{
340+
if (__unlikely(kind == BINDING_KIND_BACKDATED_CONST) &&
341+
!b->did_print_backdate_admonition) {
342+
print_backdate_admonition(b);
343+
}
344+
}
345+
325346
JL_DLLEXPORT jl_value_t *jl_get_binding_value(jl_binding_t *b)
326347
{
327348
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
328349
jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age);
329-
if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
350+
enum jl_partition_kind kind = decode_restriction_kind(pku);
351+
if (jl_bkind_is_some_guard(kind))
330352
return NULL;
331-
if (jl_bkind_is_some_constant(decode_restriction_kind(pku)))
353+
if (jl_bkind_is_some_constant(kind)) {
354+
check_backdated_binding(b, kind);
332355
return decode_restriction_value(pku);
356+
}
333357
return jl_atomic_load_relaxed(&b->value);
334358
}
335359

336360
JL_DLLEXPORT jl_value_t *jl_get_binding_value_seqcst(jl_binding_t *b)
337361
{
338362
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
339363
jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age);
340-
if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
364+
enum jl_partition_kind kind = decode_restriction_kind(pku);
365+
if (jl_bkind_is_some_guard(kind))
341366
return NULL;
342-
if (jl_bkind_is_some_constant(decode_restriction_kind(pku)))
367+
if (jl_bkind_is_some_constant(kind)) {
368+
check_backdated_binding(b, kind);
343369
return decode_restriction_value(pku);
370+
}
344371
return jl_atomic_load(&b->value);
345372
}
346373

347374
JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_const(jl_binding_t *b)
348375
{
349376
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
350377
jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age);
351-
if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
378+
enum jl_partition_kind kind = decode_restriction_kind(pku);
379+
if (jl_bkind_is_some_guard(kind))
352380
return NULL;
353-
if (!jl_bkind_is_some_constant(decode_restriction_kind(pku)))
381+
if (!jl_bkind_is_some_constant(kind))
354382
return NULL;
383+
check_backdated_binding(b, kind);
355384
return decode_restriction_value(pku);
356385
}
357386

@@ -368,10 +397,12 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_resolved_and_const(jl_binding_t
368397
if (bpart->min_world > jl_current_task->world_age || jl_current_task->world_age > max_world)
369398
return NULL;
370399
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
371-
if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
400+
enum jl_partition_kind kind = decode_restriction_kind(pku);
401+
if (jl_bkind_is_some_guard(kind))
372402
return NULL;
373-
if (!jl_bkind_is_some_constant(decode_restriction_kind(pku)))
403+
if (!jl_bkind_is_some_constant(kind))
374404
return NULL;
405+
check_backdated_binding(b, kind);
375406
return decode_restriction_value(pku);
376407
}
377408

@@ -388,12 +419,15 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_resolved(jl_binding_t *b)
388419
if (bpart->min_world > jl_current_task->world_age || jl_current_task->world_age > max_world)
389420
return NULL;
390421
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
391-
if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
422+
enum jl_partition_kind kind = decode_restriction_kind(pku);
423+
if (jl_bkind_is_some_guard(kind))
392424
return NULL;
393-
if (jl_bkind_is_some_import(decode_restriction_kind(pku)))
425+
if (jl_bkind_is_some_import(kind))
394426
return NULL;
395-
if (jl_bkind_is_some_constant(decode_restriction_kind(pku)))
427+
if (jl_bkind_is_some_constant(kind)) {
428+
check_backdated_binding(b, kind);
396429
return decode_restriction_value(pku);
430+
}
397431
return jl_atomic_load_relaxed(&b->value);
398432
}
399433

@@ -895,13 +929,26 @@ JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var, int allow_import) // u
895929
jl_binding_t *b = jl_get_module_binding(m, var, allow_import);
896930
if (!b)
897931
return 0;
932+
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
933+
if (!bpart)
934+
return 0;
935+
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
898936
if (!allow_import) {
899-
jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
900-
if (!bpart || jl_bkind_is_some_import(decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction))))
937+
if (!bpart || jl_bkind_is_some_import(decode_restriction_kind(pku)))
901938
return 0;
902-
return jl_get_binding_value(b) != NULL;
939+
} else {
940+
if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) {
941+
jl_resolve_owner(b, b->globalref->mod, b->globalref->name, NULL, jl_current_task->world_age);
942+
}
943+
pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age);
944+
}
945+
if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
946+
return 0;
947+
if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
948+
// N.B.: No backdated check for isdefined
949+
return 1;
903950
}
904-
return jl_reresolve_binding_value_seqcst(b) != NULL;
951+
return jl_atomic_load(&b->value) != NULL;
905952
}
906953

907954
JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var)

src/toplevel.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ static void import_module(jl_module_t *JL_NONNULL m, jl_module_t *import, jl_sym
669669
if (decode_restriction_kind(pku) != BINDING_KIND_GUARD && decode_restriction_kind(pku) != BINDING_KIND_FAILED) {
670670
// Unlike regular constant declaration, we allow this as long as we eventually end up at a constant.
671671
pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age);
672-
if (decode_restriction_kind(pku) == BINDING_KIND_CONST || decode_restriction_kind(pku) == BINDING_KIND_CONST_IMPORT) {
672+
if (decode_restriction_kind(pku) == BINDING_KIND_CONST || decode_restriction_kind(pku) == BINDING_KIND_BACKDATED_CONST || decode_restriction_kind(pku) == BINDING_KIND_CONST_IMPORT) {
673673
// Already declared (e.g. on another thread) or imported.
674674
if (decode_restriction_value(pku) == (jl_value_t*)import)
675675
return;
@@ -784,10 +784,11 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3(
784784
break;
785785
}
786786
}
787-
// N.B.: This backdates the first definition of the constant to world age 0 for backwards compatibility
788-
// TODO: Mark this specially with a separate partition.
789-
if (bpart->min_world != 0)
790-
bpart->min_world = new_world;
787+
int needs_backdate = bpart->min_world == 0 && new_world;
788+
bpart->min_world = new_world;
789+
if (needs_backdate) {
790+
jl_declare_constant_val3(b, mod, var, val, BINDING_KIND_BACKDATED_CONST, 0);
791+
}
791792
JL_GC_POP();
792793
return bpart;
793794
}

test/worlds.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,15 @@ wc265_41332a = Task(tls_world_age)
115115
global wc265_41332d = Task(tls_world_age)
116116
nothing
117117
end)()
118-
@test wc265 + 3 == get_world_counter() == tls_world_age()
118+
@test wc265 + 4 == get_world_counter() == tls_world_age()
119119
schedule(wc265_41332a)
120120
schedule(wc265_41332b)
121121
schedule(wc265_41332c)
122122
schedule(wc265_41332d)
123123
@test wc265 == fetch(wc265_41332a)
124-
@test wc265 + 1 == fetch(wc265_41332b)
125-
@test wc265 + 3 == fetch(wc265_41332c)
126-
@test wc265 + 1 == fetch(wc265_41332d)
124+
@test wc265 + 2 == fetch(wc265_41332b)
125+
@test wc265 + 4 == fetch(wc265_41332c)
126+
@test wc265 + 2 == fetch(wc265_41332d)
127127
chnls, tasks = Base.channeled_tasks(2, wfunc)
128128
t265 = tasks[1]
129129

0 commit comments

Comments
 (0)