diff --git a/Compiler/test/abioverride.jl b/Compiler/test/abioverride.jl
index 49907ea8e4c63..feb992b27ee43 100644
--- a/Compiler/test/abioverride.jl
+++ b/Compiler/test/abioverride.jl
@@ -46,7 +46,7 @@ let world = Base.tls_world_age()
     global new_ci = Core.CodeInstance(Core.ABIOverride(Tuple{typeof(myplus), Int}, mi),
         #=owner=#SecondArgConstOverride(1), new_source.rettype, Any#=new_source.exctype is missing=#,
         #=inferred_const=#nothing, #=code=#nothing, #=const_flags=#Int32(0),
-        new_source.min_world, new_source.max_world, #=new_source.ipo_purity_bits is missing=#UInt32(0),
+        new_source.min_world, typemax(UInt), #=new_source.ipo_purity_bits is missing=#UInt32(0),
         #=analysis_results=#nothing, new_source.debuginfo, new_source.edges)
 
     # Poke the CI into the global cache
diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl
index 61c0cf71e70c2..061a94bffd9cf 100644
--- a/base/docs/Docs.jl
+++ b/base/docs/Docs.jl
@@ -75,18 +75,23 @@ const META    = gensym(:meta)
 const METAType = IdDict{Any,Any}
 
 function meta(m::Module; autoinit::Bool=true)
-    if !isdefined(m, META) || getfield(m, META) === nothing
-        autoinit ? initmeta(m) : return nothing
+    if !isdefinedglobal(m, META)
+        return autoinit ? invokelatest(initmeta, m) : nothing
     end
-    return getfield(m, META)::METAType
+    # TODO: This `invokelatest` is not technically required, but because
+    # of the automatic constant backdating is currently required to avoid
+    # a warning.
+    return invokelatest(getglobal, m, META)::METAType
 end
 
 function initmeta(m::Module)
-    if !isdefined(m, META) || getfield(m, META) === nothing
-        Core.eval(m, :($META = $(METAType())))
+    if !isdefinedglobal(m, META)
+        val = METAType()
+        Core.eval(m, :(const $META = $val))
         push!(modules, m)
+        return val
     end
-    nothing
+    return getglobal(m, META)
 end
 
 function signature!(tv::Vector{Any}, expr::Expr)
diff --git a/base/exports.jl b/base/exports.jl
index 56cd58ce269e7..d81067478dd55 100644
--- a/base/exports.jl
+++ b/base/exports.jl
@@ -818,6 +818,7 @@ export
     @invoke,
     invokelatest,
     @invokelatest,
+    @world,
 
 # loading source files
     __precompile__,
diff --git a/base/loading.jl b/base/loading.jl
index 240406292246b..57d69f49483c9 100644
--- a/base/loading.jl
+++ b/base/loading.jl
@@ -1389,7 +1389,7 @@ function register_restored_modules(sv::SimpleVector, pkg::PkgId, path::String)
     restored = sv[1]::Vector{Any}
     for M in restored
         M = M::Module
-        if isdefined(M, Base.Docs.META) && getfield(M, Base.Docs.META) !== nothing
+        if isdefinedglobal(M, Base.Docs.META)
             push!(Base.Docs.modules, M)
         end
         if is_root_module(M)
diff --git a/src/builtins.c b/src/builtins.c
index 90d8a0d453e20..f67ef65d35356 100644
--- a/src/builtins.c
+++ b/src/builtins.c
@@ -1395,7 +1395,7 @@ JL_CALLABLE(jl_f_setglobal)
         jl_atomic_error("setglobal!: module binding cannot be written non-atomically");
     else if (order >= jl_memory_order_seq_cst)
         jl_fence();
-    jl_binding_t *b = jl_get_binding_wr(mod, var, 0);
+    jl_binding_t *b = jl_get_binding_wr(mod, var);
     jl_checked_assignment(b, mod, var, args[2]); // release store
     if (order >= jl_memory_order_seq_cst)
         jl_fence();
@@ -1430,7 +1430,7 @@ JL_CALLABLE(jl_f_swapglobal)
     if (order == jl_memory_order_notatomic)
         jl_atomic_error("swapglobal!: module binding cannot be written non-atomically");
     // is seq_cst already, no fence needed
-    jl_binding_t *b = jl_get_binding_wr(mod, var, 0);
+    jl_binding_t *b = jl_get_binding_wr(mod, var);
     return jl_checked_swap(b, mod, var, args[2]);
 }
 
@@ -1448,7 +1448,7 @@ JL_CALLABLE(jl_f_modifyglobal)
     JL_TYPECHK(modifyglobal!, symbol, (jl_value_t*)var);
     if (order == jl_memory_order_notatomic)
         jl_atomic_error("modifyglobal!: module binding cannot be written non-atomically");
-    jl_binding_t *b = jl_get_binding_wr(mod, var, 0);
+    jl_binding_t *b = jl_get_binding_wr(mod, var);
     // is seq_cst already, no fence needed
     return jl_checked_modify(b, mod, var, args[2], args[3]);
 }
@@ -1477,7 +1477,7 @@ JL_CALLABLE(jl_f_replaceglobal)
         jl_atomic_error("replaceglobal!: module binding cannot be written non-atomically");
     if (failure_order == jl_memory_order_notatomic)
         jl_atomic_error("replaceglobal!: module binding cannot be accessed non-atomically");
-    jl_binding_t *b = jl_get_binding_wr(mod, var, 0);
+    jl_binding_t *b = jl_get_binding_wr(mod, var);
     // is seq_cst already, no fence needed
     return jl_checked_replace(b, mod, var, args[2], args[3]);
 }
@@ -1506,7 +1506,7 @@ JL_CALLABLE(jl_f_setglobalonce)
         jl_atomic_error("setglobalonce!: module binding cannot be written non-atomically");
     if (failure_order == jl_memory_order_notatomic)
         jl_atomic_error("setglobalonce!: module binding cannot be accessed non-atomically");
-    jl_binding_t *b = jl_get_binding_wr(mod, var, 0);
+    jl_binding_t *b = jl_get_binding_wr(mod, var);
     // is seq_cst already, no fence needed
     jl_value_t *old = jl_checked_assignonce(b, mod, var, args[2]);
     return old == NULL ? jl_true : jl_false;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 19ee1e9161152..e9e4275672c7e 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -930,12 +930,12 @@ static const auto jlgetbindingorerror_func = new JuliaFunction<>{
     },
     nullptr,
 };
-static const auto jlgetbindingwrorerror_func = new JuliaFunction<>{
-    XSTR(jl_get_binding_wr),
+static const auto jlcheckbpwritable_func = new JuliaFunction<>{
+    XSTR(jl_check_binding_currently_writable),
     [](LLVMContext &C) {
         auto T_pjlvalue = JuliaType::get_pjlvalue_ty(C);
-        return FunctionType::get(T_pjlvalue,
-                {T_pjlvalue, T_pjlvalue, getInt32Ty(C)}, false);
+        return FunctionType::get(getVoidTy(C),
+                {T_pjlvalue, T_pjlvalue, T_pjlvalue}, false);
     },
     nullptr,
 };
@@ -2098,8 +2098,6 @@ static Type *julia_type_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, bool *isboxed
 static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value *fval, StringRef name, jl_value_t *sig, jl_value_t *jlrettype, bool is_opaque_closure, bool gcstack_arg,
         ArrayRef<const char*> ArgNames=None, unsigned nreq=0);
 static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval = -1);
-static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t *s,
-                                     jl_binding_t **pbnd, bool assign, bool alloc);
 static jl_cgval_t emit_checked_var(jl_codectx_t &ctx, Value *bp, jl_sym_t *name, jl_value_t *scope, bool isvol, MDNode *tbaa);
 static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i);
 static Value *emit_condition(jl_codectx_t &ctx, const jl_cgval_t &condV, const Twine &msg);
@@ -3498,19 +3496,17 @@ static jl_cgval_t emit_globalop(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *s
                                 bool issetglobal, bool isreplaceglobal, bool isswapglobal, bool ismodifyglobal, bool issetglobalonce,
                                 const jl_cgval_t *modifyop, bool alloc)
 {
-    jl_binding_t *bnd = NULL;
-    Value *bp = global_binding_pointer(ctx, mod, sym, &bnd, true, alloc);
+    jl_binding_t *bnd = jl_get_module_binding(mod, sym, 1);
     jl_binding_partition_t *bpart = jl_get_binding_partition_all(bnd, ctx.min_world, ctx.max_world);
-    if (bp == NULL)
-        return jl_cgval_t();
+    Value *bp = julia_binding_gv(ctx, bnd);
     if (bpart) {
         jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
-        if (!jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
+        if (decode_restriction_kind(pku) == BINDING_KIND_GLOBAL) {
             jl_value_t *ty = decode_restriction_value(pku);
             if (ty != nullptr) {
                 const std::string fname = issetglobal ? "setglobal!" : isreplaceglobal ? "replaceglobal!" : isswapglobal ? "swapglobal!" : ismodifyglobal ? "modifyglobal!" : "setglobalonce!";
                 if (!ismodifyglobal) {
-                    // TODO: use typeassert in jl_check_binding_wr too
+                    // TODO: use typeassert in jl_check_binding_assign_value too
                     emit_typecheck(ctx, rval, ty, "typeassert");
                     rval = update_julia_type(ctx, rval, ty);
                     if (rval.typ == jl_bottom_type)
@@ -3545,6 +3541,8 @@ static jl_cgval_t emit_globalop(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *s
     }
     Value *m = literal_pointer_val(ctx, (jl_value_t*)mod);
     Value *s = literal_pointer_val(ctx, (jl_value_t*)sym);
+    ctx.builder.CreateCall(prepare_call(jlcheckbpwritable_func),
+        { bp, m, s });
     if (issetglobal) {
         ctx.builder.CreateCall(prepare_call(jlcheckassign_func),
                 { bp, m, s, mark_callee_rooted(ctx, boxed(ctx, rval)) });
@@ -5991,85 +5989,6 @@ static void emit_hasnofield_error_ifnot(jl_codectx_t &ctx, Value *ok, jl_datatyp
     ctx.builder.SetInsertPoint(ifok);
 }
 
-// returns a jl_ppvalue_t location for the global variable m.s
-// if the reference currently bound or assign == true,
-//   pbnd will also be assigned with the binding address
-static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t *s,
-                                     jl_binding_t **pbnd, bool assign, bool alloc)
-{
-    jl_binding_t *b = jl_get_module_binding(m, s, 1);
-    jl_binding_partition_t *bpart = jl_get_binding_partition_all(b, ctx.min_world, ctx.max_world);
-    jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
-    if (assign) {
-        if (jl_bkind_is_some_guard(decode_restriction_kind(pku)))
-            // not yet declared
-            b = NULL;
-    }
-    else {
-        if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) {
-            // try to look this up now
-            b = jl_get_binding(m, s);
-            bpart = jl_get_binding_partition_all(b, ctx.min_world, ctx.max_world);
-        }
-        pku = jl_walk_binding_inplace_all(&b, &bpart, ctx.min_world, ctx.max_world);
-    }
-    if (!b || !bpart) {
-        // var not found. switch to delayed lookup.
-        Constant *initnul = Constant::getNullValue(ctx.types().T_pjlvalue);
-        GlobalVariable *bindinggv = new GlobalVariable(*ctx.f->getParent(), ctx.types().T_pjlvalue,
-                false, GlobalVariable::PrivateLinkage, initnul, "jl_binding_ptr"); // LLVM has bugs with nameless globals
-        LoadInst *cachedval = ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, bindinggv, Align(sizeof(void*)));
-        setName(ctx.emission_context, cachedval, jl_symbol_name(m->name) + StringRef(".") + jl_symbol_name(s) + ".cached");
-        cachedval->setOrdering(AtomicOrdering::Unordered);
-        BasicBlock *have_val = BasicBlock::Create(ctx.builder.getContext(), "found");
-        BasicBlock *not_found = BasicBlock::Create(ctx.builder.getContext(), "notfound");
-        BasicBlock *currentbb = ctx.builder.GetInsertBlock();
-        auto iscached = ctx.builder.CreateICmpNE(cachedval, initnul);
-        setName(ctx.emission_context, iscached, "iscached");
-        ctx.builder.CreateCondBr(iscached, have_val, not_found);
-        not_found->insertInto(ctx.f);
-        ctx.builder.SetInsertPoint(not_found);
-        Value *bval = nullptr;
-        if (assign) {
-            bval = ctx.builder.CreateCall(prepare_call(jlgetbindingwrorerror_func),
-                    { literal_pointer_val(ctx, (jl_value_t*)m),
-                    literal_pointer_val(ctx, (jl_value_t*)s),
-                    ConstantInt::get(getInt32Ty(ctx.builder.getContext()), alloc)});
-        } else {
-            bval = ctx.builder.CreateCall(prepare_call(jlgetbindingorerror_func),
-                    { literal_pointer_val(ctx, (jl_value_t*)m),
-                    literal_pointer_val(ctx, (jl_value_t*)s)});
-        }
-        setName(ctx.emission_context, bval, jl_symbol_name(m->name) + StringRef(".") + jl_symbol_name(s) + ".found");
-        ctx.builder.CreateAlignedStore(bval, bindinggv, Align(sizeof(void*)))->setOrdering(AtomicOrdering::Release);
-        ctx.builder.CreateBr(have_val);
-        have_val->insertInto(ctx.f);
-        ctx.builder.SetInsertPoint(have_val);
-        PHINode *p = ctx.builder.CreatePHI(ctx.types().T_pjlvalue, 2);
-        p->addIncoming(cachedval, currentbb);
-        p->addIncoming(bval, not_found);
-        setName(ctx.emission_context, p, jl_symbol_name(m->name) + StringRef(".") + jl_symbol_name(s));
-        return p;
-    }
-    if (assign) {
-        if (decode_restriction_kind(pku) != BINDING_KIND_GLOBAL && !jl_bkind_is_some_guard(decode_restriction_kind(pku))) {
-            // this will fail at runtime, so defer to the runtime to create the error
-            ctx.builder.CreateCall(prepare_call(jlgetbindingwrorerror_func),
-                    { literal_pointer_val(ctx, (jl_value_t*)m),
-                      literal_pointer_val(ctx, (jl_value_t*)s),
-                      ConstantInt::get(getInt32Ty(ctx.builder.getContext()), alloc) });
-            CreateTrap(ctx.builder);
-            return NULL;
-        }
-    }
-    else {
-        if (b->deprecated)
-            cg_bdw(ctx, s, b);
-    }
-    *pbnd = b;
-    return julia_binding_gv(ctx, b);
-}
-
 static jl_cgval_t emit_checked_var(jl_codectx_t &ctx, Value *bp, jl_sym_t *name, jl_value_t *scope, bool isvol, MDNode *tbaa)
 {
     LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)));
@@ -10184,7 +10103,7 @@ static void init_jit_functions(void)
     add_named_global(jltypeerror_func, &jl_type_error);
     add_named_global(jlcheckassign_func, &jl_checked_assignment);
     add_named_global(jlgetbindingorerror_func, &jl_get_binding_or_error);
-    add_named_global(jlgetbindingwrorerror_func, &jl_get_binding_wr);
+    add_named_global(jlcheckbpwritable_func, &jl_check_binding_currently_writable);
     add_named_global(jlboundp_func, &jl_boundp);
     for (auto it : builtin_func_map())
         add_named_global(it.second, it.first);
diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc
index c1b29a091511b..9e221420aa9f4 100644
--- a/src/jl_exported_funcs.inc
+++ b/src/jl_exported_funcs.inc
@@ -196,6 +196,7 @@
     XX(jl_get_binding_for_method_def) \
     XX(jl_get_binding_or_error) \
     XX(jl_get_binding_wr) \
+    XX(jl_check_binding_currently_writable) \
     XX(jl_get_cpu_name) \
     XX(jl_get_cpu_features) \
     XX(jl_cpu_has_fma) \
diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm
index 57f67755df692..97d76e7762a9e 100644
--- a/src/julia-syntax.scm
+++ b/src/julia-syntax.scm
@@ -4626,6 +4626,8 @@ f(x) = yt(x)
       (if (globalref? lhs)
         (begin
           (emit `(global ,lhs))
+          (if (null? (cadr lam))
+            (emit `(latestworld)))
           (emit `(call (top setglobal!) ,(cadr lhs) (inert ,(caddr lhs)) ,rhs)))
         (emit `(= ,lhs ,rhs))))
     (define (emit-assignment lhs rhs)
@@ -4944,13 +4946,16 @@ f(x) = yt(x)
                  #f))
             ((global) ; keep global declarations as statements
              (if value (error "misplaced \"global\" declaration"))
-             (emit e))
+             (emit e)
+             (if (null? (cadr lam))
+               (emit `(latestworld))))
             ((globaldecl)
              (if value (error "misplaced \"global\" declaration"))
-             (if (atom? (caddr e)) (emit e)
+             (if (atom? (caddr e)) (begin (emit e) (emit `(latestworld)))
               (let ((rr (make-ssavalue)))
                 (emit `(= ,rr ,(caddr e)))
-                (emit `(globaldecl ,(cadr e) ,rr)))))
+                (emit `(globaldecl ,(cadr e) ,rr))
+                (emit `(latestworld)))))
             ((local-def) #f)
             ((local) #f)
             ((moved-local)
diff --git a/src/julia.h b/src/julia.h
index f36133088119f..a5f56ad580335 100644
--- a/src/julia.h
+++ b/src/julia.h
@@ -2001,7 +2001,8 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_or_error(jl_module_t *m, jl_sym_t *var
 JL_DLLEXPORT jl_value_t *jl_module_globalref(jl_module_t *m, jl_sym_t *var);
 JL_DLLEXPORT jl_value_t *jl_get_binding_type(jl_module_t *m, jl_sym_t *var);
 // get binding for assignment
-JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, int alloc);
+JL_DLLEXPORT void jl_check_binding_currently_writable(jl_binding_t *b, jl_module_t *m, jl_sym_t *s);
+JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var);
 JL_DLLEXPORT jl_binding_t *jl_get_binding_for_method_def(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var);
 JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var, int allow_import);
 JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var);
diff --git a/src/module.c b/src/module.c
index f4c56e19efa61..2630db2dbfd94 100644
--- a/src/module.c
+++ b/src/module.c
@@ -279,38 +279,42 @@ extern void check_safe_newbinding(jl_module_t *m, jl_sym_t *var)
 
 static jl_module_t *jl_binding_dbgmodule(jl_binding_t *b, jl_module_t *m, jl_sym_t *var) JL_GLOBALLY_ROOTED;
 
-// get binding for assignment
-JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var, int alloc)
+// Checks that the binding in general is currently writable, but does not perform any checks on the
+// value to be written into the binding.
+JL_DLLEXPORT void jl_check_binding_currently_writable(jl_binding_t *b, jl_module_t *m, jl_sym_t *s)
 {
-    jl_binding_t *b = jl_get_module_binding(m, var, 1);
     jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
     jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
 retry:
     if (decode_restriction_kind(pku) != BINDING_KIND_GLOBAL && !jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
         if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) {
             if (decode_restriction_kind(pku) != BINDING_KIND_DECLARED) {
-                check_safe_newbinding(m, var);
-                if (!alloc)
-                    jl_errorf("Global %s.%s does not exist and cannot be assigned.\n"
-                              "Note: Julia 1.9 and 1.10 inadvertently omitted this error check (#56933).\n"
-                              "Hint: Declare it using `global %s` inside `%s` before attempting assignment.",
-                              jl_symbol_name(m->name), jl_symbol_name(var),
-                              jl_symbol_name(var), jl_symbol_name(m->name));
+                jl_errorf("Global %s.%s does not exist and cannot be assigned.\n"
+                            "Note: Julia 1.9 and 1.10 inadvertently omitted this error check (#56933).\n"
+                            "Hint: Declare it using `global %s` inside `%s` before attempting assignment.",
+                            jl_symbol_name(m->name), jl_symbol_name(s),
+                            jl_symbol_name(s), jl_symbol_name(m->name));
             }
             jl_ptr_kind_union_t new_pku = encode_restriction((jl_value_t*)jl_any_type, BINDING_KIND_GLOBAL);
             if (!jl_atomic_cmpswap(&bpart->restriction, &pku, new_pku))
                 goto retry;
             jl_gc_wb_knownold(bpart, jl_any_type);
         } else {
-            jl_module_t *from = jl_binding_dbgmodule(b, m, var);
+            jl_module_t *from = jl_binding_dbgmodule(b, m, s);
             if (from == m)
                 jl_errorf("cannot assign a value to imported variable %s.%s",
-                          jl_symbol_name(from->name), jl_symbol_name(var));
+                          jl_symbol_name(from->name), jl_symbol_name(s));
             else
                 jl_errorf("cannot assign a value to imported variable %s.%s from module %s",
-                          jl_symbol_name(from->name), jl_symbol_name(var), jl_symbol_name(m->name));
+                          jl_symbol_name(from->name), jl_symbol_name(s), jl_symbol_name(m->name));
         }
     }
+}
+
+JL_DLLEXPORT jl_binding_t *jl_get_binding_wr(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var)
+{
+    jl_binding_t *b = jl_get_module_binding(m, var, 1);
+    jl_check_binding_currently_writable(b, m, var);
     return b;
 }
 
@@ -1066,7 +1070,7 @@ JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var)
 
 JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT)
 {
-    jl_binding_t *bp = jl_get_binding_wr(m, var, 0);
+    jl_binding_t *bp = jl_get_binding_wr(m, var);
     jl_checked_assignment(bp, m, var, val);
 }
 
@@ -1186,7 +1190,9 @@ void jl_binding_deprecation_warning(jl_module_t *m, jl_sym_t *s, jl_binding_t *b
     }
 }
 
-jl_value_t *jl_check_binding_wr(jl_binding_t *b JL_PROPAGATES_ROOT, jl_module_t *mod, jl_sym_t *var, jl_value_t *rhs JL_MAYBE_UNROOTED, int reassign)
+// For a generally writable binding (checked using jl_check_binding_currently_writable in this world age), check whether
+// we can actually write the value `rhs` to it.
+jl_value_t *jl_check_binding_assign_value(jl_binding_t *b JL_PROPAGATES_ROOT, jl_module_t *mod, jl_sym_t *var, jl_value_t *rhs JL_MAYBE_UNROOTED)
 {
     JL_GC_PUSH1(&rhs); // callee-rooted
     jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
@@ -1219,7 +1225,7 @@ jl_value_t *jl_check_binding_wr(jl_binding_t *b JL_PROPAGATES_ROOT, jl_module_t
 
 JL_DLLEXPORT void jl_checked_assignment(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *rhs)
 {
-    if (jl_check_binding_wr(b, mod, var, rhs, 1) != NULL) {
+    if (jl_check_binding_assign_value(b, mod, var, rhs) != NULL) {
         jl_atomic_store_release(&b->value, rhs);
         jl_gc_wb(b, rhs);
     }
@@ -1227,7 +1233,7 @@ JL_DLLEXPORT void jl_checked_assignment(jl_binding_t *b, jl_module_t *mod, jl_sy
 
 JL_DLLEXPORT jl_value_t *jl_checked_swap(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *rhs)
 {
-    jl_check_binding_wr(b, mod, var, rhs, 0);
+    jl_check_binding_assign_value(b, mod, var, rhs);
     jl_value_t *old = jl_atomic_exchange(&b->value, rhs);
     jl_gc_wb(b, rhs);
     if (__unlikely(old == NULL))
@@ -1237,7 +1243,7 @@ JL_DLLEXPORT jl_value_t *jl_checked_swap(jl_binding_t *b, jl_module_t *mod, jl_s
 
 JL_DLLEXPORT jl_value_t *jl_checked_replace(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *expected, jl_value_t *rhs)
 {
-    jl_value_t *ty = jl_check_binding_wr(b, mod, var, rhs, 0);
+    jl_value_t *ty = jl_check_binding_assign_value(b, mod, var, rhs);
     return replace_value(ty, &b->value, (jl_value_t*)b, expected, rhs, 1, mod, var);
 }
 
@@ -1256,7 +1262,7 @@ JL_DLLEXPORT jl_value_t *jl_checked_modify(jl_binding_t *b, jl_module_t *mod, jl
 
 JL_DLLEXPORT jl_value_t *jl_checked_assignonce(jl_binding_t *b, jl_module_t *mod, jl_sym_t *var, jl_value_t *rhs )
 {
-    jl_check_binding_wr(b, mod, var, rhs, 0);
+    jl_check_binding_assign_value(b, mod, var, rhs);
     jl_value_t *old = NULL;
     if (jl_atomic_cmpswap(&b->value, &old, rhs))
         jl_gc_wb(b, rhs);
diff --git a/src/toplevel.c b/src/toplevel.c
index 30e78bf813fc8..e05783ac61a0c 100644
--- a/src/toplevel.c
+++ b/src/toplevel.c
@@ -302,38 +302,6 @@ static jl_value_t *jl_eval_dot_expr(jl_module_t *m, jl_value_t *x, jl_value_t *f
     return args[0];
 }
 
-void jl_binding_set_type(jl_binding_t *b, jl_module_t *mod, jl_sym_t *sym, jl_value_t *ty)
-{
-    jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
-    jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
-    jl_ptr_kind_union_t new_pku = encode_restriction(ty, BINDING_KIND_GLOBAL);
-    while (1) {
-        if (decode_restriction_kind(pku) != BINDING_KIND_GLOBAL) {
-            if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) {
-                if (jl_atomic_cmpswap(&bpart->restriction, &pku, new_pku))
-                    break;
-                continue;
-            } else {
-                jl_errorf("cannot set type for imported global %s.%s.",
-                        jl_symbol_name(mod->name), jl_symbol_name(sym));
-            }
-        }
-        if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
-            jl_errorf("cannot set type for imported constant %s.%s.",
-                    jl_symbol_name(mod->name), jl_symbol_name(sym));
-        }
-        jl_value_t *old_ty = decode_restriction_value(pku);
-        JL_GC_PROMISE_ROOTED(old_ty);
-        if (!jl_types_equal(ty, old_ty)) {
-            jl_errorf("cannot set type for global %s.%s. It already has a value or is already set to a different type.",
-                    jl_symbol_name(mod->name), jl_symbol_name(sym));
-        }
-        if (jl_atomic_cmpswap(&bpart->restriction, &pku, new_pku))
-            break;
-    }
-    jl_gc_wb(bpart, ty);
-}
-
 extern void check_safe_newbinding(jl_module_t *m, jl_sym_t *var);
 void jl_declare_global(jl_module_t *m, jl_value_t *arg, jl_value_t *set_type) {
     // create uninitialized mutable binding for "global x" decl sometimes or probably
@@ -349,17 +317,49 @@ void jl_declare_global(jl_module_t *m, jl_value_t *arg, jl_value_t *set_type) {
         gm = m;
         gs = (jl_sym_t*)arg;
     }
+    JL_LOCK(&world_counter_lock);
+    size_t new_world = jl_atomic_load_relaxed(&jl_world_counter) + 1;
     jl_binding_t *b = jl_get_module_binding(gm, gs, 1);
-    jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age);
-    jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
-    while (decode_restriction_kind(pku) == BINDING_KIND_GUARD || decode_restriction_kind(pku) == BINDING_KIND_FAILED) {
-        check_safe_newbinding(gm, gs);
-        if (jl_atomic_cmpswap(&bpart->restriction, &pku, encode_restriction(NULL, BINDING_KIND_DECLARED)))
-            break;
-    }
-    if (set_type) {
-        jl_binding_set_type(b, gm, gs, set_type);
+    jl_binding_partition_t *bpart = NULL;
+    jl_ptr_kind_union_t new_pku = encode_restriction(set_type, set_type == NULL ? BINDING_KIND_DECLARED : BINDING_KIND_GLOBAL);
+    while (1) {
+        bpart = jl_get_binding_partition(b, new_world);
+        jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
+        if (decode_restriction_kind(pku) != BINDING_KIND_GLOBAL) {
+            if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) {
+                if (decode_restriction_kind(pku) == BINDING_KIND_DECLARED && !set_type)
+                    goto done;
+                check_safe_newbinding(gm, gs);
+                if (jl_atomic_cmpswap(&bpart->restriction, &pku, new_pku)) {
+                    break;
+                }
+                continue;
+            } else if (set_type) {
+                if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
+                    jl_errorf("cannot set type for imported constant %s.%s.",
+                            jl_symbol_name(gm->name), jl_symbol_name(gs));
+                } else {
+                    jl_errorf("cannot set type for imported global %s.%s.",
+                            jl_symbol_name(gm->name), jl_symbol_name(gs));
+                }
+            }
+        }
+        if (!set_type)
+            goto done;
+        jl_value_t *old_ty = decode_restriction_value(pku);
+        JL_GC_PROMISE_ROOTED(old_ty);
+        if (!jl_types_equal(set_type, old_ty)) {
+            jl_errorf("cannot set type for global %s.%s. It already has a value or is already set to a different type.",
+                    jl_symbol_name(gm->name), jl_symbol_name(gs));
+        }
+        goto done;
     }
+    if (set_type)
+        jl_gc_wb(bpart, set_type);
+    bpart->min_world = new_world;
+    jl_atomic_store_release(&jl_world_counter, new_world);
+done:
+    JL_UNLOCK(&world_counter_lock);
 }
 
 void jl_eval_global_expr(jl_module_t *m, jl_expr_t *ex, int set_type)
@@ -751,7 +751,8 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3(
     jl_ptr_kind_union_t pku = jl_atomic_load_relaxed(&bpart->restriction);
     int did_warn = 0;
     while (1) {
-        if (jl_bkind_is_some_constant(decode_restriction_kind(pku))) {
+        enum jl_partition_kind kind = decode_restriction_kind(pku);
+        if (jl_bkind_is_some_constant(kind)) {
             if (!val) {
                 break;
             }
@@ -789,7 +790,7 @@ JL_DLLEXPORT jl_binding_partition_t *jl_declare_constant_val3(
             continue;
         }
         jl_gc_wb(bpart, val);
-        int needs_backdate = bpart->min_world == 0 && new_world && val;
+        int needs_backdate = (bpart->min_world == 0 || kind == BINDING_KIND_DECLARED) && new_world && val;
         bpart->min_world = new_world;
         if (needs_backdate) {
             jl_declare_constant_val3(b, mod, var, val, BINDING_KIND_BACKDATED_CONST, 0);
@@ -1094,9 +1095,8 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_val
     else {
         // use interpreter
         assert(thk);
-        if (has_opaque) {
+        if (has_opaque)
             jl_resolve_definition_effects_in_ir((jl_array_t*)thk->code, m, NULL, 0);
-        }
         size_t world = jl_atomic_load_acquire(&jl_world_counter);
         ct->world_age = world;
         result = jl_interpret_toplevel_thunk(m, thk);
diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl
index f83fa867748af..699024c1723a4 100644
--- a/stdlib/REPL/src/REPL.jl
+++ b/stdlib/REPL/src/REPL.jl
@@ -44,8 +44,8 @@ function UndefVarError_hint(io::IO, ex::UndefVarError)
                 "with the module it should come from.")
             elseif kind === Base.BINDING_KIND_GUARD
                 print(io, "\nSuggestion: check for spelling errors or missing imports.")
-            else
-                print(io, "\nSuggestion: this global was defined as `$(bpart.restriction.globalref)` but not assigned a value.")
+            elseif Base.is_some_imported(kind)
+                print(io, "\nSuggestion: this global was defined as `$(Base.partition_restriction(bpart).globalref)` but not assigned a value.")
             end
         elseif scope === :static_parameter
             print(io, "\nSuggestion: run Test.detect_unbound_args to detect method arguments that do not fully constrain a type parameter.")
@@ -1884,16 +1884,26 @@ function get_usings!(usings, ex)
     return usings
 end
 
+function create_global_out!(mod)
+    if !isdefinedglobal(mod, :Out)
+        out = Dict{Int, Any}()
+        @eval mod begin
+            const Out = $(out)
+            export Out
+        end
+        return out
+    end
+    return getglobal(mod, Out)
+end
+
 function capture_result(n::Ref{Int}, @nospecialize(x))
     n = n[]
     mod = Base.MainInclude
-    if !isdefined(mod, :Out)
-        @eval mod global Out
-        @eval mod export Out
-        setglobal!(mod, :Out, Dict{Int, Any}())
-    end
-    if x !== getglobal(mod, :Out) && x !== nothing # remove this?
-        getglobal(mod, :Out)[n] = x
+    # TODO: This invokelatest is only required due to backdated constants
+    # and should be removed after
+    out = isdefinedglobal(mod, :Out) ? invokelatest(getglobal, mod, :Out) : invokelatest(create_global_out!, mod)
+    if x !== out && x !== nothing # remove this?
+        out[n] = x
     end
     nothing
 end
diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl
index 8944fd76f31de..018cf9c36430e 100644
--- a/stdlib/REPL/test/repl.jl
+++ b/stdlib/REPL/test/repl.jl
@@ -752,11 +752,11 @@ fake_repl() do stdin_write, stdout_read, repl
 
     # Test removal of prefix in single statement paste
     sendrepl2("\e[200~julia> A = 2\e[201~\n")
-    @test Main.A == 2
+    @test @world(Main.A, ∞) == 2
 
     # Test removal of prefix in single statement paste
     sendrepl2("\e[200~In [12]: A = 2.2\e[201~\n")
-    @test Main.A == 2.2
+    @test @world(Main.A, ∞) == 2.2
 
     # Test removal of prefix in multiple statement paste
     sendrepl2("""\e[200~
@@ -768,7 +768,7 @@ fake_repl() do stdin_write, stdout_read, repl
 
                     julia> A = 3\e[201~
              """)
-    @test Main.A == 3
+    @test @world(Main.A, ∞) == 3
     @test @invokelatest(Main.foo(4))
     @test @invokelatest(Main.T17599(3)).a == 3
     @test !@invokelatest(Main.foo(2))
@@ -780,12 +780,12 @@ fake_repl() do stdin_write, stdout_read, repl
             julia> A = 4
             4\e[201~
              """)
-    @test Main.A == 4
+    @test @world(Main.A, ∞) == 4
     @test @invokelatest(Main.goo(4)) == 5
 
     # Test prefix removal only active in bracket paste mode
     sendrepl2("julia = 4\n julia> 3 && (A = 1)\n")
-    @test Main.A == 1
+    @test @world(Main.A, ∞) == 1
 
     # Test that indentation corresponding to the prompt is removed
     s = sendrepl2("""\e[200~julia> begin\n           α=1\n           β=2\n       end\n\e[201~""")
@@ -820,8 +820,8 @@ fake_repl() do stdin_write, stdout_read, repl
             julia> B = 2
             2\e[201~
              """)
-    @test Main.A == 1
-    @test Main.B == 2
+    @test @world(Main.A, ∞) == 1
+    @test @world(Main.B, ∞) == 2
     end # redirect_stdout
 
     # Close repl
diff --git a/sysimage.mk b/sysimage.mk
index 571e2da003346..ae6ce8699f417 100644
--- a/sysimage.mk
+++ b/sysimage.mk
@@ -39,6 +39,7 @@ COMPILER_SRCS := $(addprefix $(JULIAHOME)/, \
 		base/error.jl \
 		base/essentials.jl \
 		base/expr.jl \
+		base/exports.jl \
 		base/generator.jl \
 		base/int.jl \
 		base/indices.jl \
diff --git a/test/core.jl b/test/core.jl
index 3886e6728df10..5e2677f0f075f 100644
--- a/test/core.jl
+++ b/test/core.jl
@@ -8233,6 +8233,7 @@ end
 let M = @__MODULE__
     Core.eval(M, :(global a_typed_global))
     @test Core.eval(M, :(global a_typed_global::$(Tuple{Union{Integer,Nothing}}))) === nothing
+    @Core.latestworld
     @test Core.get_binding_type(M, :a_typed_global) === Tuple{Union{Integer,Nothing}}
     @test Core.eval(M, :(global a_typed_global::$(Tuple{Union{Integer,Nothing}}))) === nothing
     @test Core.eval(M, :(global a_typed_global::$(Union{Tuple{Integer},Tuple{Nothing}}))) === nothing
diff --git a/test/precompile.jl b/test/precompile.jl
index f5a412b416ddc..a9516231ff8d7 100644
--- a/test/precompile.jl
+++ b/test/precompile.jl
@@ -1969,7 +1969,7 @@ precompile_test_harness("Issue #50538") do load_path
         """
         module I50538
         const newglobal = try
-            Base.newglobal = false
+            eval(Expr(:global, GlobalRef(Base, :newglobal)))
         catch ex
             ex isa ErrorException || rethrow()
             ex
diff --git a/test/worlds.jl b/test/worlds.jl
index 025aaba6cea4f..48fb6593d3a37 100644
--- a/test/worlds.jl
+++ b/test/worlds.jl
@@ -107,7 +107,7 @@ end
 g265() = [f265(x) for x in 1:3.]
 wc265 = get_world_counter()
 wc265_41332a = Task(tls_world_age)
-@test tls_world_age() == wc265
+@test tls_world_age() == wc265 + 2
 (function ()
     global wc265_41332b = Task(tls_world_age)
     @eval f265(::Any) = 1.0
@@ -115,24 +115,24 @@ wc265_41332a = Task(tls_world_age)
     global wc265_41332d = Task(tls_world_age)
     nothing
 end)()
-@test wc265 + 4 == get_world_counter() == tls_world_age()
+@test wc265 + 10 == get_world_counter() == tls_world_age()
 schedule(wc265_41332a)
 schedule(wc265_41332b)
 schedule(wc265_41332c)
 schedule(wc265_41332d)
-@test wc265 == fetch(wc265_41332a)
-@test wc265 + 2 == fetch(wc265_41332b)
-@test wc265 + 4 == fetch(wc265_41332c)
-@test wc265 + 2 == fetch(wc265_41332d)
+@test wc265 + 1 == fetch(wc265_41332a)
+@test wc265 + 8 == fetch(wc265_41332b)
+@test wc265 + 10 == fetch(wc265_41332c)
+@test wc265 + 8 == fetch(wc265_41332d)
 chnls, tasks = Base.channeled_tasks(2, wfunc)
 t265 = tasks[1]
 
 wc265 = get_world_counter()
 @test put_n_take!(get_world_counter, ()) == wc265
-@test put_n_take!(tls_world_age, ()) == wc265
+@test put_n_take!(tls_world_age, ()) + 3 == wc265
 f265(::Int) = 1
 @test put_n_take!(get_world_counter, ()) == wc265 + 1 == get_world_counter() == tls_world_age()
-@test put_n_take!(tls_world_age, ()) == wc265
+@test put_n_take!(tls_world_age, ()) + 3 == wc265
 
 @test g265() == Int[1, 1, 1]
 @test Core.Compiler.return_type(f265, Tuple{Any,}) == Union{Float64, Int}
@@ -162,12 +162,12 @@ let ex = t265.exception
     @test ex isa MethodError
     @test ex.f == h265
     @test ex.args == ()
-    @test ex.world == wc265
+    @test ex.world == wc265-3
     str = sprint(showerror, ex)
     wc = get_world_counter()
     cmps = """
         MethodError: no method matching h265()
-        The applicable method may be too new: running in world age $wc265, while current world is $wc."""
+        The applicable method may be too new: running in world age $(wc265-3), while current world is $wc."""
     @test startswith(str, cmps)
     cmps = "\n  h265() (method too new to be called from this world context.)\n   $loc_h265"
     @test occursin(cmps, str)
@@ -500,3 +500,12 @@ end
 end
 
 @test_throws ErrorException("Generated function result with `edges == nothing` and `max_world == typemax(UInt)` must have `min_world == 1`") generated_no_edges()
+
+# Test that backdating of constants is working for structs
+before_backdate_age = Base.tls_world_age()
+struct FooBackdated
+    x::Vector{FooBackdated}
+
+    FooBackdated() = new(FooBackdated[])
+end
+@test Base.invoke_in_world(before_backdate_age, isdefined, @__MODULE__, :FooBackdated)