diff --git a/releasenotes.md b/releasenotes.md index afc1f9d44..c41b50c67 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -28,6 +28,8 @@ - Some folding was missing in binary op compile time resolution #2135. - Defining an enum like `ABC = { 1 2 }` was accidentally allowed. - Using a non-const as the end range for a bitstruct would trigger an assert. +- Incorrect parsing of ad hoc generic types, like `Foo{int}****` #2140. +- $define did not correctly handle generic types #2140. ### Stdlib changes - Added `String.quick_ztr` and `String.is_zstr` diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 9cbab080d..1d9051f5c 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -633,7 +633,7 @@ static inline TypeInfo *parse_type_with_base_maybe_generic(ParseContext *c, Type ptr_type->pointer = type_info; type_info = ptr_type; RANGE_EXTEND_PREV(type_info); - return type_info; + break; } } if (type_info->resolve_status == RESOLVE_DONE) diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index ee733ba1c..78c292b3c 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -4852,6 +4852,18 @@ static bool sema_analyse_generic_module_contracts(SemaContext *c, Module *module } +bool sema_parameterized_type_is_found(SemaContext *context, Path *decl_path, const char *name, SourceSpan span) +{ + NameResolve name_resolve = { + .path = decl_path, + .span = span, + .symbol = name, + .suppress_error = true + }; + + return unit_resolve_parameterized_symbol(context, &name_resolve); +} + Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, const char *name, SourceSpan span, Expr **params, bool *was_recursive_ref) { diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 2874cfa1b..fde1091ef 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -9140,7 +9140,15 @@ RETRY: case TYPE_INFO_POISON: return poisoned_type; case TYPE_INFO_GENERIC: - return poisoned_type; + { + TypeInfo *base = type_info->generic.base; + if (base->kind == TYPE_INFO_IDENTIFIER) + { + if (!sema_parameterized_type_is_found(context, base->unresolved.path, base->unresolved.name, type_info->span)) return NULL; + } + if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_DEFAULT)) return poisoned_type; + return type_info->type; + } case TYPE_INFO_VECTOR: { ArraySize size; diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index b9ad235da..999bbf408 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -119,6 +119,7 @@ void cast_to_int_to_max_bit_size(Expr *lhs, Expr *rhs, Type *left_type, Type *ri bool sema_decl_if_cond(SemaContext *context, Decl *decl); Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, const char *name, SourceSpan span, Expr **params, bool *was_recursive_ref); +bool sema_parameterized_type_is_found(SemaContext *context, Path *decl_path, const char *name, SourceSpan span); Type *sema_resolve_type_get_func(Signature *signature, CallABI abi); INLINE bool sema_set_abi_alignment(SemaContext *context, Type *type, AlignSize *result); INLINE bool sema_set_alloca_alignment(SemaContext *context, Type *type, AlignSize *result); diff --git a/test/test_suite/compile_time_introspection/defined_generic_type.c3t b/test/test_suite/compile_time_introspection/defined_generic_type.c3t new file mode 100644 index 000000000..c9cbc4011 --- /dev/null +++ b/test/test_suite/compile_time_introspection/defined_generic_type.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 +module test; +import foo; + +fn void test() +{ + bool c = $defined(Foo{int}); +} + +fn int main() +{ + bool a = $defined(Baz{int}**); + bool b = $defined(Foo{int}****); + return 0; +} + +module foo {Type}; + +struct Foo +{ + Type x; +} + +/* #expect: test.ll + + + %c = alloca i8, align 1 + store i8 1, ptr %c, align 1 + + %a = alloca i8, align 1 + %b = alloca i8, align 1 + store i8 0, ptr %a, align 1 + store i8 1, ptr %b, align 1