Skip to content

Commit ec2b509

Browse files
authored
Give undefined constants their own binding kind (#56968)
As noted in #56649 (comment), there needs to be a separate kind for undefined constants, so we know whether or not it is safe to call `partition_restriction`.
1 parent 22134ca commit ec2b509

File tree

6 files changed

+37
-14
lines changed

6 files changed

+37
-14
lines changed

Diff for: base/runtime_internals.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,12 @@ const BINDING_KIND_IMPORTED = 0x5
228228
const BINDING_KIND_FAILED = 0x6
229229
const BINDING_KIND_DECLARED = 0x7
230230
const BINDING_KIND_GUARD = 0x8
231+
const BINDING_KIND_UNDEF_CONST = 0x9
231232

232-
is_some_const_binding(kind::UInt8) = (kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT)
233+
is_defined_const_binding(kind::UInt8) = (kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT)
234+
is_some_const_binding(kind::UInt8) = (is_defined_const_binding(kind) || kind == BINDING_KIND_UNDEF_CONST)
233235
is_some_imported(kind::UInt8) = (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_EXPLICIT || kind == BINDING_KIND_IMPORTED)
234-
is_some_guard(kind::UInt8) = (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED)
236+
is_some_guard(kind::UInt8) = (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED || kind == BINDING_KIND_UNDEF_CONST)
235237

236238
function lookup_binding_partition(world::UInt, b::Core.Binding)
237239
ccall(:jl_get_binding_partition, Ref{Core.BindingPartition}, (Any, UInt), b, world)

Diff for: base/show.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,7 @@ function check_world_bounded(tn::Core.TypeName)
10451045
isdefined(bnd, :partitions) || return nothing
10461046
partition = @atomic bnd.partitions
10471047
while true
1048-
if is_some_const_binding(binding_kind(partition)) && partition_restriction(partition) <: tn.wrapper
1048+
if is_defined_const_binding(binding_kind(partition)) && partition_restriction(partition) <: tn.wrapper
10491049
max_world = @atomic partition.max_world
10501050
max_world == typemax(UInt) && return nothing
10511051
return Int(partition.min_world):Int(max_world)
@@ -3364,9 +3364,11 @@ function print_partition(io::IO, partition::Core.BindingPartition)
33643364
end
33653365
print(io, " - ")
33663366
kind = binding_kind(partition)
3367-
if is_some_const_binding(kind)
3367+
if is_defined_const_binding(kind)
33683368
print(io, "constant binding to ")
33693369
print(io, partition_restriction(partition))
3370+
elseif kind == BINDING_KIND_UNDEF_CONST
3371+
print(io, "undefined const binding")
33703372
elseif kind == BINDING_KIND_GUARD
33713373
print(io, "undefined binding - guard entry")
33723374
elseif kind == BINDING_KIND_FAILED

Diff for: src/julia.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ typedef struct _jl_weakref_t {
623623

624624
// N.B: Needs to be synced with runtime_internals.jl
625625
enum jl_partition_kind {
626-
// Constant: This binding partition is a constant declared using `const`
626+
// Constant: This binding partition is a constant declared using `const _ = ...`
627627
// ->restriction holds the constant value
628628
BINDING_KIND_CONST = 0x0,
629629
// Import Constant: This binding partition is a constant declared using `import A`
@@ -649,7 +649,11 @@ enum jl_partition_kind {
649649
BINDING_KIND_DECLARED = 0x7,
650650
// Guard: The binding was looked at, but no global or import was resolved at the time
651651
// ->restriction is NULL.
652-
BINDING_KIND_GUARD = 0x8
652+
BINDING_KIND_GUARD = 0x8,
653+
// Undef Constant: This binding partition is a constant declared using `const`, but
654+
// without a value.
655+
// ->restriction is NULL
656+
BINDING_KIND_UNDEF_CONST = 0x9
653657
};
654658

655659
#ifdef _P64

Diff for: src/julia_internal.h

+16-3
Original file line numberDiff line numberDiff line change
@@ -924,8 +924,13 @@ EXTERN_INLINE_DECLARE enum jl_partition_kind decode_restriction_kind(jl_ptr_kind
924924
uint8_t bits = (pku & 0x7);
925925
jl_value_t *val = (jl_value_t*)(pku & ~0x7);
926926

927-
if (val == NULL && bits == BINDING_KIND_IMPLICIT) {
928-
return BINDING_KIND_GUARD;
927+
if (val == NULL) {
928+
if (bits == BINDING_KIND_IMPLICIT) {
929+
return BINDING_KIND_GUARD;
930+
}
931+
if (bits == BINDING_KIND_CONST) {
932+
return BINDING_KIND_UNDEF_CONST;
933+
}
929934
}
930935

931936
return (enum jl_partition_kind)bits;
@@ -947,10 +952,14 @@ STATIC_INLINE jl_value_t *decode_restriction_value(jl_ptr_kind_union_t JL_PROPAG
947952
STATIC_INLINE jl_ptr_kind_union_t encode_restriction(jl_value_t *val, enum jl_partition_kind kind) JL_NOTSAFEPOINT
948953
{
949954
#ifdef _P64
950-
if (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED)
955+
if (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED || kind == BINDING_KIND_UNDEF_CONST)
951956
assert(val == NULL);
957+
else if (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_CONST)
958+
assert(val != NULL);
952959
if (kind == BINDING_KIND_GUARD)
953960
kind = BINDING_KIND_IMPLICIT;
961+
else if (kind == BINDING_KIND_UNDEF_CONST)
962+
kind = BINDING_KIND_CONST;
954963
assert((((uintptr_t)val) & 0x7) == 0);
955964
return ((jl_ptr_kind_union_t)val) | kind;
956965
#else
@@ -964,6 +973,10 @@ STATIC_INLINE int jl_bkind_is_some_import(enum jl_partition_kind kind) JL_NOTSAF
964973
}
965974

966975
STATIC_INLINE int jl_bkind_is_some_constant(enum jl_partition_kind kind) JL_NOTSAFEPOINT {
976+
return kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT || kind == BINDING_KIND_UNDEF_CONST;
977+
}
978+
979+
STATIC_INLINE int jl_bkind_is_defined_constant(enum jl_partition_kind kind) JL_NOTSAFEPOINT {
967980
return kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT;
968981
}
969982

Diff for: src/module.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,10 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_resolved(jl_binding_t *b)
400400
JL_DLLEXPORT jl_value_t *jl_bpart_get_restriction_value(jl_binding_partition_t *bpart)
401401
{
402402
jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
403-
return decode_restriction_value(pku);
403+
jl_value_t *v = decode_restriction_value(pku);
404+
if (!v)
405+
jl_throw(jl_undefref_exception);
406+
return v;
404407
}
405408

406409
typedef struct _modstack_t {

Diff for: src/toplevel.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex
157157
else {
158158
jl_binding_t *b = jl_get_module_binding(parent_module, name, 1);
159159
jl_binding_partition_t *bpart = jl_get_binding_partition(b, ct->world_age);
160-
jl_ptr_kind_union_t pku = encode_restriction(NULL, BINDING_KIND_CONST);
160+
jl_ptr_kind_union_t pku = encode_restriction(NULL, BINDING_KIND_UNDEF_CONST);
161161
jl_ptr_kind_union_t new_pku = encode_restriction((jl_value_t*)newm, BINDING_KIND_CONST);
162162
if (!jl_atomic_cmpswap(&bpart->restriction, &pku, new_pku)) {
163163
if (decode_restriction_kind(pku) != BINDING_KIND_CONST) {
@@ -749,8 +749,7 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val2(jl_binding_t *b, j
749749
while (1) {
750750
if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
751751
if (!val) {
752-
JL_GC_POP();
753-
return bpart;
752+
break;
754753
}
755754
jl_value_t *old = decode_restriction_value(pku);
756755
JL_GC_PROMISE_ROOTED(old);
@@ -787,7 +786,7 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val2(jl_binding_t *b, j
787786

788787
JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *val)
789788
{
790-
return jl_declare_constant_val2(b, mod, var, val, BINDING_KIND_CONST);
789+
return jl_declare_constant_val2(b, mod, var, val, val ? BINDING_KIND_CONST : BINDING_KIND_UNDEF_CONST);
791790
}
792791

793792
JL_DLLEXPORT void jl_eval_const_decl(jl_module_t *m, jl_value_t *arg, jl_value_t *val)

0 commit comments

Comments
 (0)