aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-10-26 11:50:42 +0100
committergingerBill <bill@gingerbill.org>2019-10-26 11:50:42 +0100
commit2c75fe2314aa6de6c8f80d519bbb1812ad77b444 (patch)
tree9e925e975a60ee65550dac4c615f6540515db455
parent1da0668653a4bc800a56629664f4e716c4560fa3 (diff)
Allow for cycles in record polymorphic parameters but not in actualized fields
-rw-r--r--src/check_expr.cpp72
1 files changed, 41 insertions, 31 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 195443159..ea9248089 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -6127,47 +6127,57 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
defer (array_free(&operands));
bool named_fields = false;
-
- if (is_call_expr_field_value(ce)) {
- named_fields = true;
- operands = array_make<Operand>(heap_allocator(), ce->args.count);
- for_array(i, ce->args) {
- Ast *arg = ce->args[i];
- ast_node(fv, FieldValue, arg);
-
- if (fv->field->kind == Ast_Ident) {
- String name = fv->field->Ident.token.string;
- isize index = lookup_polymorphic_record_parameter(original_type, name);
- if (index >= 0) {
- TypeTuple *params = get_record_polymorphic_params(original_type);
- Entity *e = params->variables[i];
- if (e->kind == Entity_Constant) {
- check_expr_with_type_hint(c, &operands[i], fv->value, e->type);
+ {
+ // NOTE(bill, 2019-10-26): Allow a cycle in the parameters but not in the fields themselves
+ auto prev_type_path = c->type_path;
+ c->type_path = new_checker_type_path();
+ defer ({
+ destroy_checker_type_path(c->type_path);
+ c->type_path = prev_type_path;
+ });
+
+ if (is_call_expr_field_value(ce)) {
+ named_fields = true;
+ operands = array_make<Operand>(heap_allocator(), ce->args.count);
+ for_array(i, ce->args) {
+ Ast *arg = ce->args[i];
+ ast_node(fv, FieldValue, arg);
+
+ if (fv->field->kind == Ast_Ident) {
+ String name = fv->field->Ident.token.string;
+ isize index = lookup_polymorphic_record_parameter(original_type, name);
+ if (index >= 0) {
+ TypeTuple *params = get_record_polymorphic_params(original_type);
+ Entity *e = params->variables[i];
+ if (e->kind == Entity_Constant) {
+ check_expr_with_type_hint(c, &operands[i], fv->value, e->type);
+ }
}
+
}
+ check_expr_or_type(c, &operands[i], fv->value);
+ }
+ bool vari_expand = (ce->ellipsis.pos.line != 0);
+ if (vari_expand) {
+ error(ce->ellipsis, "Invalid use of '..' in a polymorphic type call'");
}
- check_expr_or_type(c, &operands[i], fv->value);
- }
- bool vari_expand = (ce->ellipsis.pos.line != 0);
- if (vari_expand) {
- error(ce->ellipsis, "Invalid use of '..' in a polymorphic type call'");
- }
+ } else {
+ operands = array_make<Operand>(heap_allocator(), 0, 2*ce->args.count);
- } else {
- operands = array_make<Operand>(heap_allocator(), 0, 2*ce->args.count);
+ Entity **lhs = nullptr;
+ isize lhs_count = -1;
- Entity **lhs = nullptr;
- isize lhs_count = -1;
+ TypeTuple *params = get_record_polymorphic_params(original_type);
+ if (params != nullptr) {
+ lhs = params->variables.data;
+ lhs_count = params->variables.count;
+ }
- TypeTuple *params = get_record_polymorphic_params(original_type);
- if (params != nullptr) {
- lhs = params->variables.data;
- lhs_count = params->variables.count;
+ check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, false);
}
- check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, false);
}
CallArgumentError err = CallArgumentError_None;