mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Make methods be available in earlier stages of analysis. Add @adhoc attribute to allow types with ad hoc generic declarations.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
module std::collections::maybe(<Type>);
|
||||
|
||||
struct Maybe
|
||||
struct Maybe @adhoc
|
||||
{
|
||||
Type value;
|
||||
bool has_value;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::collections::tuple(<Type1, Type2>);
|
||||
|
||||
struct Tuple @deprecated
|
||||
struct Tuple @adhoc
|
||||
{
|
||||
Type1 first;
|
||||
Type2 second;
|
||||
@@ -8,7 +8,7 @@ struct Tuple @deprecated
|
||||
|
||||
module std::collections::triple(<Type1, Type2, Type3>);
|
||||
|
||||
struct Triple @deprecated
|
||||
struct Triple @adhoc
|
||||
{
|
||||
Type1 first;
|
||||
Type2 second;
|
||||
|
||||
@@ -23,11 +23,12 @@
|
||||
- Allow the "self" parameter to be $/# for macro methods.
|
||||
- Support compile time slicing of untyped lists.
|
||||
- Allow specifying an import module using `@wasm` #1305.
|
||||
- Deprecated inline generic types outside of struct definitions and macros unless marked `@adhoc`.
|
||||
- Improved method detection in earlier stages of checking.
|
||||
|
||||
### Fixes
|
||||
- Issue where a lambda wasn't correctly registered as external. #1408
|
||||
- Generic methods were incorrectly registered as functions, leading to naming collisions. #1402
|
||||
- Deprecated inline generic types outside of struct definitions and macros.
|
||||
- Deprecated tuple / triple types.
|
||||
- Converting a slice to a vector/array would copy too little data.
|
||||
- Crash when reading an empty 'manifest.json'.
|
||||
|
||||
@@ -600,6 +600,7 @@ typedef struct Decl_
|
||||
bool no_strip : 1;
|
||||
bool is_cond : 1;
|
||||
bool is_if : 1;
|
||||
bool is_adhoc : 1;
|
||||
bool attr_nopadding : 1;
|
||||
bool attr_compact : 1;
|
||||
bool resolved_attributes : 1;
|
||||
@@ -1604,6 +1605,7 @@ struct CompilationUnit_
|
||||
Decl **ct_includes;
|
||||
Decl **vars;
|
||||
Decl **macros;
|
||||
Decl **methods_to_register;
|
||||
Decl **methods;
|
||||
Decl **macro_methods;
|
||||
Decl **global_decls;
|
||||
@@ -2273,6 +2275,7 @@ bool sema_cast_const(Expr *expr);
|
||||
bool sema_expr_check_discard(SemaContext *context, Expr *expr);
|
||||
bool sema_analyse_inferred_expr(SemaContext *context, Type *to, Expr *expr);
|
||||
bool sema_analyse_decl(SemaContext *context, Decl *decl);
|
||||
bool sema_analyse_method_register(SemaContext *context, Decl *method);
|
||||
bool sema_resolve_type_structure(SemaContext *context, Type *type, SourceSpan span);
|
||||
bool sema_analyse_var_decl_ct(SemaContext *context, Decl *decl);
|
||||
bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local);
|
||||
|
||||
@@ -181,7 +181,7 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl)
|
||||
assert(decl->name);
|
||||
if (decl->func_decl.type_parent)
|
||||
{
|
||||
vec_add(unit->macro_methods, decl);
|
||||
vec_add(unit->methods_to_register, decl);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -194,7 +194,7 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl)
|
||||
assert(decl->name);
|
||||
if (decl->func_decl.type_parent)
|
||||
{
|
||||
vec_add(unit->methods, decl);
|
||||
vec_add(unit->methods_to_register, decl);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -233,7 +233,6 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl)
|
||||
vec_add(unit->attributes, decl);
|
||||
decl_register(decl);
|
||||
break;
|
||||
|
||||
case DECL_FAULTVALUE:
|
||||
case DECL_ENUM_CONSTANT:
|
||||
case DECL_IMPORT:
|
||||
|
||||
@@ -46,9 +46,13 @@ typedef enum
|
||||
ANALYSIS_MODULE_TOP,
|
||||
ANALYSIS_IMPORTS,
|
||||
ANALYSIS_REGISTER_GLOBAL_DECLARATIONS,
|
||||
ANALYSIS_METHODS_REGISTER,
|
||||
ANALYSIS_INCLUDES,
|
||||
ANALYSIS_METHODS_INCLUDES,
|
||||
ANALYSIS_REGISTER_CONDITIONAL_UNITS,
|
||||
ANALYSIS_REGISTER_CONDITIONAL_DECLARATIONS,
|
||||
ANALYSIS_METHODS_CONDITIONAL,
|
||||
ANALYSIS_POST_REGISTER,
|
||||
ANALYSIS_DECLS,
|
||||
ANALYSIS_CT_ECHO,
|
||||
ANALYSIS_CT_ASSERT,
|
||||
@@ -250,6 +254,7 @@ typedef enum FLAG_ATTR
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATTRIBUTE_ADHOC,
|
||||
ATTRIBUTE_ALIGN,
|
||||
ATTRIBUTE_BENCHMARK,
|
||||
ATTRIBUTE_BIGENDIAN,
|
||||
@@ -988,10 +993,11 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
RESOLVE_TYPE_DEFAULT,
|
||||
RESOLVE_TYPE_ALLOW_INFER = 0x01,
|
||||
RESOLVE_TYPE_ALLOW_FLEXIBLE = 0x02,
|
||||
RESOLVE_TYPE_MACRO_METHOD = RESOLVE_TYPE_ALLOW_INFER,
|
||||
RESOLVE_TYPE_FUNC_METHOD = RESOLVE_TYPE_DEFAULT
|
||||
RESOLVE_TYPE_ALLOW_INFER = 0x01,
|
||||
RESOLVE_TYPE_ALLOW_FLEXIBLE = 0x02,
|
||||
RESOLVE_TYPE_NO_CHECK_DISTINCT = 0x04,
|
||||
RESOLVE_TYPE_MACRO_METHOD = RESOLVE_TYPE_ALLOW_INFER | RESOLVE_TYPE_NO_CHECK_DISTINCT,
|
||||
RESOLVE_TYPE_FUNC_METHOD = RESOLVE_TYPE_NO_CHECK_DISTINCT,
|
||||
} ResolveTypeKind;
|
||||
|
||||
typedef enum FLAG_ATTR
|
||||
|
||||
@@ -1780,15 +1780,6 @@ INLINE SourceSpan method_find_overload_span(Decl *method)
|
||||
|
||||
static inline bool unit_add_base_extension_method(SemaContext *context, CompilationUnit *unit, Type *parent_type, Decl *method)
|
||||
{
|
||||
// We don't support operator overloading on base types, because
|
||||
// there seems little use for it frankly.
|
||||
if (method->operator)
|
||||
{
|
||||
sema_error_at(context, method_find_overload_span(method),
|
||||
"Only user-defined types support operator oveloading.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add it to the right list of extensions.
|
||||
switch (method->visibility)
|
||||
{
|
||||
@@ -1841,10 +1832,20 @@ INLINE bool sema_analyse_operator_method(SemaContext *context, Type *parent_type
|
||||
// Check it's valid for the operator type.
|
||||
if (!sema_check_operator_method_validity(context, method)) return false;
|
||||
|
||||
// We don't support operator overloading on base types, because
|
||||
// there seems little use for it frankly.
|
||||
if (!type_is_user_defined(parent_type))
|
||||
{
|
||||
sema_error_at(context, method_find_overload_span(method),
|
||||
"Only user-defined types support operator oveloading.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// See if the operator has already been defined.
|
||||
OperatorOverload operator = method->operator;
|
||||
|
||||
Decl *other = sema_find_operator(context, parent_type, operator);
|
||||
if (other)
|
||||
if (other != method)
|
||||
{
|
||||
SourceSpan span = method_find_overload_span(method);
|
||||
sema_error_at(context, span, "This operator is already defined for '%s'.", parent_type->name);
|
||||
@@ -1920,6 +1921,11 @@ INLINE bool sema_analyse_operator_method(SemaContext *context, Type *parent_type
|
||||
// So compare the value
|
||||
if (this_value != value)
|
||||
{
|
||||
if (operator == OVERLOAD_ELEMENT_REF)
|
||||
{
|
||||
value = type_get_ptr(value);
|
||||
this_value = type_get_ptr(this_value);
|
||||
}
|
||||
SEMA_ERROR(method, "There is a mismatch of the 'value' type compared to that of another operator: expected %s but got %s.",
|
||||
type_quoted_error_string(value), type_quoted_error_string(this_value));
|
||||
SEMA_NOTE(other, "The other definition is here.");
|
||||
@@ -1966,6 +1972,7 @@ static inline bool unit_add_method(SemaContext *context, Type *parent_type, Decl
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Is it a base extension?
|
||||
if (!type_is_user_defined(parent_type)) return unit_add_base_extension_method(context, unit, parent_type, method);
|
||||
|
||||
@@ -1984,12 +1991,6 @@ static inline bool unit_add_method(SemaContext *context, Type *parent_type, Decl
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is it an operator?
|
||||
if (method->operator)
|
||||
{
|
||||
if (!sema_analyse_operator_method(context, parent_type, method)) return false;
|
||||
}
|
||||
|
||||
DEBUG_LOG("Method-like '%s.%s' analysed.", parent->name, method->name);
|
||||
|
||||
// Add it to the correct place: type methods, private extensions, local method extensions
|
||||
@@ -2178,13 +2179,12 @@ static inline bool sema_compare_method_with_interface(SemaContext *context, Decl
|
||||
*
|
||||
* 1. Check that it has no init/finalizer attributes.
|
||||
* 2. Check that it has no test/benchmark attributes.
|
||||
* 3. Resolve the parent type.
|
||||
* 4. Resolve the declaration of the parent (as needed).
|
||||
* 5. Check that it has at least one parameter.
|
||||
* 6. Check that this parameter is correct.
|
||||
* 7. If it is dynamic, the type may not be an interface or any
|
||||
* 8. If it is dynamic, make sure that it implements an interface correctly if available
|
||||
* 9. Try adding the method
|
||||
* 3. Resolve the declaration of the parent (as needed).
|
||||
* 4. Check that it has at least one parameter.
|
||||
* 5. Check that this parameter is correct.
|
||||
* 6. If it is dynamic, the type may not be an interface or any
|
||||
* 7. If it is dynamic, make sure that it implements an interface correctly if available
|
||||
* 8. Try adding the method
|
||||
*/
|
||||
static inline bool sema_analyse_method(SemaContext *context, Decl *decl)
|
||||
{
|
||||
@@ -2202,7 +2202,7 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl)
|
||||
|
||||
// Resolve the parent type.
|
||||
TypeInfo *parent_type = type_infoptr(decl->func_decl.type_parent);
|
||||
if (!sema_resolve_type_info(context, parent_type, RESOLVE_TYPE_FUNC_METHOD)) return false;
|
||||
assert(parent_type->resolve_status == RESOLVE_DONE);
|
||||
Type *par_type = parent_type->type->canonical;
|
||||
|
||||
// Resolve declaration of parent as needed.
|
||||
@@ -2245,7 +2245,13 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl)
|
||||
decl->func_decl.interface_method = 0;
|
||||
}
|
||||
}
|
||||
return unit_add_method(context, par_type, decl);
|
||||
// Is it an operator?
|
||||
if (decl->operator)
|
||||
{
|
||||
if (!sema_analyse_operator_method(context, par_type, decl)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *attribute_domain_to_string(AttributeDomain domain)
|
||||
@@ -2363,6 +2369,7 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_
|
||||
assert(type >= 0 && type < NUMBER_OF_ATTRIBUTES);
|
||||
// NOLINTBEGIN(*.EnumCastOutOfRange)
|
||||
static AttributeDomain attribute_domain[NUMBER_OF_ATTRIBUTES] = {
|
||||
[ATTRIBUTE_ADHOC] = USER_DEFINED_TYPES,
|
||||
[ATTRIBUTE_ALIGN] = ATTR_FUNC | ATTR_CONST | ATTR_LOCAL | ATTR_GLOBAL | ATTR_BITSTRUCT | ATTR_STRUCT | ATTR_UNION | ATTR_MEMBER, // NOLINT
|
||||
[ATTRIBUTE_BENCHMARK] = ATTR_FUNC,
|
||||
[ATTRIBUTE_BIGENDIAN] = ATTR_BITSTRUCT,
|
||||
@@ -2526,6 +2533,9 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_
|
||||
FAILED_OP_TYPE:
|
||||
RETURN_SEMA_ERROR(attr, "'operator' requires an operator type argument: '[]', '[]=', '&[]' or 'len'.");
|
||||
}
|
||||
case ATTRIBUTE_ADHOC:
|
||||
decl->is_adhoc = true;
|
||||
return true;
|
||||
case ATTRIBUTE_ALIGN:
|
||||
if (!expr)
|
||||
{
|
||||
@@ -3462,20 +3472,8 @@ static bool sema_analyse_macro_method(SemaContext *context, Decl *decl)
|
||||
{
|
||||
// Resolve the type of the method.
|
||||
TypeInfo *parent_type_info = type_infoptr(decl->func_decl.type_parent);
|
||||
if (!sema_resolve_type_info(context, parent_type_info, RESOLVE_TYPE_MACRO_METHOD)) return false;
|
||||
|
||||
// Can the type have methods?
|
||||
Type *parent_type = parent_type_info->type;
|
||||
if (!type_may_have_method(parent_type))
|
||||
{
|
||||
RETURN_SEMA_ERROR(parent_type_info, "Methods can not be associated with '%s'", type_to_error_string(parent_type));
|
||||
}
|
||||
|
||||
// We need at least one argument (the parent type)
|
||||
if (!vec_size(decl->func_decl.signature.params))
|
||||
{
|
||||
RETURN_SEMA_ERROR(decl, "Expected at least one parameter - of type '%s'.", type_to_error_string(parent_type));
|
||||
}
|
||||
assert(parent_type_info->resolve_status == RESOLVE_DONE);
|
||||
Type *parent_type = parent_type_info->type->canonical;
|
||||
|
||||
// Check the first argument.
|
||||
Decl *first_param = decl->func_decl.signature.params[0];
|
||||
@@ -3484,13 +3482,19 @@ static bool sema_analyse_macro_method(SemaContext *context, Decl *decl)
|
||||
RETURN_SEMA_ERROR(decl, "The first parameter to this method must be of type '%s'.", type_to_error_string(parent_type));
|
||||
return false;
|
||||
}
|
||||
if (!sema_is_valid_method_param(context, first_param, parent_type->canonical, false)) return false;
|
||||
if (!sema_is_valid_method_param(context, first_param, parent_type, false)) return false;
|
||||
|
||||
if (first_param->var.kind != VARDECL_PARAM_EXPR && first_param->var.kind != VARDECL_PARAM_CT && first_param->var.kind != VARDECL_PARAM_REF && first_param->var.kind != VARDECL_PARAM)
|
||||
{
|
||||
RETURN_SEMA_ERROR(first_param, "The first parameter must be a compile time, regular or ref (&) type.");
|
||||
}
|
||||
return unit_add_method(context, parent_type->canonical, decl);
|
||||
// Is it an operator?
|
||||
if (decl->operator)
|
||||
{
|
||||
if (!sema_analyse_operator_method(context, parent_type, decl)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE bool sema_analyse_macro_body(SemaContext *context, Decl **body_parameters)
|
||||
@@ -4408,6 +4412,31 @@ RETRY:
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
bool sema_analyse_method_register(SemaContext *context, Decl *method)
|
||||
{
|
||||
TypeInfo *parent_type_info = type_infoptr(method->func_decl.type_parent);
|
||||
if (!sema_resolve_type_info(context, parent_type_info, method->decl_kind == DECL_MACRO ? RESOLVE_TYPE_MACRO_METHOD : RESOLVE_TYPE_FUNC_METHOD)) return false;
|
||||
|
||||
// Can the type have methods?
|
||||
Type *parent_type = parent_type_info->type;
|
||||
if (!type_may_have_method(parent_type))
|
||||
{
|
||||
RETURN_SEMA_ERROR(parent_type_info, "Methods can not be associated with '%s'", type_to_error_string(parent_type));
|
||||
}
|
||||
|
||||
// We need at least one argument (the parent type)
|
||||
if (!vec_size(method->func_decl.signature.params))
|
||||
{
|
||||
RETURN_SEMA_ERROR(method, "Expected at least one parameter - of type '%s'.", type_to_error_string(parent_type));
|
||||
}
|
||||
|
||||
// Check the first argument.
|
||||
Decl *first_param = method->func_decl.signature.params[0];
|
||||
if (!first_param) RETURN_SEMA_ERROR(method, "The first parameter to this method must be of type '%s'.", type_to_error_string(parent_type));
|
||||
|
||||
return unit_add_method(context, parent_type->canonical, method);
|
||||
}
|
||||
|
||||
bool sema_analyse_decl(SemaContext *context, Decl *decl)
|
||||
{
|
||||
if (decl->resolve_status == RESOLVE_DONE) return decl_ok(decl);
|
||||
|
||||
@@ -2129,7 +2129,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
type_quoted_error_string(type_get_ptr(type_info->type)));
|
||||
}
|
||||
body_arg->type = type;
|
||||
if (type_info && type_storage_type(type_info->type))
|
||||
if (type_info && type_storage_type(type_info->type) == STORAGE_NORMAL)
|
||||
{
|
||||
if (!sema_set_alloca_alignment(context, body_arg->type, &body_arg->alignment)) return false;
|
||||
}
|
||||
@@ -3547,6 +3547,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
|
||||
Decl *member = sema_decl_stack_find_decl_member(context, decl, name);
|
||||
if (!decl_ok(member)) return false;
|
||||
if (!member)
|
||||
@@ -4507,10 +4508,6 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
return true;
|
||||
}
|
||||
case TYPE_PROPERTY_METHODSOF:
|
||||
if (context->compilation_unit->module->stage <= ANALYSIS_DECLS)
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "'methodsof' is not available until after declaration analysis is complete.");
|
||||
}
|
||||
sema_create_const_methodsof(context, expr, flat);
|
||||
return true;
|
||||
case TYPE_PROPERTY_PARAMSOF:
|
||||
|
||||
@@ -76,6 +76,7 @@ void sema_analysis_pass_register_global_declarations(Module *module);
|
||||
void sema_analysis_pass_process_includes(Module *module);
|
||||
void sema_analysis_pass_register_conditional_units(Module *module);
|
||||
void sema_analysis_pass_register_conditional_declarations(Module *module);
|
||||
void sema_analysis_pass_process_methods(Module *module);
|
||||
void sema_analysis_pass_decls(Module *module);
|
||||
void sema_analysis_pass_ct_assert(Module *module);
|
||||
void sema_analysis_pass_ct_echo(Module *module);
|
||||
|
||||
@@ -367,7 +367,6 @@ void sema_analysis_pass_register_global_declarations(Module *module)
|
||||
DEBUG_LOG("Processing %s.", unit->file->name);
|
||||
register_global_decls(unit, unit->global_decls);
|
||||
}
|
||||
|
||||
DEBUG_LOG("Pass finished with %d error(s).", compiler.context.errors_found);
|
||||
}
|
||||
|
||||
@@ -385,6 +384,33 @@ void sema_analysis_pass_process_includes(Module *module)
|
||||
DEBUG_LOG("Pass finished with %d error(s).", compiler.context.errors_found);
|
||||
}
|
||||
|
||||
|
||||
void sema_analysis_pass_process_methods(Module *module)
|
||||
{
|
||||
DEBUG_LOG("Pass: Process methods register for module '%s'.", module->name->module);
|
||||
FOREACH(CompilationUnit *, unit, module->units)
|
||||
{
|
||||
SemaContext context;
|
||||
sema_context_init(&context, unit);
|
||||
FOREACH(Decl *, method, unit->methods_to_register)
|
||||
{
|
||||
sema_analyse_method_register(&context, method);
|
||||
if (method->decl_kind == DECL_MACRO)
|
||||
{
|
||||
vec_add(unit->macro_methods, method);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec_add(unit->methods, method);
|
||||
}
|
||||
}
|
||||
sema_context_destroy(&context);
|
||||
vec_resize(unit->methods_to_register, 0);
|
||||
}
|
||||
|
||||
DEBUG_LOG("Pass finished with %d error(s).", compiler.context.errors_found);
|
||||
}
|
||||
|
||||
void sema_analysis_pass_register_conditional_units(Module *module)
|
||||
{
|
||||
DEBUG_LOG("Pass: Register conditional units for %s", module->name->module);
|
||||
|
||||
@@ -192,7 +192,7 @@ static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type,
|
||||
}
|
||||
|
||||
|
||||
static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_info)
|
||||
static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_type_kind)
|
||||
{
|
||||
if (type_info->unresolved.name == type_string->name && !type_info->unresolved.path)
|
||||
{
|
||||
@@ -224,8 +224,15 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in
|
||||
type_info->type = decl->type;
|
||||
type_info->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
case DECL_TYPEDEF:
|
||||
case DECL_DISTINCT:
|
||||
if (resolve_type_kind & RESOLVE_TYPE_NO_CHECK_DISTINCT)
|
||||
{
|
||||
type_info->type = decl->type;
|
||||
type_info->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case DECL_TYPEDEF:
|
||||
if (!sema_analyse_decl(context, decl)) return type_info_poison(type_info);
|
||||
type_info->type = decl->type;
|
||||
type_info->resolve_status = RESOLVE_DONE;
|
||||
@@ -361,10 +368,11 @@ INLINE bool sema_resolve_generic_type(SemaContext *context, TypeInfo *type_info)
|
||||
Decl *type = sema_analyse_parameterized_identifier(context, inner->unresolved.path, inner->unresolved.name, inner->span, type_info->generic.params);
|
||||
if (!decl_ok(type)) return false;
|
||||
type_info->type = type->type;
|
||||
if (!context->current_macro && (context->call_env.kind == CALL_ENV_FUNCTION || context->call_env.kind == CALL_ENV_FUNCTION_STATIC)
|
||||
if (!type->is_adhoc && !context->current_macro && (context->call_env.kind == CALL_ENV_FUNCTION || context->call_env.kind == CALL_ENV_FUNCTION_STATIC)
|
||||
&& !context->call_env.current_function->func_decl.in_macro)
|
||||
{
|
||||
SEMA_DEPRECATED(type_info, "Direct generic type declarations outside of macros and type declarations is a deprecated feature, please use 'def' to create an alias.");
|
||||
|
||||
SEMA_DEPRECATED(type_info, "Direct generic type declarations not marked '@adhoc' outside of macros and type declarations is a deprecated feature, please use 'def' to create an alias.");
|
||||
// TODO, completely disallow
|
||||
// RETURN_SEMA_ERROR(type_info, "Direct generic type declarations are only allowed inside of macros. Use `def` to define an alias for the type instead.");
|
||||
}
|
||||
@@ -411,7 +419,7 @@ static inline bool sema_resolve_type(SemaContext *context, TypeInfo *type_info,
|
||||
case TYPE_INFO_CT_IDENTIFIER:
|
||||
case TYPE_INFO_IDENTIFIER:
|
||||
// $Type or Foo
|
||||
if (!sema_resolve_type_identifier(context, type_info)) return type_info_poison(type_info);
|
||||
if (!sema_resolve_type_identifier(context, type_info, resolve_type_kind)) return type_info_poison(type_info);
|
||||
goto APPEND_QUALIFIERS;
|
||||
case TYPE_INFO_EVALTYPE:
|
||||
if (!sema_resolve_evaltype(context, type_info, resolve_type_kind)) return type_info_poison(type_info);
|
||||
|
||||
@@ -158,15 +158,26 @@ void sema_analyze_stage(Module *module, AnalysisStage stage)
|
||||
case ANALYSIS_REGISTER_GLOBAL_DECLARATIONS:
|
||||
sema_analysis_pass_register_global_declarations(module);
|
||||
break;
|
||||
case ANALYSIS_METHODS_REGISTER:
|
||||
sema_analysis_pass_process_methods(module);
|
||||
break;
|
||||
case ANALYSIS_INCLUDES:
|
||||
sema_analysis_pass_process_includes(module);
|
||||
break;
|
||||
case ANALYSIS_METHODS_INCLUDES:
|
||||
sema_analysis_pass_process_methods(module);
|
||||
break;
|
||||
case ANALYSIS_REGISTER_CONDITIONAL_UNITS:
|
||||
sema_analysis_pass_register_conditional_units(module);
|
||||
break;
|
||||
case ANALYSIS_REGISTER_CONDITIONAL_DECLARATIONS:
|
||||
sema_analysis_pass_register_conditional_declarations(module);
|
||||
break;
|
||||
case ANALYSIS_METHODS_CONDITIONAL:
|
||||
sema_analysis_pass_process_methods(module);
|
||||
break;
|
||||
case ANALYSIS_POST_REGISTER:
|
||||
break;
|
||||
case ANALYSIS_DECLS:
|
||||
sema_analysis_pass_decls(module);
|
||||
break;
|
||||
|
||||
@@ -312,6 +312,7 @@ void symtab_init(uint32_t capacity)
|
||||
kw_at_require = KW_DEF("@require");
|
||||
kw_at_return = KW_DEF("@return");
|
||||
kw_at_jump = KW_DEF("@jump");
|
||||
attribute_list[ATTRIBUTE_ADHOC] = KW_DEF("@adhoc");
|
||||
attribute_list[ATTRIBUTE_ALIGN] = KW_DEF("@align");
|
||||
attribute_list[ATTRIBUTE_BENCHMARK] = KW_DEF("@benchmark");
|
||||
attribute_list[ATTRIBUTE_BIGENDIAN] = KW_DEF("@bigendian");
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
struct Foo { int a; }
|
||||
struct Foo2 { int a; }
|
||||
struct Bar { int a; }
|
||||
|
||||
fn int Foo.x(&self, int x) @operator([]) => 1;
|
||||
fn int Foo.y(&self, int x) @operator(&[]) => 1; // #error: The return type must be a pointer
|
||||
fn int** Foo.y2(&self, int x) @operator(&[]) => null; // #error: There is a mismatch of the 'value' type
|
||||
fn void Foo.z(&self, uint x, int a) @operator([]=) {} // #error: There is a mismatch of the 'index'
|
||||
fn int Foo.y(&self, int x) @operator(&[]) => 1; // #error: The return type must be a pointer
|
||||
fn int Foo2.y(&self, int x) @operator([]) => null;
|
||||
fn int** Foo2.y2(&self, int x) @operator(&[]) => null; // #error: There is a mismatch of the 'value' type
|
||||
fn void Foo.z(&self, uint x, int a) @operator([]=) {} // #error: There is a mismatch of the 'index'
|
||||
|
||||
fn double Bar.x(&self, int x) @operator([]) => 0.1;
|
||||
fn void Bar.y(&self, int x, float y) @operator([]=) {} // #error: There is a mismatch of the 'value'
|
||||
|
||||
Reference in New Issue
Block a user