Commit b7b905d227

Andrew Kelley <andrew@ziglang.org>
2022-12-07 01:57:27
add behavior test for while(true) not needing else unreachable
closes #707
1 parent e7d2834
lib/std/event/loop.zig
@@ -1469,7 +1469,7 @@ pub const Loop = struct {
                             .Cancelled => continue,
                         }
                         if (overlapped) |o| break o;
-                    } else unreachable; // TODO else unreachable should not be necessary
+                    };
                     const resume_node = @fieldParentPtr(ResumeNode, "overlapped", overlapped);
                     const handle = resume_node.handle;
                     const resume_node_id = resume_node.id;
lib/std/zig/render.zig
@@ -2211,7 +2211,7 @@ fn renderAsm(
             },
             else => unreachable,
         }
-    } else unreachable; // TODO shouldn't need this on while(true)
+    }
 }
 
 fn renderCall(
lib/std/zig/string_literal.zig
@@ -266,7 +266,7 @@ pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result
                 index += 1;
             },
         }
-    } else unreachable; // TODO should not need else unreachable on while(true)
+    }
 }
 
 /// Higher level API. Does not return extra info about parse errors.
lib/std/os.zig
@@ -3621,7 +3621,7 @@ pub fn accept(
                 else => |err| return unexpectedErrno(err),
             }
         }
-    } else unreachable;
+    };
 
     if (!have_accept4) {
         try setSockFlags(accepted_sock, flags);
src/print_air.zig
@@ -848,7 +848,7 @@ const Writer = struct {
                 if ((bits >> 31) != 0) break :blk false;
                 extra_index += 1;
                 tomb_op_index += 31;
-            } else unreachable;
+            }
         };
         return w.writeInstRef(s, operand, dies);
     }
src/Sema.zig
@@ -1359,7 +1359,7 @@ fn analyzeBodyInner(
                             break check_block.runtime_index;
                         }
                         check_block = check_block.parent.?;
-                    } else unreachable;
+                    };
 
                     if (@enumToInt(target_runtime_index) < @enumToInt(block.runtime_index)) {
                         const runtime_src = block.runtime_cond orelse block.runtime_loop.?;
@@ -1733,7 +1733,7 @@ fn analyzeBodyInner(
             break always_noreturn;
         map.putAssumeCapacity(inst, air_inst);
         i += 1;
-    } else unreachable;
+    };
 
     // balance out dbg_block_begins in case of early noreturn
     const noreturn_inst = block.instructions.popOrNull();
@@ -3478,7 +3478,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
                 .store => break candidate,
                 else => break :ct,
             }
-        } else unreachable; // TODO shouldn't need this
+        };
 
         while (true) {
             if (search_index == 0) break :ct;
@@ -3704,7 +3704,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
                         .store => break candidate,
                         else => break :ct,
                     }
-                } else unreachable; // TODO shouldn't need this
+                };
 
                 const bitcast_inst = while (true) {
                     if (search_index == 0) break :ct;
@@ -3716,7 +3716,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
                         .bitcast => break candidate,
                         else => break :ct,
                     }
-                } else unreachable; // TODO shouldn't need this
+                };
 
                 const const_inst = while (true) {
                     if (search_index == 0) break :ct;
@@ -3728,7 +3728,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
                         .constant => break candidate,
                         else => break :ct,
                     }
-                } else unreachable; // TODO shouldn't need this
+                };
 
                 const store_op = air_datas[store_inst].bin_op;
                 const store_val = (try sema.resolveMaybeUndefVal(store_op.rhs)) orelse break :ct;
@@ -14964,7 +14964,7 @@ fn zirClosureGet(
             break tv;
         }
         scope = scope.parent.?;
-    } else unreachable;
+    };
 
     if (tv.val.tag() == .unreachable_value and !block.is_typeof and sema.func == null) {
         const msg = msg: {
src/translate_c.zig
@@ -523,7 +523,7 @@ fn declVisitorNamesOnly(c: *Context, decl: *const clang.Decl) Error!void {
                     child_ty = macroqualified_ty.getModifiedType().getTypePtr();
                 },
                 else => return,
-            } else unreachable;
+            };
 
             const result = try c.unnamed_typedefs.getOrPut(c.gpa, addr);
             if (result.found_existing) {
@@ -629,7 +629,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
             },
             else => break fn_type,
         }
-    } else unreachable;
+    };
     const fn_ty = @ptrCast(*const clang.FunctionType, fn_type);
     const return_qt = fn_ty.getReturnType();
 
test/behavior/while.zig
@@ -364,3 +364,10 @@ test "try terminating an infinite loop" {
         _ = try Foo.bar();
     } else unreachable);
 }
+
+test "while loop with comptime true condition needs no else block to return value with break" {
+    const x = while (true) {
+        break @as(u32, 69);
+    };
+    try expect(x == 69);
+}