diff --git a/releasenotes.md b/releasenotes.md index 750fcdcbd..a287f963b 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -15,6 +15,7 @@ - Bug causing a compiler error when parsing a broken lambda inside of an expression. - Fixed: regression in comments for `@deprecated` and `@pure`. - Detect recursive creation of generics #2366. +- Compiler assertion when defining a function with return type untyped_list #2368. ### Stdlib changes - Add `==` to `Pair`, `Triple` and TzDateTime. Add print to `Pair` and `Triple`. diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 273efa1c6..3adf4ea11 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2935,7 +2935,7 @@ INLINE const char *type_invalid_storage_type_name(Type *type) case TYPE_UNTYPED_LIST: return "an untyped list"; case TYPE_TYPEINFO: - return "a type"; + return "a typeinfo"; case TYPE_WILDCARD: return "an empty value"; default: diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 40f006668..5c6135146 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -235,8 +235,9 @@ static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent case STORAGE_NORMAL: break; case STORAGE_VOID: + RETURN_SEMA_ERROR(type_info, "Members cannot be %s.", type_quoted_error_string(type)); case STORAGE_COMPILE_TIME: - RETURN_SEMA_ERROR(type_info, "Members cannot be of type %s.", type_quoted_error_string(type)); + RETURN_SEMA_ERROR(type_info, "Members cannot be %s.", type_invalid_storage_type_name(type)); case STORAGE_WILDCARD: case STORAGE_UNKNOWN: RETURN_SEMA_ERROR(type_info, "%s has unknown size and cannot be used as a member.", type_quoted_error_string(type)); @@ -1108,6 +1109,21 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, is_macro ? RESOLVE_TYPE_ALLOW_INFER : RESOLVE_TYPE_DEFAULT)) return false; rtype = rtype_info->type; + switch (sema_resolve_storage_type(context, rtype)) + { + case STORAGE_ERROR: + return false; + case STORAGE_VOID: + case STORAGE_NORMAL: + break; + case STORAGE_UNKNOWN: + RETURN_SEMA_ERROR(rtype_info, "This type is of unknown size, and cannot be a return value. However, you can pass it by pointer."); + case STORAGE_WILDCARD: + RETURN_SEMA_ERROR(rtype_info, "The type cannot be determined for this return value."); + case STORAGE_COMPILE_TIME: + if (is_macro) break; + RETURN_SEMA_ERROR(rtype_info, "A function may not return %s, only macros may do so.", type_invalid_storage_type_name(rtype)); + } if (sig->attrs.noreturn && !type_is_void(rtype)) { RETURN_SEMA_ERROR(rtype_info, "@noreturn cannot be used on %s not returning 'void'.", is_macro ? "macros" : "functions"); @@ -1278,7 +1294,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, case STORAGE_WILDCARD: RETURN_SEMA_ERROR(type_info, "The type cannot be determined for this parameter."); case STORAGE_COMPILE_TIME: - RETURN_SEMA_ERROR(type_info, "A parameter may not be declared with a compile time type."); + RETURN_SEMA_ERROR(type_info, "The type of a parameter may not %s.", type_invalid_storage_type_name(type_info->type)); } } if (i == format_index) @@ -1711,7 +1727,7 @@ static inline bool sema_analyse_raw_enum(SemaContext *context, Decl *decl, bool SEMA_ERROR(decl->enums.type_info, "An enum may not have a void type."); return decl_poison(decl); case STORAGE_COMPILE_TIME: - SEMA_ERROR(decl->enums.type_info, "An enum may not have a compile time type."); + SEMA_ERROR(decl->enums.type_info, "An enum may not be %s.", type_invalid_storage_type_name(type)); return decl_poison(decl); case STORAGE_UNKNOWN: SEMA_ERROR(decl->enums.type_info, "An enum may not be %s, as it has an unknown size.", @@ -2179,7 +2195,7 @@ static inline bool sema_analyse_operator_element_at(SemaContext *context, Decl * RETURN_SEMA_ERROR(rtype, "The return type cannot be 'void'."); case STORAGE_COMPILE_TIME: RETURN_SEMA_ERROR(rtype, "The return type is %s which is a compile time type, which isn't allowed.", - type_quoted_error_string(rtype->type)); + type_invalid_storage_type_name(rtype->type)); case STORAGE_UNKNOWN: RETURN_SEMA_ERROR(rtype, "%s has unknown size and cannot be used as a return type.", type_quoted_error_string(rtype->type)); @@ -4506,8 +4522,8 @@ static bool sema_analyse_variable_type(SemaContext *context, Type *type, SourceS } RETURN_SEMA_ERROR_AT(span, "The use of %s as a variable type is not permitted.", type_quoted_error_string(type)); case STORAGE_COMPILE_TIME: - RETURN_SEMA_ERROR_AT(span, "The variable cannot have an compile time %s type.", - type_quoted_error_string(type)); + RETURN_SEMA_ERROR_AT(span, "The variable cannot be %s which is an compile time type.", + type_invalid_storage_type_name(type)); case STORAGE_UNKNOWN: RETURN_SEMA_ERROR_AT(span, "%s has unknown size, and so it cannot be a variable type.", type_quoted_error_string(type)); @@ -4960,7 +4976,7 @@ static bool sema_generate_parameterized_name_to_scratch(SemaContext *context, Mo case STORAGE_WILDCARD: RETURN_SEMA_ERROR(type_info, "The type is undefined and cannot be used as a parameter type."); case STORAGE_COMPILE_TIME: - RETURN_SEMA_ERROR(type_info, "Expected a runtime type."); + RETURN_SEMA_ERROR(type_info, "Expected a runtime type but it was %s.", type_invalid_storage_type_name(type)); case STORAGE_UNKNOWN: RETURN_SEMA_ERROR(type_info, "%s doesn't have a well defined size and cannot be used as a parameter type.", diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index f20b67c4f..04243d900 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1097,7 +1097,7 @@ static inline bool sema_expr_analyse_ternary(SemaContext *context, Type *infer_t { RETURN_SEMA_ERROR(expr, "The ternary would be an 'untyped list', you need to explicitly type one or both branches to a runtime type."); } - RETURN_SEMA_ERROR(expr, "A ternary must always return a runtime type, but it was %s.", type_quoted_error_string(left_canonical)); + RETURN_SEMA_ERROR(expr, "A ternary must always return a runtime type, but it was %s.", type_invalid_storage_type_name(left_canonical)); break; default: break; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 0880c4c17..b74582d5a 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -130,7 +130,7 @@ static inline bool sema_analyse_assert_stmt(SemaContext *context, Ast *statement { RETURN_SEMA_ERROR(e, "The type of an untyped list cannot be inferred, you can try adding an explicit type to solve this."); } - RETURN_SEMA_ERROR(e, "You can't use a compile time type as an assert argument."); + RETURN_SEMA_ERROR(e, "You can't use a compile time type (%s) as an assert argument.", type_invalid_storage_type_name(e->type)); case STORAGE_UNKNOWN: RETURN_SEMA_ERROR(e, "You can't use an argument of type %s in an assert.", type_quoted_error_string(e->type)); } diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 8054d7071..1aba5368c 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -340,6 +340,7 @@ INLINE bool sema_resolve_typeof(SemaContext *context, TypeInfo *type_info) case STORAGE_NORMAL: case STORAGE_VOID: case STORAGE_UNKNOWN: + case STORAGE_COMPILE_TIME: type_info->type = expr_type; return true; case STORAGE_WILDCARD: @@ -349,9 +350,6 @@ INLINE bool sema_resolve_typeof(SemaContext *context, TypeInfo *type_info) return true; } RETURN_SEMA_ERROR(expr, "This %sexpression lacks a concrete type.", type_is_optional(expr_type) ? "optional " : ""); - case STORAGE_COMPILE_TIME: - type_info->type = type_untypedlist; - return true; } UNREACHABLE } diff --git a/test/test_suite/compile_time/untyped_list_rtype.c3 b/test/test_suite/compile_time/untyped_list_rtype.c3 new file mode 100644 index 000000000..58eaddc32 --- /dev/null +++ b/test/test_suite/compile_time/untyped_list_rtype.c3 @@ -0,0 +1,18 @@ + + +macro $typeof({}) foo2() { return {}; } + +struct Foo +{ + int a; +} + +fn $typeof(Foo.a) foo3() {} // #error: may not return a member reference + +fn $typeof({}) foo() {} // #error: A function may not return an untyped list + +fn int main() +{ + foo2(); + return 0; +} \ No newline at end of file