Skip to content

static_show: Use reinterpret for types with non-default constructors #58627

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -2378,8 +2378,20 @@ JL_CALLABLE(jl_f__equiv_typedef)

JL_CALLABLE(jl_f__defaultctors)
{
JL_NARGS(_defaultctors, 2, 2);
jl_ctor_def(args[0], args[1]);
JL_NARGS(_defaultctors, 3, 3);

jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(args[0]);
JL_TYPECHK(_defaultctors, datatype, (jl_value_t *)dt);
JL_TYPECHK(_defaultctors, linenumbernode, args[1]);
JL_TYPECHK(_defaultctors, bool, args[2]);

if (args[2] == jl_true) {
jl_ctor_def(args[0], args[1]);
dt->name->hasdefaultctors = 1;
} else {
dt->name->hasdefaultctors = 0;
}

return jl_nothing;
}

Expand Down
1 change: 1 addition & 0 deletions src/datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *modu
tn->abstract = abstract;
tn->mutabl = mutabl;
tn->mayinlinealloc = 0;
tn->hasdefaultctors = 0;
tn->partial = NULL;
tn->atomicfields = NULL;
tn->constfields = NULL;
Expand Down
1 change: 1 addition & 0 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3133,6 +3133,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_tuple_typename = jl_anytuple_type->name;
// fix some miscomputed values, since we didn't know this was going to be a Tuple in jl_precompute_memoized_dt
jl_tuple_typename->wrapper = (jl_value_t*)jl_anytuple_type; // remove UnionAll wrappers
jl_tuple_typename->hasdefaultctors = 1;
jl_anytuple_type->isconcretetype = 0;
jl_anytuple_type->maybe_subtype_of_cache = 0;
jl_anytuple_type->layout = NULL;
Expand Down
4 changes: 2 additions & 2 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1023,8 +1023,8 @@
;; added alongside (replacing) the old ones, than to not have them and need them.
;; Commonly Revise.jl should be used to figure out actually which methods should
;; actually be deleted or added anew.
,(if (null? defs)
`(call (core _defaultctors) ,newdef (inert ,loc))
(call (core _defaultctors) ,newdef (inert ,loc) ,(if (null? defs) '(true) '(false)))
,(if (null? defs) '()
`(scope-block
(block
(hardscope)
Expand Down
3 changes: 2 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,8 @@ typedef struct {
uint8_t abstract:1;
uint8_t mutabl:1;
uint8_t mayinlinealloc:1;
uint8_t _unused:5;
uint8_t hasdefaultctors:1;
uint8_t _unused:4;
_Atomic(uint8_t) cache_entry_count; // (approximate counter of TypeMapEntry for heuristics)
uint8_t max_methods; // override for inference's max_methods setting (0 = no additional limit or relaxation)
uint8_t constprop_heustic; // override for inference's constprop heuristic
Expand Down
20 changes: 18 additions & 2 deletions src/rtutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1348,16 +1348,29 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
// typeof(v) isa DataType, so v is an *instance of* a type that is a Datatype,
// meaning v is e.g. an instance of a struct. These are printed as a call to a
// type constructor, such as e.g. `Base.UnitRange{Int64}(start=1, stop=2)`

int istuple = jl_is_tuple_type(vt), isnamedtuple = jl_is_namedtuple_type(vt);
int isprimitivetype = jl_is_primitivetype(vt);

// In many cases, default constructors may not be available (e.g. primitive types
// never have them), so print these as "reinterpret(Foo, ...)" to make sure that
// these round-trip as expected.
int reinterpret = (!vt->name->hasdefaultctors && !istuple && !isnamedtuple) || isprimitivetype;

size_t tlen = jl_datatype_nfields(vt);
if (reinterpret)
n += jl_printf(out, "Base.reinterpret(");
if (isnamedtuple) {
if (tlen == 0)
n += jl_printf(out, "NamedTuple");
}
else if (!istuple) {
n += jl_static_show_x(out, (jl_value_t*)vt, depth, ctx);
}
n += jl_printf(out, "(");
if (reinterpret)
n += jl_printf(out, ", ");
if (!isprimitivetype)
n += jl_printf(out, "(");
size_t nb = jl_datatype_size(vt);
if (nb > 0 && tlen == 0) {
uint8_t *data = (uint8_t*)v;
Expand Down Expand Up @@ -1405,7 +1418,10 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
n += jl_static_show_next_(out, next, v, depth, ctx);
}
}
n += jl_printf(out, ")");
if (!isprimitivetype)
n += jl_printf(out, ")");
if (reinterpret)
n += jl_printf(out, ")");
}
else {
n += jl_printf(out, "<?#%p::", (void*)v);
Expand Down
7 changes: 5 additions & 2 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1520,7 +1520,7 @@ function static_shown(x)
end

# Test for PR 17803
@test static_shown(Int128(-1)) == "Int128(0xffffffffffffffffffffffffffffffff)"
@test static_shown(Int128(-1)) == "Base.reinterpret(Int128, 0xffffffffffffffffffffffffffffffff)"

# PR #22160
@test static_shown(:aa) == ":aa"
Expand Down Expand Up @@ -1618,9 +1618,12 @@ struct var"%X%" end # Invalid name without '#'
Val(1), Val(Int8(1)), Val(Int16(1)), Val(Int32(1)), Val(Int64(1)), Val(Int128(1)),
Val(UInt(1)), Val(UInt8(1)), Val(UInt16(1)), Val(UInt32(1)), Val(UInt64(1)), Val(UInt128(1)),

# Primitive types should round-trip via reinterpret(...)
Val(Char('u')), Val(Char('\0')),

# BROKEN
# Symbol("a\xffb"),
# User-defined primitive types
# User-defined primitive types with size not a power-of-two
# Non-canonical NaNs
# BFloat16
)
Expand Down