diff --git a/base/runtime_internals.jl b/base/runtime_internals.jl index 13c467667c51e..67694e533ac47 100644 --- a/base/runtime_internals.jl +++ b/base/runtime_internals.jl @@ -228,10 +228,12 @@ const BINDING_KIND_IMPORTED = 0x5 const BINDING_KIND_FAILED = 0x6 const BINDING_KIND_DECLARED = 0x7 const BINDING_KIND_GUARD = 0x8 +const BINDING_KIND_UNDEF_CONST = 0x9 -is_some_const_binding(kind::UInt8) = (kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT) +is_defined_const_binding(kind::UInt8) = (kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT) +is_some_const_binding(kind::UInt8) = (is_defined_const_binding(kind) || kind == BINDING_KIND_UNDEF_CONST) is_some_imported(kind::UInt8) = (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_EXPLICIT || kind == BINDING_KIND_IMPORTED) -is_some_guard(kind::UInt8) = (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED) +is_some_guard(kind::UInt8) = (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED || kind == BINDING_KIND_UNDEF_CONST) function lookup_binding_partition(world::UInt, b::Core.Binding) ccall(:jl_get_binding_partition, Ref{Core.BindingPartition}, (Any, UInt), b, world) diff --git a/base/show.jl b/base/show.jl index 381c0e7d1480a..de45ca07e3131 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1045,7 +1045,7 @@ function check_world_bounded(tn::Core.TypeName) isdefined(bnd, :partitions) || return nothing partition = @atomic bnd.partitions while true - if is_some_const_binding(binding_kind(partition)) && partition_restriction(partition) <: tn.wrapper + if is_defined_const_binding(binding_kind(partition)) && partition_restriction(partition) <: tn.wrapper max_world = @atomic partition.max_world max_world == typemax(UInt) && return nothing return Int(partition.min_world):Int(max_world) @@ -3364,9 +3364,11 @@ function print_partition(io::IO, partition::Core.BindingPartition) end print(io, " - ") kind = binding_kind(partition) - if is_some_const_binding(kind) + if is_defined_const_binding(kind) print(io, "constant binding to ") print(io, partition_restriction(partition)) + elseif kind == BINDING_KIND_UNDEF_CONST + print(io, "undefined const binding") elseif kind == BINDING_KIND_GUARD print(io, "undefined binding - guard entry") elseif kind == BINDING_KIND_FAILED diff --git a/src/julia.h b/src/julia.h index 5cafc9bfa5232..bfa9d0857c73c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -623,7 +623,7 @@ typedef struct _jl_weakref_t { // N.B: Needs to be synced with runtime_internals.jl enum jl_partition_kind { - // Constant: This binding partition is a constant declared using `const` + // Constant: This binding partition is a constant declared using `const _ = ...` // ->restriction holds the constant value BINDING_KIND_CONST = 0x0, // Import Constant: This binding partition is a constant declared using `import A` @@ -649,7 +649,11 @@ enum jl_partition_kind { BINDING_KIND_DECLARED = 0x7, // Guard: The binding was looked at, but no global or import was resolved at the time // ->restriction is NULL. - BINDING_KIND_GUARD = 0x8 + BINDING_KIND_GUARD = 0x8, + // Undef Constant: This binding partition is a constant declared using `const`, but + // without a value. + // ->restriction is NULL + BINDING_KIND_UNDEF_CONST = 0x9 }; #ifdef _P64 diff --git a/src/julia_internal.h b/src/julia_internal.h index 00103e9b00a48..917577eb1c7c8 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -923,8 +923,13 @@ EXTERN_INLINE_DECLARE enum jl_partition_kind decode_restriction_kind(jl_ptr_kind uint8_t bits = (pku & 0x7); jl_value_t *val = (jl_value_t*)(pku & ~0x7); - if (val == NULL && bits == BINDING_KIND_IMPLICIT) { - return BINDING_KIND_GUARD; + if (val == NULL) { + if (bits == BINDING_KIND_IMPLICIT) { + return BINDING_KIND_GUARD; + } + if (bits == BINDING_KIND_CONST) { + return BINDING_KIND_UNDEF_CONST; + } } return (enum jl_partition_kind)bits; @@ -946,10 +951,14 @@ STATIC_INLINE jl_value_t *decode_restriction_value(jl_ptr_kind_union_t JL_PROPAG STATIC_INLINE jl_ptr_kind_union_t encode_restriction(jl_value_t *val, enum jl_partition_kind kind) JL_NOTSAFEPOINT { #ifdef _P64 - if (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED) + if (kind == BINDING_KIND_GUARD || kind == BINDING_KIND_DECLARED || kind == BINDING_KIND_FAILED || kind == BINDING_KIND_UNDEF_CONST) assert(val == NULL); + else if (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_CONST) + assert(val != NULL); if (kind == BINDING_KIND_GUARD) kind = BINDING_KIND_IMPLICIT; + else if (kind == BINDING_KIND_UNDEF_CONST) + kind = BINDING_KIND_CONST; assert((((uintptr_t)val) & 0x7) == 0); return ((jl_ptr_kind_union_t)val) | kind; #else @@ -963,6 +972,10 @@ STATIC_INLINE int jl_bkind_is_some_import(enum jl_partition_kind kind) JL_NOTSAF } STATIC_INLINE int jl_bkind_is_some_constant(enum jl_partition_kind kind) JL_NOTSAFEPOINT { + return kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT || kind == BINDING_KIND_UNDEF_CONST; +} + +STATIC_INLINE int jl_bkind_is_defined_constant(enum jl_partition_kind kind) JL_NOTSAFEPOINT { return kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT; } diff --git a/src/module.c b/src/module.c index 38f4b980a72fd..37d7519bd567c 100644 --- a/src/module.c +++ b/src/module.c @@ -396,7 +396,10 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_value_if_resolved(jl_binding_t *b) JL_DLLEXPORT jl_value_t *jl_bpart_get_restriction_value(jl_binding_partition_t *bpart) { jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction); - return decode_restriction_value(pku); + jl_value_t *v = decode_restriction_value(pku); + if (!v) + jl_throw(jl_undefref_exception); + return v; } typedef struct _modstack_t { diff --git a/src/toplevel.c b/src/toplevel.c index 11e1f9ad521a1..0f8fae8939faf 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -157,7 +157,7 @@ static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex else { jl_binding_t *b = jl_get_module_binding(parent_module, name, 1); jl_binding_partition_t *bpart = jl_get_binding_partition(b, ct->world_age); - jl_ptr_kind_union_t pku = encode_restriction(NULL, BINDING_KIND_CONST); + jl_ptr_kind_union_t pku = encode_restriction(NULL, BINDING_KIND_UNDEF_CONST); jl_ptr_kind_union_t new_pku = encode_restriction((jl_value_t*)newm, BINDING_KIND_CONST); if (!jl_atomic_cmpswap(&bpart->restriction, &pku, new_pku)) { 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 while (1) { if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) { if (!val) { - JL_GC_POP(); - return bpart; + break; } jl_value_t *old = decode_restriction_value(pku); JL_GC_PROMISE_ROOTED(old); @@ -787,7 +786,7 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val2(jl_binding_t *b, j 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) { - return jl_declare_constant_val2(b, mod, var, val, BINDING_KIND_CONST); + return jl_declare_constant_val2(b, mod, var, val, val ? BINDING_KIND_CONST : BINDING_KIND_UNDEF_CONST); } JL_DLLEXPORT void jl_eval_const_decl(jl_module_t *m, jl_value_t *arg, jl_value_t *val)