Repository navigation
Conversation
The API functions and their helpers take the predicate or callback as
`f::Function` and pass it on: to the next function, to a `do` block, or,
for every method with keyword arguments, to the method's keyword body.
Julia does not specialize a method on a `Function` argument it only
passes on, so these methods are compiled for `f::Function` and calling
the callback is a dynamic dispatch. Under `juliac --trim=safe` this
makes every `Tar.create`, `list`, `extract`, `rewrite` and `tree_hash`
fail verification (together with ArgTools' `arg_read` / `arg_write`,
which have the same problem).
Type the callbacks as `f::F where {F <: Function}`. The signatures, and
so dispatch, are unchanged; the methods are compiled for the callback's
type.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`read_standard_header` rewrites the message of the `ErrorException` that `check_version_field` or `check_checksum_field` throws. It converted the message with `String(err.msg)`, but `ErrorException`'s `msg` field is an `AbstractString`, so that is a dynamic call, which `juliac --trim=safe` rejects. Both checks throw through `header_error`, which calls `error` with a `String` (built by `sprint`): assert that instead of converting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pankgeorg
marked this pull request as ready for review
October 29, 2026 18:20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This removes two of the blockers to using Tar in programs compiled with
juliac --trim=safe. With JuliaIO/ArgTools.jl#46 and a Base change (below), reading and extracting tarballs verifies cleanly; the change is correct and tested on its own.Specialize on callbacks that are only passed on. The API functions and their helpers take the predicate or callback as
f::Functionand pass it on: to the next function, to adoblock, or, for every method with keyword arguments, to the method's keyword body. Julia does not specialize a method on aFunctionargument it only passes on (performance tips), so these methods are compiled forf::Functionand calling the callback is a dynamic dispatch. After callingcreate,list,extract,rewriteandtree_hashwith closures, 31 method instances of Tar haveFunctionin their signature on master; with this change, none. The callbacks are now typedf::F where {F <: Function}; the signatures, and so dispatch, are unchanged.Take a header error's message as the String it is.
read_standard_headerconverted the message of theErrorExceptionthrown by its header checks withString(err.msg), a dynamic call (the field is anAbstractString). Both checks throw throughheader_error, which callserrorwith aString, so the message is asserted to be one instead.Effect on
juliac --trim=safe(JuliaC 0.3.12, Julia master 0d77de6d2c). A program that callsTar.list(with and without a callback) andTar.extractwith a predicate on a tarball path gets 0 verifier errors with this change, JuliaIO/ArgTools.jl#46 and JuliaLang/julia#64448, so thatshowof aSymboldoes not compile the expression printer (check_headershows aSymbolthroughrepr(hdr)), and 264 with only the first two. On masterTar.list(path)stops at ArgTools (2 errors inopen_nolock). Addingcreate,tree_hashandrewriteto that program leaves 8 errors, all increate, all fromreprof aDictinwrite_tarball's error message, which is Base'sshowforPairs and not changed here.Cost. More methods are compiled per callback type. First calls in a fresh process, in this order (median of 5, master; this change vs. without): with the default predicate
create167 ms vs. 168,list137 vs. 151,extract146 vs. 165,tree_hash107 vs. 112,rewrite71 vs. 74; then with new user closurescreate(pred)14 vs. 14 andextract(pred)55 vs. 27, the extract path being compiled for the new closure type.Tests. A new testset calls the API with closures in a fresh Julia process and checks that no Tar method was compiled with
Functionin its signature (a fresh process, since inference and reflection elsewhere can compile such instances); it fails on master, listing them. The full test suite passes on Julia 1.13.2 and on master.🤖 Generated with Claude Code
https://claude.ai/code/session_01HN2L2VxELK7cEP7rLbYHoC