From c86965baa2f240d23eabdd4d7034fffe2ff0d54b Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Thu, 12 Sep 2024 03:41:49 -0400 Subject: [PATCH] Add `invokelatest` barrier to `string(...)` in `@assert` (#55739) This change protects `@assert` from invalidations to `Base.string(...)` by adding an `invokelatest` barrier. A common source of invalidations right now is `print(io, join(args...))`. The problem is: 1. Inference concludes that `join(::Any...)` returns `Union{String,AnnotatedString}` 2. The `print` call is union-split to `String` and `AnnotatedString` 3. This code is now invalidated when StyledStrings defines `print(io, ::AnnotatedString)` The invalidation chain for `@assert` is similar: ` @assert 1 == 1` calls into `string(::Expr)` which calls into `print(io, join(args::Any...))`. Unfortunately that leads to the invalidation of almost all `@assert`s without an explicit error message Similar to https://github.com/JuliaLang/julia/pull/55583#issuecomment-2308969806 (cherry picked from commit 945517ba4e15f7470b8790a696ba5404ef047f2f) --- base/error.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/error.jl b/base/error.jl index 37ceb39253e38..e25157b6f2b95 100644 --- a/base/error.jl +++ b/base/error.jl @@ -223,14 +223,14 @@ macro assert(ex, msgs...) msg = msg # pass-through elseif !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol)) # message is an expression needing evaluating - msg = :(Main.Base.string($(esc(msg)))) + msg = :(Main.Base.invokelatest(Main.Base.string, $(esc(msg)))) elseif isdefined(Main, :Base) && isdefined(Main.Base, :string) && applicable(Main.Base.string, msg) msg = Main.Base.string(msg) else # string() might not be defined during bootstrap msg = quote msg = $(Expr(:quote,msg)) - isdefined(Main, :Base) ? Main.Base.string(msg) : + isdefined(Main, :Base) ? Main.Base.invokelatest(Main.Base.string, msg) : (Core.println(msg); "Error during bootstrap. See stdout.") end end