mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Expand inference.
This commit is contained in:
@@ -895,7 +895,7 @@ static void print_arch_asm(PlatformTarget *target)
|
||||
default:
|
||||
UNREACHABLE_VOID
|
||||
}
|
||||
if (scratch_buffer.len) scratch_buffer.len -= 2;
|
||||
if (scratch_buffer.len) scratch_buffer_delete(2);
|
||||
printf("%-30s | ", scratch_buffer_to_string());
|
||||
int len = 0;
|
||||
for (unsigned j = 0; j < instruction->param_count; j++)
|
||||
|
||||
@@ -635,6 +635,7 @@ typedef struct
|
||||
const char *cname_suffix;
|
||||
Decl **generated_decls;
|
||||
} GenericInstanceDecl;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool is_func : 1;
|
||||
|
||||
@@ -66,7 +66,7 @@ static bool filename_to_module_in_buffer(const char *path)
|
||||
}
|
||||
scratch_buffer_append_char(c);
|
||||
}
|
||||
if (last_was_underscore && scratch_buffer.len) scratch_buffer.len--;
|
||||
if (last_was_underscore && scratch_buffer.len) scratch_buffer_delete(1);
|
||||
if (!scratch_buffer.len) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5192,6 +5192,179 @@ static bool sema_analyse_generic_module_contracts(SemaContext *c, Module *module
|
||||
return true;
|
||||
}
|
||||
|
||||
Decl *sema_generate_parameterized_identifier(SemaContext *context, Decl *generic, Decl *alias, Expr **params, Decl **param_decls, const char *suffix, const char *csuffix, SourceSpan invocation_span, SourceSpan span)
|
||||
{
|
||||
Module *module = alias->unit->module;
|
||||
Decl *instance = NULL;
|
||||
unsigned id = generic->generic_decl.id;
|
||||
FOREACH(Decl *, g, alias->unit->module->generic_sections)
|
||||
{
|
||||
if (g->generic_decl.id != id) continue;
|
||||
FOREACH (Decl *, candidate, g->generic_decl.instances)
|
||||
{
|
||||
if (candidate->name == csuffix)
|
||||
{
|
||||
instance = candidate;
|
||||
goto FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
FOUND:;
|
||||
if (!instance)
|
||||
{
|
||||
DEBUG_LOG("Generate generic instance %s", csuffix);
|
||||
if (compiler.context.errors_found) return poisoned_decl;
|
||||
instance = decl_new(DECL_GENERIC_INSTANCE, csuffix, generic->span);
|
||||
FOREACH_IDX(i, const char *, param_name, generic->generic_decl.parameters)
|
||||
{
|
||||
Decl *decl;
|
||||
Expr *param = params ? params[i] : copy_expr_single(param_decls[i]->var.init_expr);
|
||||
ASSERT_SPAN(param, param->expr_kind == EXPR_CONST);
|
||||
if (expr_is_const_typeid(param))
|
||||
{
|
||||
decl = decl_new_var(param_name, param->span, NULL, VARDECL_PARAM_CT_TYPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(param->expr_kind == EXPR_CONST);
|
||||
decl = decl_new_var(param_name, param->span, NULL, VARDECL_CONST);
|
||||
}
|
||||
decl->var.init_expr = param;
|
||||
decl->unit = alias->unit;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
decl->type = param->type;
|
||||
vec_add(instance->instance_decl.params, decl);
|
||||
}
|
||||
instance->unit = alias->unit;
|
||||
Decl **copied = NULL;
|
||||
Decl **copied_cond = NULL;
|
||||
if (!suffix)
|
||||
{
|
||||
if (!sema_generate_parameter_suffix_to_scratch(context, params, false, false)) return poisoned_decl;
|
||||
suffix = scratch_buffer_interned();
|
||||
}
|
||||
instance->instance_decl.name_suffix = suffix;
|
||||
instance->instance_decl.cname_suffix = csuffix;
|
||||
instance->instance_decl.id = id;
|
||||
FOREACH(Decl *, g, module->generic_sections)
|
||||
{
|
||||
if (g->generic_decl.id == generic->generic_decl.id)
|
||||
{
|
||||
vec_add(instance->instance_decl.templates, g);
|
||||
Decl **decls = g->generic_decl.decls;
|
||||
Decl **cond_decls = g->generic_decl.conditional_decls;
|
||||
decls = decls ? copy_decl_list_single_for_generic(decls, instance) : NULL;
|
||||
cond_decls = cond_decls ? copy_decl_list_single_for_generic(cond_decls, instance) : NULL;
|
||||
FOREACH(Decl *, d, decls) vec_add(copied, d);
|
||||
FOREACH(Decl *, d, cond_decls) vec_add(copied_cond, d);
|
||||
}
|
||||
}
|
||||
vec_add(generic->generic_decl.instances, instance);
|
||||
AnalysisStage stage = module->stage;
|
||||
ASSERT(stage > ANALYSIS_IMPORTS);
|
||||
// Add all the normal top level declarations
|
||||
FOREACH(Decl *, decl, copied) unit_register_global_decl(decl->unit, decl);
|
||||
// Add all the conditional declarations
|
||||
FOREACH(Decl *, decl, copied_cond)
|
||||
{
|
||||
unit_register_optional_global_decl(decl->unit, decl);
|
||||
if (decl->decl_kind != DECL_ERASED) vec_add(copied, decl);
|
||||
}
|
||||
if (compiler.context.errors_found) return poisoned_decl;
|
||||
|
||||
// Check contracts
|
||||
FOREACH(Decl *, decl, module->generic_sections)
|
||||
{
|
||||
if (decl->generic_decl.id == generic->generic_decl.id)
|
||||
{
|
||||
AstId contracts = decl->generic_decl.contracts;
|
||||
if (!contracts) continue;
|
||||
copy_begin();
|
||||
contracts = astid(copy_ast_macro(astptr(contracts)));
|
||||
copy_end();
|
||||
SourceSpan param_span = extend_span_with_token(params[0]->span, VECLAST(params)->span);
|
||||
if (!sema_analyse_generic_module_contracts(context, module, instance, contracts, param_span, invocation_span))
|
||||
{
|
||||
return poisoned_decl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stage < ANALYSIS_METHODS_REGISTER) goto EXIT;
|
||||
FOREACH(Decl *, decl, copied)
|
||||
{
|
||||
if (decl->decl_kind != DECL_FUNC && decl->decl_kind != DECL_MACRO) continue;
|
||||
if (!decl->func_decl.type_parent) continue;
|
||||
SemaContext gen_context;
|
||||
sema_context_init(&gen_context, decl->unit);
|
||||
gen_context.generic_instance = instance;
|
||||
if (sema_analyse_method_register(&gen_context, decl))
|
||||
{
|
||||
if (decl->decl_kind == DECL_MACRO)
|
||||
{
|
||||
vec_add(decl->unit->macro_methods, decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec_add(decl->unit->methods, decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stage < ANALYSIS_DECLS) goto EXIT;
|
||||
FOREACH(Decl *, decl, copied)
|
||||
{
|
||||
SemaContext context_gen;
|
||||
sema_context_init(&context_gen, decl->unit);
|
||||
context_gen.active_scope = (DynamicScope) { .depth = 0 };
|
||||
sema_analyse_decl(&context_gen, decl);
|
||||
context_gen.generic_instance = instance;
|
||||
sema_analyse_inner_func_ptr(&context_gen, decl);
|
||||
FOREACH(TypeInfo *, info, decl->unit->check_type_variable_array)
|
||||
{
|
||||
sema_check_type_variable_array(&context_gen, info);
|
||||
}
|
||||
sema_context_destroy(&context_gen);
|
||||
}
|
||||
if (stage < ANALYSIS_FUNCTIONS) goto EXIT;
|
||||
if (compiler.context.errors_found) return poisoned_decl;
|
||||
FOREACH(Decl *, decl, copied)
|
||||
{
|
||||
SemaContext context_gen;
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_FUNC:
|
||||
sema_context_init(&context_gen, decl->unit);
|
||||
analyse_func_body(&context_gen, decl);
|
||||
sema_context_destroy(&context_gen);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(stage < ANALYSIS_INTERFACE);
|
||||
EXIT:;
|
||||
if (compiler.context.errors_found) return poisoned_decl;
|
||||
}
|
||||
Decl *symbol = sema_find_generic_instance(context, module, generic, instance, alias->name);
|
||||
if (!symbol)
|
||||
{
|
||||
sema_error_at(context, span, "The generic '%s' does not exist for this parameterization.", alias->name);
|
||||
return poisoned_decl;
|
||||
}
|
||||
|
||||
CompilationUnit *unit = symbol->unit;
|
||||
if (unit->module->stage < ANALYSIS_POST_REGISTER)
|
||||
{
|
||||
vec_add(unit->global_decls, symbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_decl(context, symbol)) return poisoned_decl;
|
||||
}
|
||||
unit_register_external_symbol(context, symbol);
|
||||
return symbol;
|
||||
|
||||
}
|
||||
Decl *sema_analyse_parameterized_identifier(SemaContext *context, Path *decl_path, const char *name, SourceSpan span,
|
||||
Expr **params, bool *was_recursive_ref, SourceSpan invocation_span)
|
||||
{
|
||||
@@ -5261,176 +5434,9 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *context, Path *decl_pat
|
||||
ASSERT(expr_is_const(param));
|
||||
}
|
||||
}
|
||||
|
||||
Module *module = alias->unit->module;
|
||||
if (!sema_generate_parameter_suffix_to_scratch(context, params, true, was_recursive_ref)) return poisoned_decl;
|
||||
const char *suffix = scratch_buffer_interned();
|
||||
Decl *instance = NULL;
|
||||
unsigned id = generic->generic_decl.id;
|
||||
FOREACH(Decl *, g, alias->unit->module->generic_sections)
|
||||
{
|
||||
if (g->generic_decl.id != id) continue;
|
||||
FOREACH (Decl *, candidate, g->generic_decl.instances)
|
||||
{
|
||||
if (candidate->name == suffix)
|
||||
{
|
||||
instance = candidate;
|
||||
goto FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
FOUND:;
|
||||
bool instantiation = instance == NULL;
|
||||
if (!instance)
|
||||
{
|
||||
DEBUG_LOG("Generate generic instance %s", suffix);
|
||||
if (compiler.context.errors_found) return poisoned_decl;
|
||||
instance = decl_new(DECL_GENERIC_INSTANCE, suffix, generic->span);
|
||||
FOREACH_IDX(i, const char *, param_name, generic->generic_decl.parameters)
|
||||
{
|
||||
Decl *decl;
|
||||
Expr *param = params[i];
|
||||
ASSERT_SPAN(param, param->expr_kind == EXPR_CONST);
|
||||
if (expr_is_const_typeid(param))
|
||||
{
|
||||
decl = decl_new_var(param_name, param->span, NULL, VARDECL_PARAM_CT_TYPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(param->expr_kind == EXPR_CONST);
|
||||
decl = decl_new_var(param_name, param->span, NULL, VARDECL_CONST);
|
||||
}
|
||||
decl->var.init_expr = param;
|
||||
decl->unit = alias->unit;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
decl->type = param->type;
|
||||
vec_add(instance->instance_decl.params, decl);
|
||||
}
|
||||
instance->unit = alias->unit;
|
||||
Decl **copied = NULL;
|
||||
Decl **copied_cond = NULL;
|
||||
if (!sema_generate_parameter_suffix_to_scratch(context, params, false, was_recursive_ref)) return poisoned_decl;
|
||||
instance->instance_decl.name_suffix = scratch_buffer_copy();
|
||||
if (!sema_generate_parameter_suffix_to_scratch(context, params, true, was_recursive_ref)) return poisoned_decl;
|
||||
instance->instance_decl.cname_suffix = scratch_buffer_copy();
|
||||
instance->instance_decl.id = id;
|
||||
FOREACH(Decl *, g, module->generic_sections)
|
||||
{
|
||||
if (g->generic_decl.id == generic->generic_decl.id)
|
||||
{
|
||||
vec_add(instance->instance_decl.templates, g);
|
||||
Decl **decls = g->generic_decl.decls;
|
||||
Decl **cond_decls = g->generic_decl.conditional_decls;
|
||||
decls = decls ? copy_decl_list_single_for_generic(decls, instance) : NULL;
|
||||
cond_decls = cond_decls ? copy_decl_list_single_for_generic(cond_decls, instance) : NULL;
|
||||
FOREACH(Decl *, d, decls) vec_add(copied, d);
|
||||
FOREACH(Decl *, d, cond_decls) vec_add(copied_cond, d);
|
||||
}
|
||||
}
|
||||
vec_add(generic->generic_decl.instances, instance);
|
||||
AnalysisStage stage = module->stage;
|
||||
ASSERT(stage > ANALYSIS_IMPORTS);
|
||||
// Add all the normal top level declarations
|
||||
FOREACH(Decl *, decl, copied) unit_register_global_decl(decl->unit, decl);
|
||||
// Add all the conditional declarations
|
||||
FOREACH(Decl *, decl, copied_cond)
|
||||
{
|
||||
unit_register_optional_global_decl(decl->unit, decl);
|
||||
if (decl->decl_kind != DECL_ERASED) vec_add(copied, decl);
|
||||
}
|
||||
if (compiler.context.errors_found) return poisoned_decl;
|
||||
|
||||
// Check contracts
|
||||
FOREACH(Decl *, decl, module->generic_sections)
|
||||
{
|
||||
if (decl->generic_decl.id == generic->generic_decl.id)
|
||||
{
|
||||
AstId contracts = decl->generic_decl.contracts;
|
||||
if (!contracts) continue;
|
||||
copy_begin();
|
||||
contracts = astid(copy_ast_macro(astptr(contracts)));
|
||||
copy_end();
|
||||
SourceSpan param_span = extend_span_with_token(params[0]->span, params[parameter_count - 1]->span);
|
||||
if (!sema_analyse_generic_module_contracts(context, module, instance, contracts, param_span, invocation_span))
|
||||
{
|
||||
return poisoned_decl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stage < ANALYSIS_METHODS_REGISTER) goto EXIT;
|
||||
FOREACH(Decl *, decl, copied)
|
||||
{
|
||||
if (decl->decl_kind != DECL_FUNC && decl->decl_kind != DECL_MACRO) continue;
|
||||
if (!decl->func_decl.type_parent) continue;
|
||||
SemaContext gen_context;
|
||||
sema_context_init(&gen_context, decl->unit);
|
||||
gen_context.generic_instance = instance;
|
||||
if (sema_analyse_method_register(&gen_context, decl))
|
||||
{
|
||||
if (decl->decl_kind == DECL_MACRO)
|
||||
{
|
||||
vec_add(decl->unit->macro_methods, decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec_add(decl->unit->methods, decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stage < ANALYSIS_DECLS) goto EXIT;
|
||||
FOREACH(Decl *, decl, copied)
|
||||
{
|
||||
SemaContext context_gen;
|
||||
sema_context_init(&context_gen, decl->unit);
|
||||
context_gen.active_scope = (DynamicScope) { .depth = 0 };
|
||||
sema_analyse_decl(&context_gen, decl);
|
||||
context_gen.generic_instance = instance;
|
||||
sema_analyse_inner_func_ptr(&context_gen, decl);
|
||||
FOREACH(TypeInfo *, info, decl->unit->check_type_variable_array)
|
||||
{
|
||||
sema_check_type_variable_array(&context_gen, info);
|
||||
}
|
||||
sema_context_destroy(&context_gen);
|
||||
}
|
||||
if (stage < ANALYSIS_FUNCTIONS) goto EXIT;
|
||||
if (compiler.context.errors_found) return poisoned_decl;
|
||||
FOREACH(Decl *, decl, copied)
|
||||
{
|
||||
SemaContext context_gen;
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_FUNC:
|
||||
sema_context_init(&context_gen, decl->unit);
|
||||
analyse_func_body(&context_gen, decl);
|
||||
sema_context_destroy(&context_gen);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(stage < ANALYSIS_INTERFACE);
|
||||
EXIT:;
|
||||
if (compiler.context.errors_found) return poisoned_decl;
|
||||
}
|
||||
Decl *symbol = sema_find_generic_instance(context, module, generic, instance, name);
|
||||
if (!symbol)
|
||||
{
|
||||
sema_error_at(context, span, "The generic '%s' does not exist for this parameterization.", name);
|
||||
return poisoned_decl;
|
||||
}
|
||||
|
||||
CompilationUnit *unit = symbol->unit;
|
||||
if (unit->module->stage < ANALYSIS_POST_REGISTER)
|
||||
{
|
||||
vec_add(unit->global_decls, symbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_decl(context, symbol)) return poisoned_decl;
|
||||
}
|
||||
unit_register_external_symbol(context, symbol);
|
||||
return symbol;
|
||||
return sema_generate_parameterized_identifier(context, generic, alias, params, NULL, NULL, suffix, invocation_span, span);
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_attribute_decl(SemaContext *context, SemaContext *c, Decl *decl, bool *erase_decl)
|
||||
|
||||
@@ -127,6 +127,8 @@ void cast_promote_vararg(Expr *arg);
|
||||
Type *cast_numeric_arithmetic_promotion(Type *type);
|
||||
void cast_to_int_to_max_bit_size(Expr *lhs, Expr *rhs, Type *left_type, Type *right_type);
|
||||
bool sema_decl_if_cond(SemaContext *context, Decl *decl);
|
||||
Decl *sema_generate_parameterized_identifier(SemaContext *context, Decl *generic, Decl *alias, Expr **params,
|
||||
Decl **param_decls, const char *suffix, const char *csuffix, SourceSpan invocation_span, SourceSpan span);
|
||||
Decl *sema_analyse_parameterized_identifier(SemaContext *context, Path *decl_path, const char *name, SourceSpan span,
|
||||
Expr **params, bool *was_recursive_ref, SourceSpan invocation_span);
|
||||
bool sema_parameterized_type_is_found(SemaContext *context, Path *decl_path, const char *name, SourceSpan span);
|
||||
|
||||
@@ -785,6 +785,22 @@ INLINE Module *sema_find_module_for_path(SemaContext *context, Path *path)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool sema_has_matching_generic_params(Decl *generic_instance, Decl *generic)
|
||||
{
|
||||
ASSERT(generic_instance->instance_decl.id != generic->generic_decl.id);
|
||||
GenericInstanceDecl *gen_instance_decl = &generic_instance->instance_decl;
|
||||
GenericDecl *gen_decl = &generic->generic_decl;
|
||||
if (vec_size(gen_instance_decl->params) != vec_size(gen_decl->parameters)) return false;
|
||||
FOREACH_IDX(i, Decl *, param, gen_instance_decl->params)
|
||||
{
|
||||
const char *param_name = gen_decl->parameters[i];
|
||||
const char *param_name_other = param->name;
|
||||
bool is_constant_a = str_is_valid_constant(param_name);
|
||||
bool is_constant_b = str_is_valid_constant(param_name_other);
|
||||
if (is_constant_a != is_constant_b) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
INLINE bool sema_resolve_symbol_common(SemaContext *context, NameResolve *name_resolve)
|
||||
{
|
||||
name_resolve->ambiguous_other_decl = NULL;
|
||||
@@ -853,9 +869,22 @@ INLINE bool sema_resolve_symbol_common(SemaContext *context, NameResolve *name_r
|
||||
{
|
||||
if (context->generic_infer->instance_decl.id != generic->generic_decl.id)
|
||||
{
|
||||
if (name_resolve->suppress_error) return name_resolve->found = NULL, true;
|
||||
RETURN_SEMA_ERROR_AT(name_resolve->span, "Found '%s' in the module '%s', but it doesn't match the inferred generic '%s'.", found->name, found->unit->module->name->module,
|
||||
context->generic_infer->unit->module->name->module);
|
||||
if (!sema_has_matching_generic_params(context->generic_infer, generic))
|
||||
{
|
||||
if (name_resolve->suppress_error) return name_resolve->found = NULL, true;
|
||||
scratch_buffer_clear();
|
||||
FOREACH (const char *, name, generic->generic_decl.parameters)
|
||||
{
|
||||
scratch_buffer_printf("%s, ", name);
|
||||
}
|
||||
scratch_buffer_delete(2);
|
||||
RETURN_SEMA_ERROR_AT(name_resolve->span, "Found '%s' in the module '%s', but it lacks parameters. Inferring parameter values does not work, since the inferred parameter list '%s' doesn't match parameter list '%s' which %s expects.", found->name, found->unit->module->name->module, context->generic_infer->instance_decl.name_suffix, scratch_buffer_to_string(), found->name);
|
||||
}
|
||||
Decl *decl = sema_generate_parameterized_identifier(context, generic, found, NULL, context->generic_infer->instance_decl.params,
|
||||
context->generic_infer->instance_decl.name_suffix, context->generic_infer->instance_decl.cname_suffix, name_resolve->span, name_resolve->span);
|
||||
if (!decl_ok(decl)) return false;
|
||||
ASSERT(decl);
|
||||
return name_resolve->found = decl, true;
|
||||
}
|
||||
Decl *candidate = sema_find_generic_instance(context, found->unit->module, generic, context->generic_infer, found->name);
|
||||
if (candidate) return name_resolve->found = candidate, true;
|
||||
|
||||
@@ -611,7 +611,7 @@ static void cpu_features_set_to_features(CpuFeatures enabled_features, CpuFeatur
|
||||
scratch_buffer_append(list[i]);
|
||||
scratch_buffer_append_char(',');
|
||||
}
|
||||
if (scratch_buffer.len > 0) scratch_buffer.len--;
|
||||
if (scratch_buffer.len > 0) scratch_buffer_delete(1);
|
||||
compiler.platform.features = scratch_buffer_copy();
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +172,7 @@ static inline StringSlice slice_from_string(const char *data);
|
||||
void slice_trim(StringSlice *slice);
|
||||
|
||||
void scratch_buffer_clear(void);
|
||||
void scratch_buffer_delete(size_t len);
|
||||
void scratch_buffer_append(const char *string);
|
||||
void scratch_buffer_append_len(const char *string, size_t len);
|
||||
bool scratch_buffer_may_append(size_t len);
|
||||
|
||||
@@ -362,6 +362,12 @@ char *str_copy(const char *start, size_t str_len)
|
||||
return dst;
|
||||
}
|
||||
|
||||
void scratch_buffer_delete(size_t len)
|
||||
{
|
||||
ASSERT(scratch_buffer.len >= len);
|
||||
scratch_buffer.len -= len;
|
||||
}
|
||||
|
||||
void scratch_buffer_clear(void)
|
||||
{
|
||||
scratch_buffer.len = 0;
|
||||
@@ -553,7 +559,7 @@ void scratch_buffer_append_remove_space(const char *start, int len)
|
||||
clast = ch;
|
||||
printed++;
|
||||
}
|
||||
if (clast == ' ' && printed > 0) scratch_buffer.len--;
|
||||
if (clast == ' ' && printed > 0) scratch_buffer_delete(1);
|
||||
}
|
||||
|
||||
void scratch_buffer_append_char(char c)
|
||||
|
||||
14
test/test_suite/generic/generic_infer_mismatch.c3
Normal file
14
test/test_suite/generic/generic_infer_mismatch.c3
Normal file
@@ -0,0 +1,14 @@
|
||||
import std;
|
||||
struct Result @generic(WithType2)
|
||||
{
|
||||
fault error;
|
||||
}
|
||||
macro err(fault error) @generic(OfType, SOME_CONST) @builtin => (Result{OfType}){ .error = error };
|
||||
|
||||
faultdef TESTIN;
|
||||
|
||||
fn int main()
|
||||
{
|
||||
Result{int} x = err(TESTIN); // #error: Found 'err' in the module 'generic_infer_mismatch', but it lacks parameters
|
||||
return 0;
|
||||
}
|
||||
14
test/test_suite/generic/generic_infer_ok.c3
Normal file
14
test/test_suite/generic/generic_infer_ok.c3
Normal file
@@ -0,0 +1,14 @@
|
||||
import std;
|
||||
struct Result @generic(WithType2)
|
||||
{
|
||||
fault error;
|
||||
}
|
||||
macro err(fault error) @generic(OfType) @builtin => (Result{OfType}){ .error = error };
|
||||
|
||||
faultdef TESTIN;
|
||||
|
||||
fn int main()
|
||||
{
|
||||
Result{int} x = err(TESTIN);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user