Skip to content

Conversation

xal-0
Copy link
Member

@xal-0 xal-0 commented May 23, 2025

Makes more types survive jl_static_show:

  • Symbols
    • Symbols printed in the :var"foo" form use raw string escaping, fixing :var"a\b", :var"a\\", :var"$a", etc.
    • Symbols that require parens use parens (:(=), ...)
  • Signed integers: Except for Int, signed integers print like Int8(1).
  • Floats: floats are printed in a naive but reversible (TODO: double check) way. Inf(16|32|) and NaN(16|32|) are printed, and Float16/Float32 print the type (Float32(1.5)). Float64s are printed with a trailing .0 if it is necessary to disambiguate from Int.

Fixes #52677, #58484 (comment), #58484 (comment), and the specific case mentioned in #58484. Improves the situation for #38902 but does not close it, because a few cases still do not round-trip (inexhaustive list):

  • Non-canonical NaNs
  • BFloat16
  • User-defined primitive types. This one is tricky, because they can have a size different from any type we have literals for.
  • Without don't print field names in static_show of structs #40652 or something similar, precompile statements will still fail with field names.

@xal-0 xal-0 requested a review from topolarity May 23, 2025 19:39
@xal-0 xal-0 added the bugfix This change fixes an existing bug label May 23, 2025
@KristofferC
Copy link
Member

For #40652, can we thread something through to not show the field name in precompile printing contexts? Seems unnecessary to have the correctness of the printing be bike shredded on how people want it to print in the debugger.

@nickrobinson251
Copy link
Contributor

Fixes ... #58484 (comment),

Please can you add tests for Val(Inf) (and maybe Val(-Inf) and Inf and -Inf)?

@topolarity topolarity added backport 1.10 Change should be backported to the 1.10 release backport 1.11 Change should be backported to release-1.11 backport 1.12 Change should be backported to release-1.12 labels May 23, 2025
@topolarity
Copy link
Member

It might be worth printing these floating-point numbers as hexadecimal literals (specifically in a type context):

julia> 0x1p0
1.0

julia> 0x1.8p3
12.0

julia> x = 0x.4p-1
0.125

These can be easy to parse / print bit-accurately, if we have trouble finding floating point <-> decimal conversion routines that we trust to be digit-/bit-accurate.

Of course, if we trust the decimal conversion on all platforms, that's just as good and more human-readable.

n backslashes followed by " => 2n+1 backslashes and "
n backslahes at the end     => 2n backslashes
@KristofferC KristofferC mentioned this pull request May 28, 2025
58 tasks
@xal-0
Copy link
Member Author

xal-0 commented May 28, 2025

Unfortunately we have no hex Float32 literals, and I would like to preserve readability. That's also why I prefer %.17g (with trailing .0 when required) over %.17e: 123.0 is nicer than 1.23000000000000000e+02, 0.5 vs 5.00000000000000000e-01, etc. It's not as nice as Ryu (we still print 0.10000000000000001 instead of 0.1), but it's the best we can do with libc.

xal-0 and others added 3 commits May 28, 2025 11:09
Co-authored-by: Jameson Nash <vtjnash@gmail.com>
Co-authored-by: Jameson Nash <vtjnash@gmail.com>
@topolarity
Copy link
Member

Unfortunately we have no hex Float32 literals

No, but it losslessly casts to Float32 in the same way that Int64 -> Int32 does

That said, I'm all in favor of the readability

#ifdef _P64
n += jl_printf(out, "0x%016" PRIx64, *(uint64_t*)v);
#else
n += jl_printf(out, "0x%08" PRIx32, *(uint32_t*)v);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix-up Pointer types as well?

julia> ccall(:jl_, Cvoid, (Any,), Val(Ptr{Cvoid}(1)))
Base.Val{0x0000000000000001}()

It's a little awkward, because their repr doesn't round-trip either:

julia> Val(Ptr{Cvoid}(1))
Val{Ptr{Nothing} @0x0000000000000001}()

julia> Val{Ptr{Nothing} @0x0000000000000001}()
ERROR: ParseError:
# Error @ REPL[10]:1:18
Val{Ptr{Nothing} @0x0000000000000001}()
#                └─────────────────┘ ── Expected `}`

but regardless of whether it parses properly, I don't think we should be throwing out the type information

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also consider fixing the jl_tvar_type case also. Right now it only prints the name after checking that the parent UnionAll is present, but we should also check that that name is unique, and if not, to find some way to make it unique in printing.

kpamnany pushed a commit to RelationalAI/julia that referenced this pull request Jun 4, 2025
kpamnany pushed a commit to RelationalAI/julia that referenced this pull request Jun 4, 2025
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Makes more types survive `jl_static_show` unambiguously:
- Symbols
- Symbols printed in the `:var"foo"` form use raw string escaping,
fixing `:var"a\b"`, `:var"a\\"`, `:var"$a"`, etc.
  - Symbols that require parens use parens (`:(=)`, ...)
- Signed integers: Except for `Int`, signed integers print like
`Int8(1)`.
- Floats: floats are printed in a naive but reversible (TODO: double
check) way. `Inf(16|32|)` and `NaN(16|32|)` are printed, and
`Float16`/`Float32` print the type (`Float32(1.5)`). `Float64`s are
printed with a trailing `.0` if it is necessary to disambiguate from
`Int`.

Fixes #52677,
#58484 (comment),
#58484 (comment),
and the specific case mentioned in #58484. Improves the situation for
round-trip (inexhaustive list):
- Non-canonical NaNs
- BFloat16
- User-defined primitive types. This one is tricky, because they can
have a size different from any type we have literals for.

(cherry picked from commit b03ef6b)
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Small follow-up to #58512

(cherry picked from commit 36bd3ad)
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Makes more types survive `jl_static_show` unambiguously:
- Symbols
- Symbols printed in the `:var"foo"` form use raw string escaping,
fixing `:var"a\b"`, `:var"a\\"`, `:var"$a"`, etc.
  - Symbols that require parens use parens (`:(=)`, ...)
- Signed integers: Except for `Int`, signed integers print like
`Int8(1)`.
- Floats: floats are printed in a naive but reversible (TODO: double
check) way. `Inf(16|32|)` and `NaN(16|32|)` are printed, and
`Float16`/`Float32` print the type (`Float32(1.5)`). `Float64`s are
printed with a trailing `.0` if it is necessary to disambiguate from
`Int`.

Fixes #52677,
#58484 (comment),
#58484 (comment),
and the specific case mentioned in #58484. Improves the situation for
round-trip (inexhaustive list):
- Non-canonical NaNs
- BFloat16
- User-defined primitive types. This one is tricky, because they can
have a size different from any type we have literals for.

(cherry picked from commit b03ef6b)
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Small follow-up to #58512

(cherry picked from commit 36bd3ad)
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Makes more types survive `jl_static_show` unambiguously:
- Symbols
- Symbols printed in the `:var"foo"` form use raw string escaping,
fixing `:var"a\b"`, `:var"a\\"`, `:var"$a"`, etc.
  - Symbols that require parens use parens (`:(=)`, ...)
- Signed integers: Except for `Int`, signed integers print like
`Int8(1)`.
- Floats: floats are printed in a naive but reversible (TODO: double
check) way. `Inf(16|32|)` and `NaN(16|32|)` are printed, and
`Float16`/`Float32` print the type (`Float32(1.5)`). `Float64`s are
printed with a trailing `.0` if it is necessary to disambiguate from
`Int`.

Fixes #52677,
#58484 (comment),
#58484 (comment),
and the specific case mentioned in #58484. Improves the situation for
round-trip (inexhaustive list):
- Non-canonical NaNs
- BFloat16
- User-defined primitive types. This one is tricky, because they can
have a size different from any type we have literals for.

(cherry picked from commit b03ef6b)
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Small follow-up to #58512

(cherry picked from commit 36bd3ad)
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Makes more types survive `jl_static_show` unambiguously:
- Symbols
- Symbols printed in the `:var"foo"` form use raw string escaping,
fixing `:var"a\b"`, `:var"a\\"`, `:var"$a"`, etc.
  - Symbols that require parens use parens (`:(=)`, ...)
- Signed integers: Except for `Int`, signed integers print like
`Int8(1)`.
- Floats: floats are printed in a naive but reversible (TODO: double
check) way. `Inf(16|32|)` and `NaN(16|32|)` are printed, and
`Float16`/`Float32` print the type (`Float32(1.5)`). `Float64`s are
printed with a trailing `.0` if it is necessary to disambiguate from
`Int`.

Fixes #52677,
#58484 (comment),
#58484 (comment),
and the specific case mentioned in #58484. Improves the situation for
round-trip (inexhaustive list):
- Non-canonical NaNs
- BFloat16
- User-defined primitive types. This one is tricky, because they can
have a size different from any type we have literals for.

(cherry picked from commit b03ef6b)
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Small follow-up to #58512

(cherry picked from commit 36bd3ad)
kpamnany added a commit to RelationalAI/julia that referenced this pull request Jun 5, 2025
* static-show: improve accuracy of some printings (JuliaLang#52799)

- Show strings with escaping, rather than trying to output the text
unmodified.
- Show symbols with the same formatting as Strings
- Avoid accidentally defining a broken Core.show method for NamedTuple

* Make more types jl_static_show unambiguously (JuliaLang#58512)

Makes more types survive `jl_static_show` unambiguously:
- Symbols
- Symbols printed in the `:var"foo"` form use raw string escaping,
fixing `:var"a\b"`, `:var"a\\"`, `:var"$a"`, etc.
  - Symbols that require parens use parens (`:(=)`, ...)
- Signed integers: Except for `Int`, signed integers print like
`Int8(1)`.
- Floats: floats are printed in a naive but reversible (TODO: double
check) way. `Inf(16|32|)` and `NaN(16|32|)` are printed, and
`Float16`/`Float32` print the type (`Float32(1.5)`). `Float64`s are
printed with a trailing `.0` if it is necessary to disambiguate from
`Int`.

Fixes JuliaLang#52677,
JuliaLang#58484 (comment),
JuliaLang#58484 (comment),
and the specific case mentioned in JuliaLang#58484. Improves the situation for
round-trip (inexhaustive list):
- Non-canonical NaNs
- BFloat16
- User-defined primitive types. This one is tricky, because they can
have a size different from any type we have literals for.

* Use `julia__gnu_h2f_ieee` instead of `julia_half_to_float`

`julia_half_to_float` came in with an LLVM version upgrade after
v1.10.

---------

Co-authored-by: Jameson Nash <vtjnash@gmail.com>
Co-authored-by: Sam Schweigel <33556084+xal-0@users.noreply.github.com>
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Makes more types survive `jl_static_show` unambiguously:
- Symbols
- Symbols printed in the `:var"foo"` form use raw string escaping,
fixing `:var"a\b"`, `:var"a\\"`, `:var"$a"`, etc.
  - Symbols that require parens use parens (`:(=)`, ...)
- Signed integers: Except for `Int`, signed integers print like
`Int8(1)`.
- Floats: floats are printed in a naive but reversible (TODO: double
check) way. `Inf(16|32|)` and `NaN(16|32|)` are printed, and
`Float16`/`Float32` print the type (`Float32(1.5)`). `Float64`s are
printed with a trailing `.0` if it is necessary to disambiguate from
`Int`.

Fixes #52677,
#58484 (comment),
#58484 (comment),
and the specific case mentioned in #58484. Improves the situation for
round-trip (inexhaustive list):
- Non-canonical NaNs
- BFloat16
- User-defined primitive types. This one is tricky, because they can
have a size different from any type we have literals for.

(cherry picked from commit b03ef6b)
KristofferC pushed a commit that referenced this pull request Jun 5, 2025
Small follow-up to #58512

(cherry picked from commit 36bd3ad)
kpamnany pushed a commit to RelationalAI/julia that referenced this pull request Jun 9, 2025
KristofferC pushed a commit that referenced this pull request Jun 25, 2025
Makes more types survive `jl_static_show` unambiguously:
- Symbols
- Symbols printed in the `:var"foo"` form use raw string escaping,
fixing `:var"a\b"`, `:var"a\\"`, `:var"$a"`, etc.
  - Symbols that require parens use parens (`:(=)`, ...)
- Signed integers: Except for `Int`, signed integers print like
`Int8(1)`.
- Floats: floats are printed in a naive but reversible (TODO: double
check) way. `Inf(16|32|)` and `NaN(16|32|)` are printed, and
`Float16`/`Float32` print the type (`Float32(1.5)`). `Float64`s are
printed with a trailing `.0` if it is necessary to disambiguate from
`Int`.

Fixes #52677,
#58484 (comment),
#58484 (comment),
and the specific case mentioned in #58484. Improves the situation for
round-trip (inexhaustive list):
- Non-canonical NaNs
- BFloat16
- User-defined primitive types. This one is tricky, because they can
have a size different from any type we have literals for.

(cherry picked from commit b03ef6b)
KristofferC pushed a commit that referenced this pull request Jun 25, 2025
Small follow-up to #58512

(cherry picked from commit 36bd3ad)
@KristofferC
Copy link
Member

Backporting this to 1.11 gives:

Test Failed at /home/kc/julia1.11/test/show.jl:1562
  Expression: v === eval(Meta.parse(static_shown(v)))
   Evaluated: Float16(1.0) === Inf16

Test Failed at /home/kc/julia1.11/test/show.jl:1562
  Expression: v === eval(Meta.parse(static_shown(v)))
   Evaluated: Float16(1.5) === Inf16

Test Failed at /home/kc/julia1.11/test/show.jl:1562
  Expression: v === eval(Meta.parse(static_shown(v)))
   Evaluated: Float16(0.4893) === Inf16

Test Failed at /home/kc/julia1.11/test/show.jl:1562
  Expression: v === eval(Meta.parse(static_shown(v)))
   Evaluated: Float16(0.00010014) === Inf16
....

Am I missing some other PR that is needed?

@kpamnany
Copy link
Member

kpamnany commented Jun 25, 2025

We needed #52799 also, to backport this to our 1.10 build.

@KristofferC
Copy link
Member

That should already be on 1.11 though?

@kpamnany
Copy link
Member

Ah, okay. Then I don't know. Sorry.

@topolarity
Copy link
Member

Probably related to the Float16 intrinsic fixes that @xal-0 made in 1.12?

@KristofferC
Copy link
Member

I think it was due to a missing header declaration of a function which defined it implicitly and maybe caused undefined behavior? On CI this errored and after fixing that it seems like things are OK. Could that be a possible scenario?

KristofferC pushed a commit that referenced this pull request Jul 3, 2025
Makes more types survive `jl_static_show` unambiguously:
- Symbols
- Symbols printed in the `:var"foo"` form use raw string escaping,
fixing `:var"a\b"`, `:var"a\\"`, `:var"$a"`, etc.
  - Symbols that require parens use parens (`:(=)`, ...)
- Signed integers: Except for `Int`, signed integers print like
`Int8(1)`.
- Floats: floats are printed in a naive but reversible (TODO: double
check) way. `Inf(16|32|)` and `NaN(16|32|)` are printed, and
`Float16`/`Float32` print the type (`Float32(1.5)`). `Float64`s are
printed with a trailing `.0` if it is necessary to disambiguate from
`Int`.

Fixes #52677,
#58484 (comment),
#58484 (comment),
and the specific case mentioned in #58484. Improves the situation for
round-trip (inexhaustive list):
- Non-canonical NaNs
- BFloat16
- User-defined primitive types. This one is tricky, because they can
have a size different from any type we have literals for.

(cherry picked from commit b03ef6b)
KristofferC pushed a commit that referenced this pull request Jul 3, 2025
Small follow-up to #58512

(cherry picked from commit 36bd3ad)
@KristofferC KristofferC mentioned this pull request Aug 19, 2025
65 tasks
DilumAluthge added a commit that referenced this pull request Sep 5, 2025
Backported PRs:
- [x] #54840 <!-- Add boundscheck in speccache_eq to avoid OOB access
due to data race -->
- [x] #42080 <!-- recommend explicit `using Foo: Foo, ...` in package
code (was: "using considered harmful") -->
- [x] #58127 <!-- [DOC] Update installation docs: /downloads/ =>
/install/ -->
- [x] #58202 <!-- [release-1.11] malloc: use jl_get_current_task to fix
null check -->
- [x] #58584 <!-- Make `Ptr` values static-show w/ type-information -->
- [x] #58637 <!-- Make late gc lower handle insertelement of alloca use.
-->
- [x] #58837 <!-- fix null comparisons for non-standard address spaces
-->
- [x] #57826 <!-- Add a `similar` method for `Type{<:CodeUnits}` -->
- [x] #58293 <!-- fix trailing indices stackoverflow in reinterpreted
array -->
- [x] #58887 <!-- Pkg: Allow configuring can_fancyprint(io::IO) using
IOContext -->
- [x] #58937 <!-- Fix nthreadpools size in JLOptions -->
- [x] #58978 <!-- Fix precompilepkgs warn loaded setting -->
- [x] #58998 <!-- Bugfix: Use Base.aligned_sizeof instead of sizeof in
Mmap.mmap -->
- [x] #59120 <!-- Fix memory order typo in "src/julia_atomics.h" -->
- [x] #59170 <!-- Clarify and enhance confusing precompile test -->

Need manual backport:
- [ ] #56329 <!-- loading: clean up more concurrency issues -->
- [ ] #56956 <!-- Add "mea culpa" to foreign module assignment error.
-->
- [ ] #57035 <!-- linux: workaround to avoid deadlock inside
dl_iterate_phdr in glibc -->
- [ ] #57089 <!-- Block thread from receiving profile signal with
stackwalk lock -->
- [ ] #57249 <!-- restore non-freebsd-unix fix for profiling -->
- [ ] #58011 <!-- Remove try-finally scope from `@time_imports`
`@trace_compile` `@trace_dispatch` -->
- [ ] #58062 <!-- remove unnecessary edge from `exp_impl` to `pow` -->
- [ ] #58157 <!-- add showing a string to REPL precompile workload -->
- [ ] #58209 <!-- Specialize `one` for the `SizedArray` test helper -->
- [ ] #58108 <!-- Base.get_extension & Dates.format made public -->
- [ ] #58356 <!-- codegen: remove readonly from abstract type calling
convention -->
- [ ] #58415 <!-- [REPL] more reliable extension loading -->
- [ ] #58510 <!-- Don't filter `Core` methods from newly-inferred list
-->
- [ ] #58110 <!-- relax dispatch for the `IteratorSize` method for
`Generator` -->
- [ ] #58965 <!-- Fix `hygienic-scope`s in inner macro expansions -->
- [ ] #58971 <!-- Fix alignment of failed precompile jobs on CI -->
- [ ] #59066 <!-- build: Also pass -fno-strict-aliasing for C++ -->

Contains multiple commits, manual intervention needed:
- [ ] #55877 <!-- fix FileWatching designs and add workaround for a stat
bug on Apple -->
- [ ] #56755 <!-- docs: fix scope type of a `struct` to hard -->
- [ ] #57809 <!-- Fix fptrunc Float64 -> Float16 rounding through
Float32 -->
- [ ] #57398 <!-- Make remaining float intrinsics require float
arguments -->
- [ ] #56351 <!-- Fix `--project=@script` when outside script directory
-->
- [ ] #57129 <!-- clarify that time_ns is monotonic -->
- [ ] #58134 <!-- Note annotated string API is experimental in Julia
1.11 in HISTORY.md -->
- [ ] #58401 <!-- check that hashing of types does not foreigncall
(`jl_type_hash` is concrete evaluated) -->
- [ ] #58435 <!-- Fix layout flags for types that have oddly sized
primitive type fields -->
- [ ] #58483 <!-- Fix tbaa usage when storing into heap allocated
immutable structs -->
- [ ] #58512 <!-- Make more types jl_static_show readably -->
- [ ] #58012 <!-- Re-enable tab completion of kwargs for large method
tables -->
- [ ] #58683 <!-- Add 0 predecessor to entry basic block and handle it
in inlining -->
- [ ] #59112 <!-- Add builtin function name to add methods error -->

Non-merged PRs with backport label:
- [ ] #59329 <!-- aotcompile: destroy LLVM context after serializing
combined module -->
- [ ] #58848 <!-- Set array size only when safe to do so -->
- [ ] #58535 <!-- gf.c: include const-return methods in
`--trace-compile` -->
- [ ] #58038 <!-- strings/cstring: `transcode`: prevent Windows sysimage
invalidation -->
- [ ] #57604 <!-- `@nospecialize` for `string_index_err` -->
- [ ] #57366 <!-- Use ptrdiff_t sized offsets for gvars_offsets to allow
large sysimages -->
- [ ] #56890 <!-- Enable getting non-boxed LLVM type from Julia Type -->
- [ ] #56823 <!-- Make version of opaque closure constructor in world
-->
- [ ] #55958 <!-- also redirect JL_STDERR etc. when redirecting to
devnull -->
- [ ] #55956 <!-- Make threadcall gc safe -->
- [ ] #55534 <!-- Set stdlib sources as read-only during installation
-->
- [ ] #55499 <!-- propagate the terminal's `displaysize` to the
`IOContext` used by the REPL -->
- [ ] #55458 <!-- Allow for generically extracting unannotated string
-->
- [ ] #55457 <!-- Make AnnotateChar equality consider annotations -->
- [ ] #55220 <!-- `isfile_casesensitive` fixes on Windows -->
- [ ] #53957 <!-- tweak how filtering is done for what packages should
be precompiled -->
- [ ] #51479 <!-- prevent code loading from lookin in the versioned
environment when building Julia -->
- [ ] #50813 <!-- More doctests for Sockets and capitalization fix -->
- [ ] #50157 <!-- improve docs for `@inbounds` and
`Base.@propagate_inbounds` -->

---------

Co-authored-by: Kiran Pamnany <kpamnany@users.noreply.github.com>
Co-authored-by: adienes <51664769+adienes@users.noreply.github.com>
Co-authored-by: Gabriel Baraldi <baraldigabriel@gmail.com>
Co-authored-by: Keno Fischer <keno@juliacomputing.com>
Co-authored-by: Simeon David Schaub <simeon@schaub.rocks>
Co-authored-by: Jameson Nash <vtjnash@gmail.com>
Co-authored-by: Alex Arslan <ararslan@comcast.net>
Co-authored-by: Fons van der Plas <fonsvdplas@gmail.com>
Co-authored-by: Ian Butterworth <i.r.butterworth@gmail.com>
Co-authored-by: JonasIsensee <jonas.isensee@web.de>
Co-authored-by: Curtis Vogt <curtis.vogt@gmail.com>
Co-authored-by: Dilum Aluthge <dilum@aluthge.com>
Co-authored-by: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com>
Co-authored-by: DilumAluthge <5619885+DilumAluthge@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport 1.10 Change should be backported to the 1.10 release backport 1.11 Change should be backported to release-1.11 bugfix This change fixes an existing bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

trace-compile precompile statements incorrect for non-Int signed integer types
6 participants