diff --git a/releasenotes.md b/releasenotes.md index 290214dcc..d89a8b399 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -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` diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index de7bb6e2b..67fb9cf6c 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -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) { diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 74f988976..2298f9dac 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -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, diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 9db7f6a40..732a1a5e3 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -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: diff --git a/test/test_suite/enumerations/enum_reflect_associated.c3t b/test/test_suite/enumerations/enum_reflect_associated.c3t index 2f7759b14..fc46b11a7 100644 --- a/test/test_suite/enumerations/enum_reflect_associated.c3t +++ b/test/test_suite/enumerations/enum_reflect_associated.c3t @@ -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 diff --git a/test/test_suite/macros/tagof_distinct.c3 b/test/test_suite/macros/tagof_distinct.c3 new file mode 100644 index 000000000..3e277e210 --- /dev/null +++ b/test/test_suite/macros/tagof_distinct.c3 @@ -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; +}