Skip to content

Conversation

@topolarity
Copy link
Member

The idea here is that we can reasonably expect that types with default inner constructors can be constructed as Foo(field1, field2, field3) in most cases. That's because, if an outer constructor "covers" the full-length default constructor, then it can only construct the object it needs via @invoke, reinterpret, Expr(:new, ...) or similar workarounds (the full-length default constructor is not available via dispatch and neither is new)

This gives us a compact output for the majority of isbits types:

julia> struct Foo
           x::Int
           y::Int
           z::Int
       end
julia> ccall(:jl_, Cvoid, (Any,), Foo(1,2,3))
Foo(1, 2, 3)

but also evaluates to the correct value when inner constructors are present that do strange things:

julia> struct Bar
           x::Int
           y::Int
           z::Int
           Bar(z, y, x) = new(x, y, z)
       end
julia> ccall(:jl_, Cvoid, (Any,), Bar(1,2,3))
Base.reinterpret(Bar, (1, 2, 3))

Mostly a proof-of-concept to illustrate this approach. Lots of tests still needed (and hasdefaultctors may need to be tracked very differently)

@topolarity topolarity requested a review from vtjnash June 3, 2025 22:31
We can reasonably expect that types with default inner constructors can
be constructed as `Foo(fields...)` in most cases.

That's because, if an outer constructor "covers" the full-length default
constructor in the sense that calls are dispatched there instead of to
the default ctor, then it can only construct the object it needs via
`@invoke`, `reinterpret`, `Expr(:new, ...)` or similar workarounds.
@topolarity topolarity force-pushed the ct/staticshow-custom-ctors branch from d551536 to b7c28b6 Compare June 4, 2025 01:17
@vtjnash vtjnash closed this Sep 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants