Julia v1.14 Release Notes
New language features
It is now possible to control which version of the Julia syntax will be used to parse a package by setting the
compat.juliaorsyntax.julia_versionkey in Project.toml. This feature is similar to the notion of "editions" in other language ecosystems and will allow non-breaking evolution of Julia syntax in future versions. See the "Syntax Versioning" section in the code loading documentation (#60018).ᵅ(U+U+1D45),ᵋ(U+1D4B),ᶲ(U+1DB2),˱(U+02F1),˲(U+02F2), andₔ(U+2094) can now also be used as operator suffixes, accessible as\^alpha,\^epsilon,\^ltphi,\_<,\_>, and\_schwaat the REPL (#60285).The
@labelmacro can now create labeled blocks that can be exited early withbreak name [value]. Use@label name exprfor named blocks or@label exprfor anonymous blocks. Anonymous@labelblocks participate in the default break scope: a plainbreakorbreak _exits the innermost breakable scope, whether it is a loop or an@labelblock. Thecontinuestatement also supports labels withcontinue nameto continue a labeled loop (#60481).typegroupblocks allow defining mutually recursive struct types that reference each other in their field types. All types in the group are resolved atomically at the end of the block (#60569).Primitive types with non-byte-multiple logical widths can now be defined (#61359).
Introduced explicitly wrapping arithmetic operators
+%,-%,*%to annotate arithmetic operations that are semantically safe to wrap/overflow. Their behavior is currently identical to the default+,-,*operators. However, in a future version, there may be opt-in support to detect unannotated wrapping in the default operators (#50790).
Language changes
Type{T} <: Snow holds only if every type==toTis an instance ofS, fixing a long-standing soundness hole where e.g.Type{Int} <: DataTypeheld even though types likeTuple{S} where S<:Intare==(andisa) their canonical spelling without beingDataTypes. In particularType{T}is no longer a subtype of any single kind: use a union of kinds instead (e.g.Type{Int} <: Union{DataType,UnionAll}holds).isaand dispatch of type values are unaffected, and a method onType{Int}remains more specific than one onDataType(#33136, #62141).
Compiler/Runtime improvements
Type inference now refines field types through conditional checks and call signatures. For example, after
if !isnothing(x.field), inference knowsx.fieldis notnothingwithin the branch. Similarly, after a call likefunc(x.field)wherefunc(::Int)is the only matching method, inference refinesx.fieldtoInt. This works for immutable struct fields andconstfields of mutable structs. Mutable (non-const) fields are not supported due to the lack of per-object memory effect tracking; for those, the recommended pattern remains storing the field value in a local variable before the check (e.g.val = x.field; if !isnothing(val) ... end) (#41199, #47574).Stack traces now show full method signatures with argument types for inlined frames, matching the display of non-inlined frames (#53925).
Stack traces of errors raised while loading code no longer show the internals of the code loading machinery, which are collapsed to the single frame that entered loading. Frames for user code that runs during loading are unaffected. Set the
JULIA_STACKTRACE_FULL_LOADINGenvironment variable totrueto show them (#52988).Parallel package precompilation now coordinates CPU usage across both the precompile worker processes and the LLVM threads each spawns to compile its native image, sharing a single thread budget so idle cores are filled during the long tail without oversubscribing the machine when many packages compile at once. The total budget can be set with the new
JULIA_PRECOMPILE_THREADSenvironment variable (#61958).
Command-line option changes
-P <project>is now a shorthand for--project <project>(#59867).
Multi-threading changes
The return type of
fetch(::Task)is now inferred precisely when inference can determine the code the task was created to run (for examplefetch(Threads.@spawn f(x))), instead of always beingAny. Correspondingly, assigning to theresultfield of aTaskvia property syntax (t.result = v) now throws an error: the result of a task is determined by the return value of its code, and the runtime and the compiler now rely on this correspondence. To pass a value to a suspended task, useschedule(t, val)oryieldto(t, val)(#59221).New functions
Threads.atomic_fence_heavyandThreads.atomic_fence_lightprovide support for asymmetric atomic fences, speeding up atomic synchronization where one side of the synchronization runs significantly less often than the other (#60311).Threads.@threadsnow supports array comprehensions with syntax like@threads [f(i) for i in 1:n], filtered comprehensions like@threads [f(i) for i in 1:n if condition(i)], typed comprehensions like@threads Float64[f(i) for i in 1:n], and multi-dimensional comprehensions like@threads [f(i,j) for i in 1:n, j in 1:m](preserves dimensions). All scheduling options (:static,:dynamic,:greedy) are supported. Results preserve element order for:staticand:dynamicscheduling;:greedydoes not guarantee order. Non-indexable iterators are also supported (#59019).The task scheduler now avoids O(nthreads) wake overhead on every
@spawn, significantly reducing threading overhead particularly on highly oversubscribed machines. Benchmarks show up to 1000x reduction in spawn time in such scenarios (#61826).Threads.Atomicnow supports the reference form of the@atomic,@atomicswap,@atomicreplace, and@atomiconcemacros (e.g.@atomic a[],@atomic a[] = v,@atomic a[] += 1), which allows the memory ordering to be specified explicitly and makes atomic read-modify-write operations syntactically clear (#62382).
Build system changes
New library functions
tap(f)creates a function that callsf(x)for side effects and returnsx(#61340).Base.set_binding_visibility!sets the declared visibility (:none,:public, or:export) of a name in a module, allowing anexportorpublicdeclaration to be retracted programmatically (#62131).Base.generating_output()has been madepublic(but not exported) to allow checking whether the current process is performing compilation for a pkgimage/sysimage (#61224).Base.isfieldatomic(t, s)has been madepublic(but not exported); it reports whether a fieldsof a typetis declared@atomic.Base.raw_substringis an unexported, public constructor to build aSubStringwithout checking for valid string indices.Base.unannotate(::AnnotatedString)returns the underlying un-annotated string of the input string.Base.include_mapexprs(mod)is an unexported, public function returning the non-identitymapexprfunctions used byinclude(mapexpr, …)calls while loading the package rooted atmod, keyed by(including_module, absolute_path). The table is stored inside the package image, so it survives precompilation; revision tools (e.g. Revise) use it to re-apply the original transform when aninclude(mapexpr, …)-ed file is edited.
New library features
IOContextsupports a new booleanhexunsignedoption that allows for printing unsigned integers in decimal instead of hexadecimal (#60267).lazy"..."strings now support a flaglazy"..."cthat addscompactandlimitflags to theIOContextfor final output-string generation (#61887).The
StringViewtype wraps anAbstractVector{UInt8}and interprets it as a UTF-8 encoded string, superseding the StringViews.jl package (#60526).Package precompilation now supports running precompilation in a background task and has new interactive keyboard controls:
cto cleanly cancel immediately,dto detach,ifor a profile peek,vto toggle verbose mode showing elapsed time, CPU%, and memory usage, and?for help (#60943).Instances of an
Enumcan now be given their own docstrings within the@enumdefinition (#61955).New methods
readdir(path, DirEntry)andreaddir(::DirEntry, DirEntry)return directory contents along with the type of the entries in a vector of newDirEntryobjects to provide more efficientisfileetc. checks.readdir(::DirEntry)accepts aDirEntryas input and, likereaddir(::AbstractString), returns aVector{String}of names.DirEntryis exported fromBase(#55358).When the display height is too small to show any array entries, the
text/plainarray display (used e.g. by the REPL and when logging values with@infoetc.) now shows as many entries as fit on a single line, truncated to the display width, instead of showing no data at all (#62543).
Standard library changes
codepoint(c)now succeeds for overlong encodings.Base.ismalformed,Base.isoverlong, andBase.show_invalidare nowpublicand documented (but not exported) (#55152).
JuliaSyntaxHighlighting
LinearAlgebra
Markdown
Support "raw" or "inline" HTML inside Markdown data (#60629, #60632, #60732).
Support autolinks for email addresses (#60570).
Many improvements and bugfixes for rendering Markdown lists in a terminal (#55456, #60519).
Strikethrough text via
~strike~or~~through~~is now supported by the Markdown parser (#60537).Many, many bug fixes and minor tweaks; overall behavior is now much closer to CommonMark (#59977, #60502).
Profile
Random
REPL
Test
@test,@test_throws, and@test_brokennow support acontextkeyword argument that provides additional information displayed on test failure. This is useful for debugging which specific case failed in parameterized tests (#60501).@test_throws,@test_warn,@test_nowarn,@test_logs, and@test_deprecatednow supportbrokenandskipkeyword arguments for consistency with@test(#60543).New functions
detect_closure_boxesanddetect_closure_boxes_allfind methods that allocateCore.Boxin their lowered code, which can indicate performance issues from captured variables in closures (#60478).
Dates
unix2datetimenow accepts a keyword argumentlocaltime=trueto use the host system's local time zone instead of UTC (#50296).
InteractiveUtils
less/@lessandedit/@editare now supported for documented variables (#53539).A new
@methodsmacro lists all methods applicable to a call expression, using the types of the given arguments, e.g.@methods isvalid('a', 1)or@methods isvalid(::AbstractChar, ::Integer)(#62311).
Dates
External dependencies
Tooling Improvements
Deprecated or removed
Storing into a
Threads.Atomicwith the plaina[] = vform (i.e.setindex!) is deprecated in favor of@atomic a[] = v. The plain form makes read-modify-write expressions such asa[] += 1look atomic even though they expand to a separate, non-atomic load and store; use@atomic a[] += 1orThreads.atomic_add!for an atomic update. Reading witha[]is unchanged (#62382).