Browse Source

Allow for cycles in record polymorphic parameters but not in actualized fields

gingerBill 5 years ago
parent
commit
2c75fe2314
1 changed files with 41 additions and 31 deletions
  1. 41 31
      src/check_expr.cpp

+ 41 - 31
src/check_expr.cpp

@@ -6127,47 +6127,57 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
 	defer (array_free(&operands));
 	defer (array_free(&operands));
 
 
 	bool named_fields = false;
 	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;
 	CallArgumentError err = CallArgumentError_None;