Skip to content
Draft
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
31 changes: 30 additions & 1 deletion src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -2260,6 +2260,35 @@ JL_CALLABLE(jl_f__typebody)
(jl_value_t*)jl_type_type, elt);
}
}


// Before propceeding, look through the module's bindings, and check if there
// is already an existing struct definition that is `equiv_type`.
jl_datatype_t *existing;
// First, get the existing binding:
jl_module_t *module = dt->name->module;
jl_sym_t *name = dt->name->name;
jl_binding_t *b = jl_get_binding(module, name);
jl_binding_partition_t *partition = b->partitions;
while (partition != NULL) {
// If the partition is a datatype, check if it is equivalent to the one we just
// created. If it is, we can return the existing one instead.
existing = (jl_datatype_t*)partition->restriction;
jl_static_show(JL_STDOUT, (jl_value_t*)existing); jl_safe_printf("\n");
jl_safe_printf("nathan\n");
if (existing != NULL && jl_is_datatype(existing) &&
equiv_type((jl_value_t*)dt, (jl_value_t*)existing)) {
// If the existing datatype is equivalent, we can return it instead of the new one.
jl_safe_printf("Found existing equivalent type for %s in module %s\n",
jl_symbol_name(name), jl_symbol_name(module->name));
prev = (jl_value_t*)existing;
}
// If not, continue searching through the bindings.
partition = partition->next;
}



// Optimization: To avoid lots of unnecessary churning, lowering contains an optimization
// that re-uses the typevars of an existing definition (if any exists) for compute the field
// types. If such a previous type exists, there are two possibilities:
Expand Down Expand Up @@ -2324,7 +2353,7 @@ JL_CALLABLE(jl_f__typebody)
}

// this is a heuristic for allowing "redefining" a type to something identical
static int equiv_type(jl_value_t *ta, jl_value_t *tb)
int equiv_type(jl_value_t *ta, jl_value_t *tb)
{
jl_datatype_t *dta = (jl_datatype_t*)jl_unwrap_unionall(ta);
if (!jl_is_datatype(dta))
Expand Down
20 changes: 20 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7795,6 +7795,26 @@ const orig_P36104 = P36104
primitive type P36104 16 end
@test P36104 !== orig_P36104

# Test redefinition undoing
struct X57253
a::Int
b::String
end
a = X57253
struct X57253
a::Int
b::String
c::Float64
end
b = X57253
struct X57253
a::Int
b::String
end
c = X57253
@test a != b
@test a === c

# Malformed invoke
f_bad_invoke(x::Int) = invoke(x, (Any,), x)
@test_throws TypeError f_bad_invoke(1)
Expand Down