switched `iter.zip` and `iter.prod` to use `Pair` struct
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 13 Dec 2022 02:24:44 +0000 (20:24 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 13 Dec 2022 02:24:44 +0000 (20:24 -0600)
compiler/src/polymorph.h
core/container/iter.onyx
core/container/pair.onyx
tests/bugs/autopoly_limits [new file with mode: 0644]
tests/bugs/autopoly_limits.onyx [new file with mode: 0644]

index 91de95c4a3fbafa7070a89b184c19ad853c28e13..0c0583b3533e920863df8594815cf2216d59ba6b 100644 (file)
@@ -255,7 +255,10 @@ static PolySolveResult solve_poly_type(AstNode* target, AstType* type_expr, Type
         PolySolveElem elem = elem_queue[0];
         bh_arr_deleten(elem_queue, 0, 1);
 
-        if (elem.type_expr == (AstType *) target) {
+        // This check does not strictly need the `type_auto_return` check,
+        // but it does prevent bugs if the auto return type placeholder is
+        // accidentally inserted into the real type.
+        if (elem.type_expr == (AstType *) target && elem.actual != &type_auto_return) {
             result.kind = elem.kind;
 
             assert(elem.kind != PSK_Undefined);
@@ -476,7 +479,11 @@ static AstTyped* try_lookup_based_on_partial_function_type(AstFunction *pp, AstF
     }
 
     AstTyped *result = (AstTyped *) polymorphic_proc_lookup(pp, PPLM_By_Function_Type, ft->partial_function_type, pp->token);
-    if (result && result->type == NULL) {
+
+    // If the result is not ready (NULL, yield flag, no type, or `type_auto_return` as return type), wait.
+    if (result
+        && result->type == NULL
+        || (result->type->kind == Type_Kind_Function && result->type->Function.return_type == &type_auto_return)) {
         doing_nested_polymorph_lookup = 1;
         result = NULL;
     }
index ac993bd7e9336bc1aef4e57ab8cba9e9504952a4..160b02d78f5677e1c421bd43b2f1bd930d3819b7 100644 (file)
@@ -1,6 +1,6 @@
 package core.iter
 
-use core {memory, alloc, array}
+use core {memory, alloc, array, Pair}
 
 as_iterator :: #match {}
 
@@ -405,12 +405,7 @@ skip_while :: (it: Iterator($T), ctx: $Ctx, predicate: (T, Ctx) -> bool, allocat
     };
 }
 
-#local Zipped :: struct (T: type_expr, R: type_expr) {
-    first: T;
-    second: R;
-}
-
-zip :: (left_iterator: Iterator($T), right_iterator: Iterator($R), allocator := context.temp_allocator) -> Iterator(Zipped(T, R)) {
+zip :: (left_iterator: Iterator($T), right_iterator: Iterator($R), allocator := context.temp_allocator) -> Iterator(Pair(T, R)) {
     ZippedIterator :: struct (T: type_expr, R: type_expr) {
         iterator1: Iterator(T);
         iterator2: Iterator(R);
@@ -422,7 +417,7 @@ zip :: (left_iterator: Iterator($T), right_iterator: Iterator($R), allocator :=
     zipped_iterator.iterator2 = right_iterator;
     zipped_iterator.allocator = allocator;
 
-    next :: (zi: ^ZippedIterator($T, $R)) -> (Zipped(T, R), bool) {
+    next :: (zi: ^ZippedIterator($T, $R)) -> (Pair(T, R), bool) {
         v1, cont1 := zi.iterator1.next(zi.iterator1.data);
         v2, cont2 := zi.iterator2.next(zi.iterator2.data);
 
@@ -777,7 +772,7 @@ prod :: (x: $I1/Iterable, y: $I2/Iterable) => {
         ctx => {
             x_val, cont := take_one(ctx.x_iter);
             if cont {
-                return .{ x=x_val, y=ctx.y_val }, true;
+                return Pair.make(x_val, ctx.y_val), true;
             }
 
             ctx.y_val, cont = take_one(ctx.y_iter);
@@ -787,7 +782,7 @@ prod :: (x: $I1/Iterable, y: $I2/Iterable) => {
             x_val, cont = take_one(ctx.x_iter);
             if !cont do return .{}, false;
 
-            return .{ x=x_val, y=ctx.y_val }, true;
+            return Pair.make(x_val, ctx.y_val), true;
         }
     );
 }
index 292b2cc99b49da91d2278d1e93e4857997d1641b..1b043660314ed7f872cb79432018639a7132f52a 100644 (file)
@@ -16,7 +16,7 @@ Pair :: struct (First_Type: type_expr, Second_Type: type_expr) {
 }
 
 #inject Pair {
-    make :: (x: $X, y: $Y) => Pair(X, Y).{x, y};
+    make :: macro (x: $X, y: $Y) => Pair(X, Y).{x, y};
 
     _format :: (output: ^conv.Format_Output, format: ^conv.Format, p: ^Pair($First_Type, $Second_Type)) {
         conv.format(output, "({}, {})", p.first, p.second);
diff --git a/tests/bugs/autopoly_limits b/tests/bugs/autopoly_limits
new file mode 100644 (file)
index 0000000..b86592d
--- /dev/null
@@ -0,0 +1 @@
+(123, 456.0000)
diff --git a/tests/bugs/autopoly_limits.onyx b/tests/bugs/autopoly_limits.onyx
new file mode 100644 (file)
index 0000000..993cf02
--- /dev/null
@@ -0,0 +1,20 @@
+use core
+
+f :: (ctx) => {
+    x, y := 123, 456.0f;
+    if ctx.a > 0 {
+        return Pair.make(x, y), false;
+    }
+
+    return .{}, true;
+}
+
+g :: (c: $Ctx, f: (Ctx) -> ($T, bool)) -> T {
+    t, _ := f(c);
+    return t;
+}
+
+main :: () {
+    p := g(.{a = 10}, f);
+    printf("{}\n", p);
+}
\ No newline at end of file