mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fixes to distinct inline conversions.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
- Fix bug with @jump miscompile.
|
||||
- Bit negate does implicit integer promotion.
|
||||
- Bitstructs, unions and flexible arrays now correctly emitted in headers.
|
||||
- Fix distinct inline conversions.
|
||||
|
||||
### Stdlib changes
|
||||
- Added `remove_first_item` `remove_last_item` and `remove_item` as aliases for the `match` functions.
|
||||
|
||||
@@ -2440,7 +2440,6 @@ void type_mangle_introspect_name_to_buffer(Type *type);
|
||||
AlignSize type_abi_alignment(Type *type);
|
||||
bool type_func_match(Type *fn_type, Type *rtype, unsigned arg_count, ...);
|
||||
AlignSize type_alloca_alignment(Type *type);
|
||||
Type *type_find_common_ancestor(Type *left, Type *right);
|
||||
Type *type_find_largest_union_element(Type *type);
|
||||
Type *type_find_max_type(Type *type, Type *other);
|
||||
Type *type_find_max_type_may_fail(Type *type, Type *other);
|
||||
|
||||
@@ -681,6 +681,7 @@ typedef enum
|
||||
TYPE_F128,
|
||||
TYPE_FLOAT_LAST = TYPE_F128,
|
||||
TYPE_NUM_LAST = TYPE_FLOAT_LAST,
|
||||
TYPE_DISTINCT,
|
||||
TYPE_ANY,
|
||||
TYPE_INTERFACE,
|
||||
TYPE_ANYFAULT,
|
||||
@@ -694,7 +695,6 @@ typedef enum
|
||||
TYPE_BITSTRUCT,
|
||||
TYPE_FAULTTYPE,
|
||||
TYPE_TYPEDEF,
|
||||
TYPE_DISTINCT,
|
||||
TYPE_SLICE,
|
||||
TYPE_ARRAY,
|
||||
TYPE_FIRST_ARRAYLIKE = TYPE_ARRAY,
|
||||
|
||||
@@ -1878,25 +1878,50 @@ Type *type_decay_array_pointer(Type *type)
|
||||
return type;
|
||||
}
|
||||
}
|
||||
#define MAX_SEARCH_DEPTH 512
|
||||
static inline Type *type_find_max_distinct_type(Type *left, Type *right)
|
||||
{
|
||||
assert(left == left->canonical && right == right->canonical);
|
||||
assert(left != right);
|
||||
assert(left->type_kind == TYPE_DISTINCT && right->type_kind == TYPE_DISTINCT);
|
||||
static Type *left_types[MAX_SEARCH_DEPTH];
|
||||
int depth = 0;
|
||||
while (depth < MAX_SEARCH_DEPTH)
|
||||
{
|
||||
left_types[depth++] = left;
|
||||
if (left->type_kind != TYPE_DISTINCT || !left->decl->is_substruct) break;
|
||||
left = left->decl->distinct->type;
|
||||
if (left == right) return right;
|
||||
}
|
||||
if (depth == MAX_SEARCH_DEPTH)
|
||||
{
|
||||
error_exit("Common ancestor search depth %d exceeded.", MAX_SEARCH_DEPTH);
|
||||
}
|
||||
assert(left != right);
|
||||
while (true)
|
||||
{
|
||||
for (int i = 0; i < depth; i++)
|
||||
{
|
||||
if (right == left_types[i]) return right;
|
||||
}
|
||||
if (right->type_kind != TYPE_DISTINCT || !right->decl->is_substruct) return NULL;
|
||||
right = right->decl->distinct->type;
|
||||
if (left == right) return right;
|
||||
}
|
||||
}
|
||||
|
||||
Type *type_find_max_type(Type *type, Type *other)
|
||||
{
|
||||
type = type->canonical;
|
||||
other = other->canonical;
|
||||
|
||||
assert(!type_is_optional(type) && !type_is_optional(other));
|
||||
|
||||
RETRY_DISTINCT:
|
||||
if (type == other) return type;
|
||||
|
||||
if (type == type_wildcard) return other;
|
||||
if (other == type_wildcard) return type;
|
||||
|
||||
// Lower inlined distinct types.
|
||||
while (type->type_kind == TYPE_DISTINCT && type->decl->is_substruct) type = type->decl->distinct->type;
|
||||
while (other->type_kind == TYPE_DISTINCT && other->decl->is_substruct) other = other->decl->distinct->type;
|
||||
|
||||
// We may now have a match.
|
||||
if (type == other) return type;
|
||||
|
||||
// Sort types
|
||||
if (type->type_kind > other->type_kind)
|
||||
{
|
||||
@@ -1926,7 +1951,7 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
if (other->type_kind == TYPE_VECTOR) return other;
|
||||
return type_find_max_num_type(type, other);
|
||||
case ALL_FLOATS:
|
||||
if (other->type_kind == TYPE_DISTINCT && type_is_float(other->decl->distinct->type)) return other;
|
||||
if (other->type_kind == TYPE_DISTINCT && type_is_float(type_flatten(other))) return other;
|
||||
if (other->type_kind == TYPE_VECTOR) return other;
|
||||
return type_find_max_num_type(type, other);
|
||||
case TYPE_ANY:
|
||||
@@ -2000,9 +2025,6 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
return NULL;
|
||||
case TYPE_TYPEDEF:
|
||||
UNREACHABLE
|
||||
case TYPE_DISTINCT:
|
||||
// distinct + any other type => no
|
||||
return NULL;
|
||||
case TYPE_ARRAY:
|
||||
// array + [slice, other array, vector] => no
|
||||
return NULL;
|
||||
@@ -2012,53 +2034,23 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
case TYPE_VECTOR:
|
||||
// No implicit conversion between vectors
|
||||
return NULL;
|
||||
case TYPE_DISTINCT:
|
||||
if (other->type_kind == TYPE_DISTINCT)
|
||||
{
|
||||
return type_find_max_distinct_type(type, other);
|
||||
}
|
||||
// Try matching with its inline type
|
||||
if (type->decl->is_substruct)
|
||||
{
|
||||
type = type->decl->distinct->type;
|
||||
goto RETRY_DISTINCT;
|
||||
}
|
||||
// distinct + any other type => no
|
||||
return NULL;
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
#define MAX_SEARCH_DEPTH 512
|
||||
|
||||
Type *type_find_common_ancestor(Type *left, Type *right)
|
||||
{
|
||||
if (left == right) return left;
|
||||
left = left->canonical;
|
||||
right = right->canonical;
|
||||
if (left == right) return left;
|
||||
if (left->type_kind != right->type_kind) return NULL;
|
||||
if (left->type_kind == TYPE_POINTER)
|
||||
{
|
||||
Type *common = type_find_common_ancestor(left->pointer, right->pointer);
|
||||
return common ? type_get_ptr(common) : NULL;
|
||||
}
|
||||
if (left->type_kind != TYPE_STRUCT) return NULL;
|
||||
|
||||
static Type *left_types[MAX_SEARCH_DEPTH];
|
||||
int depth = 0;
|
||||
while (depth < MAX_SEARCH_DEPTH)
|
||||
{
|
||||
if (!left->decl->strukt.members) break;
|
||||
Decl *first_element = left->decl->strukt.members[0];
|
||||
if (first_element->decl_kind != DECL_VAR) break;
|
||||
if (first_element->type->canonical == right) return right;
|
||||
left = first_element->type->canonical;
|
||||
left_types[depth++] = left;
|
||||
}
|
||||
if (depth == MAX_SEARCH_DEPTH)
|
||||
{
|
||||
error_exit("Struct type depth %d exceeded.", MAX_SEARCH_DEPTH);
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
if (!right->decl->strukt.members) return NULL;
|
||||
Decl *first_element = right->decl->strukt.members[0];
|
||||
if (first_element->decl_kind != DECL_VAR) return NULL;
|
||||
right = first_element->type->canonical;
|
||||
for (int i = 0; i < depth; i++)
|
||||
{
|
||||
if (right == left_types[i]) return right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned type_get_introspection_kind(TypeKind kind)
|
||||
{
|
||||
|
||||
17
test/unit/regression/distinct_inline.c3
Normal file
17
test/unit/regression/distinct_inline.c3
Normal file
@@ -0,0 +1,17 @@
|
||||
module distinct_inline @test;
|
||||
|
||||
distinct Foo = inline int;
|
||||
distinct Bar = inline Foo;
|
||||
distinct Baz = inline Foo;
|
||||
distinct Abc = inline Baz;
|
||||
distinct Def = inline Abc;
|
||||
distinct Other = inline int;
|
||||
distinct Other2 = inline Other;
|
||||
fn void test()
|
||||
{
|
||||
assert($typeof((Foo)1 + 1).typeid == Foo.typeid);
|
||||
assert($typeof((Foo)1 + (Bar)1).typeid == Foo.typeid);
|
||||
assert($typeof((Baz)1 + (Bar)1).typeid == Foo.typeid);
|
||||
assert($typeof((Def)1 + (Bar)1).typeid == Foo.typeid);
|
||||
assert($typeof((Other2)1 + (Def)1).typeid == int.typeid);
|
||||
}
|
||||
Reference in New Issue
Block a user