Commit 37ab960492

Andrew Kelley <andrew@ziglang.org>
2020-01-28 00:59:46
fix not handling undefined u0 correctly
1 parent b38b967
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -15644,9 +15644,27 @@ static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type,
 }
 
 // Returns ErrorNotLazy when the value cannot be determined
-static Error lazy_cmp_zero(AstNode *source_node, ZigValue *val, Cmp *result) {
+static Error lazy_cmp_zero(CodeGen *codegen, AstNode *source_node, ZigValue *val, Cmp *result) {
     Error err;
 
+    switch (type_has_one_possible_value(codegen, val->type)) {
+        case OnePossibleValueInvalid:
+            return ErrorSemanticAnalyzeFail;
+        case OnePossibleValueNo:
+            break;
+        case OnePossibleValueYes:
+            switch (val->type->id) {
+                case ZigTypeIdInt:
+                    src_assert(val->type->data.integral.bit_count == 0, source_node);
+                    *result = CmpEQ;
+                    return ErrorNone;
+                case ZigTypeIdUndefined:
+                    return ErrorNotLazy;
+                default:
+                    zig_unreachable();
+            }
+    }
+
     switch (val->special) {
         case ConstValSpecialRuntime:
         case ConstValSpecialUndef:
@@ -15700,12 +15718,12 @@ static ErrorMsg *ir_eval_bin_op_cmp_scalar(IrAnalyze *ira, IrInst* source_instr,
         // Before resolving the values, we special case comparisons against zero. These can often
         // be done without resolving lazy values, preventing potential dependency loops.
         Cmp op1_cmp_zero;
-        if ((err = lazy_cmp_zero(source_instr->source_node, op1_val, &op1_cmp_zero))) {
+        if ((err = lazy_cmp_zero(ira->codegen, source_instr->source_node, op1_val, &op1_cmp_zero))) {
             if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally;
             return ira->codegen->trace_err;
         }
         Cmp op2_cmp_zero;
-        if ((err = lazy_cmp_zero(source_instr->source_node, op2_val, &op2_cmp_zero))) {
+        if ((err = lazy_cmp_zero(ira->codegen, source_instr->source_node, op2_val, &op2_cmp_zero))) {
             if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally;
             return ira->codegen->trace_err;
         }
@@ -15869,14 +15887,14 @@ static IrInstGen *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInst *source_i
     }
     Cmp op1_cmp_zero;
     bool have_op1_cmp_zero = false;
-    if ((err = lazy_cmp_zero(source_instr->source_node, op1->value, &op1_cmp_zero))) {
+    if ((err = lazy_cmp_zero(ira->codegen, source_instr->source_node, op1->value, &op1_cmp_zero))) {
         if (err != ErrorNotLazy) return ira->codegen->invalid_inst_gen;
     } else {
         have_op1_cmp_zero = true;
     }
     Cmp op2_cmp_zero;
     bool have_op2_cmp_zero = false;
-    if ((err = lazy_cmp_zero(source_instr->source_node, op2->value, &op2_cmp_zero))) {
+    if ((err = lazy_cmp_zero(ira->codegen, source_instr->source_node, op2->value, &op2_cmp_zero))) {
         if (err != ErrorNotLazy) return ira->codegen->invalid_inst_gen;
     } else {
         have_op2_cmp_zero = true;
test/stage1/behavior/eval.zig
@@ -804,3 +804,16 @@ test "comptime assign int to optional int" {
         expectEqual(20, x.?);
     }
 }
+
+test "return 0 from function that has u0 return type" {
+    const S = struct {
+        fn foo_zero() u0 {
+            return 0;
+        }
+    };
+    comptime {
+        if (S.foo_zero() != 0) {
+            @compileError("test failed");
+        }
+    }
+}