Distinct types could not be used with tagof #2152

This commit is contained in:
Christoffer Lerno
2025-05-26 00:57:20 +02:00
parent 8d563eba7a
commit 9461873b4c
6 changed files with 42 additions and 11 deletions

View File

@@ -15,6 +15,7 @@
- Deprecate `SomeFn.params`.
- Improve error message when encountering recursively defined structs. #2146
- Limit vector max size, default is 4096 bits, but may be increased using --max-vector-size.
- Allow the use of `has_tagof` on builtin types.
### Fixes
- Assert triggered when casting from `int[2]` to `uint[2]` #2115
@@ -41,6 +42,7 @@
- `--path` does not interact correctly with relative path arguments #2149.
- Add missing `@noreturn` to `os::exit`.
- Implicit casting from struct to interface failure for inheriting interfaces #2151.
- Distinct types could not be used with tagof #2152.
### Stdlib changes
- Added `String.quick_ztr` and `String.is_zstr`

View File

@@ -2521,7 +2521,7 @@ INLINE BitSize type_bit_size(Type *type);
INLINE Type *type_vector_type(Type *type);
static inline CanonicalType *type_pointer_type(Type *type);
static inline Type *type_flatten(Type *type);
static inline CanonicalType *type_flatten(Type *type);
static inline bool type_flat_is_char_array(Type *type);
static inline Type *type_base(Type *type);
@@ -3030,7 +3030,7 @@ static inline Type *type_flatten_to_int(Type *type)
}
}
static inline Type *type_flatten(Type *type)
static inline CanonicalType *type_flatten(Type *type)
{
while (1)
{

View File

@@ -1346,13 +1346,13 @@ typedef enum
TYPE_F128,
TYPE_FLOAT_LAST = TYPE_F128,
TYPE_NUM_LAST = TYPE_FLOAT_LAST,
TYPE_DISTINCT,
TYPE_ANY,
TYPE_INTERFACE,
TYPE_ANYFAULT,
TYPE_TYPEID,
TYPE_FUNC_PTR,
TYPE_POINTER,
TYPE_DISTINCT,
TYPE_ENUM,
TYPE_FUNC_RAW,
TYPE_STRUCT,

View File

@@ -2937,7 +2937,6 @@ static inline bool sema_expr_analyse_typecall(SemaContext *context, Expr *expr)
}
Expr **args = expr->call_expr.arguments;
unsigned arg_count = vec_size(args);
Decl *decl = tag->type_call_expr.type;
bool is_has = tag->type_call_expr.property == TYPE_PROPERTY_HAS_TAGOF;
const char *name = is_has ? "has_tagof" : "tagof";
if (arg_count != 1) RETURN_SEMA_ERROR(expr, "Expected a single string argument to '%s'.", name);
@@ -2947,9 +2946,11 @@ static inline bool sema_expr_analyse_typecall(SemaContext *context, Expr *expr)
{
RETURN_SEMA_ERROR(key, "The tag name should be a string constant.");
}
Decl *decl = tag->type_call_expr.type;
const char *tagname = key->const_expr.bytes.ptr;
if (!decl) goto NOT_FOUND;
ASSERT_SPAN(expr, decl->resolved_attributes);
ResolvedAttrData *attrs = decl->attrs_resolved;
const char *tagname = key->const_expr.bytes.ptr;
if (!attrs || !attrs->tags) goto NOT_FOUND;
Expr *value = NULL;
FOREACH(Attr *, attr, attrs->tags)
@@ -4990,7 +4991,7 @@ EVAL:
static bool sema_type_property_is_valid_for_type(Type *original_type, TypeProperty property)
{
Type *type = type_flatten(original_type);
CanonicalType *type = type_flatten(original_type);
switch (property)
{
case TYPE_PROPERTY_NONE:
@@ -5042,7 +5043,7 @@ static bool sema_type_property_is_valid_for_type(Type *original_type, TypeProper
case TYPE_PROPERTY_FROM_ORDINAL:
case TYPE_PROPERTY_LOOKUP:
case TYPE_PROPERTY_LOOKUP_FIELD:
return type->canonical->type_kind == TYPE_ENUM;
return type->type_kind == TYPE_ENUM;
case TYPE_PROPERTY_MIN:
case TYPE_PROPERTY_MAX:
return type_is_float(type) || type_is_integer(type);
@@ -5084,8 +5085,9 @@ static bool sema_type_property_is_valid_for_type(Type *original_type, TypeProper
return type_is_func_ptr(type);
case TYPE_PROPERTY_TAGOF:
case TYPE_PROPERTY_HAS_TAGOF:
return true;
case TYPE_PROPERTY_EXTNAMEOF:
return !type_is_builtin(type->type_kind);
return !type_is_builtin(original_type->canonical->type_kind);
}
UNREACHABLE
}
@@ -5194,7 +5196,22 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
sema_expr_rewrite_to_type_nameof(expr, type, TOKEN_CT_EXTNAMEOF);
return true;
case TYPE_PROPERTY_TAGOF:
if (!type_is_user_defined(type))
{
RETURN_SEMA_ERROR(expr, "'tagof' is not defined for builtin types like %s.", type_quoted_error_string(type));
}
FALLTHROUGH;
case TYPE_PROPERTY_HAS_TAGOF:
if (!type_is_user_defined(type))
{
expr->expr_kind = EXPR_TYPECALL;
expr->type_call_expr = (ExprTypeCall) {
.type = NULL,
.property = property };
return true;
}
FALLTHROUGH;
case TYPE_PROPERTY_FROM_ORDINAL:
case TYPE_PROPERTY_LOOKUP:
case TYPE_PROPERTY_LOOKUP_FIELD:

View File

@@ -18,9 +18,8 @@ fn int main()
@.str.2 = private unnamed_addr constant [4 x i8] c"int\00", align 1
@.str.4 = private unnamed_addr constant [7 x i8] c"double\00", align 1
@.str.6 = private unnamed_addr constant [7 x i8] c"String\00", align 1
@.str.6 = private unnamed_addr constant [18 x i8] c"std::core::String\00", align 1
; Function Attrs:
define i32 @main() #0 {
entry:
%varargslots = alloca [1 x %any], align 16
@@ -42,7 +41,7 @@ entry:
%4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.String" to i64), 1
store %any %4, ptr %varargslots1, align 16
%5 = call i64 @std.io.printfn(ptr %retparam3, ptr @.str.3, i64 2, ptr %varargslots1, i64 1)
store %"char[]" { ptr @.str.6, i64 6 }, ptr %taddr5, align 8
store %"char[]" { ptr @.str.6, i64 17 }, ptr %taddr5, align 8
%6 = insertvalue %any undef, ptr %taddr5, 0
%7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.String" to i64), 1
store %any %7, ptr %varargslots4, align 16

View File

@@ -0,0 +1,13 @@
macro @foo(#type)
{
return $typeof(#type).has_tagof("hello");
}
typedef Foo = uint;
fn int main()
{
Foo f = 1;
@foo(f);
return 0;
}