Commit 3266585606

Raul Leal <raulgrell@gmail.com>
2017-04-13 11:59:39
Implicit cast from T to %?T
closes #171
1 parent 2e0b114
Changed files (3)
.vscode
src
test
cases
.vscode/settings.json
@@ -0,0 +1,8 @@
+{
+    "files.associations": {
+        "*.zig": "c",
+        "type_traits": "cpp",
+        "*.inc": "cpp",
+        "thread": "cpp"
+    }
+}
\ No newline at end of file
src/ir.cpp
@@ -5826,11 +5826,12 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
         {
             return true;
         }
-    } else if ((other_type->id == TypeTableEntryIdNumLitFloat &&
-                const_val->data.x_bignum.kind == BigNumKindFloat) ||
-               (other_type->id == TypeTableEntryIdNumLitInt &&
-                const_val->data.x_bignum.kind == BigNumKindInt))
-    {
+    } else if ((other_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||
+               (other_type->id == TypeTableEntryIdNumLitInt   && const_val->data.x_bignum.kind == BigNumKindInt  )) {
+        return true;
+    } else if ((other_type->id == TypeTableEntryIdMaybe &&
+                other_type->data.maybe.child_type->id == TypeTableEntryIdInt &&
+                const_val->data.x_bignum.kind == BigNumKindInt)) {
         return true;
     }
 
@@ -5894,6 +5895,18 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
         return ImplicitCastMatchResultYes;
     }
 
+    // implicit conversion from T to %?T
+    if (expected_type->id == TypeTableEntryIdErrorUnion &&
+        expected_type->data.error.child_type->id == TypeTableEntryIdMaybe &&
+        ir_types_match_with_implicit_cast(
+            ira,
+            expected_type->data.error.child_type->data.maybe.child_type,
+            actual_type,
+            value))
+    {
+        return ImplicitCastMatchResultYes;
+    }
+
     // implicit widening conversion
     if (expected_type->id == TypeTableEntryIdInt &&
         actual_type->id == TypeTableEntryIdInt &&
@@ -7067,6 +7080,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
         return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
     }
 
+    // explicit cast from T to %?T
+    if (wanted_type->id == TypeTableEntryIdErrorUnion &&
+        wanted_type->data.error.child_type->id == TypeTableEntryIdMaybe &&
+        actual_type->id != TypeTableEntryIdMaybe) {
+        if (types_match_const_cast_only(wanted_type->data.error.child_type->data.maybe.child_type, actual_type) || 
+            actual_type->id == TypeTableEntryIdNullLit ||
+            actual_type->id == TypeTableEntryIdNumLitInt ) {
+            IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error.child_type, value);
+            if (type_is_invalid(cast1->value.type))
+                return ira->codegen->invalid_instruction;
+
+            IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+            if (type_is_invalid(cast2->value.type))
+                return ira->codegen->invalid_instruction;
+                
+            return cast2;
+        }
+    }
+
     // explicit cast from number literal to another type
     // explicit cast from number literal to &const integer
     if (actual_type->id == TypeTableEntryIdNumLitFloat ||
test/cases/cast.zig
@@ -65,7 +65,6 @@ fn testPeerResolveArrayConstSlice(b: bool) {
     assert(mem.eql(u8, value2, "zz"));
 }
 
-
 test "integer literal to &const int" {
     const x: &const i32 = 3;
     assert(*x == 3);
@@ -75,3 +74,41 @@ test "string literal to &const []const u8" {
     const x: &const []const u8 = "hello";
     assert(mem.eql(u8, *x, "hello"));
 }
+
+test "implicitly cast from T to %?T" {
+    castToMaybeTypeError(1);
+    comptime castToMaybeTypeError(1);
+}
+const A = struct {
+    a: i32,
+};
+fn castToMaybeTypeError(z: i32) {
+    const x = i32(1);
+    const y: %?i32 = x;
+    assert(??%%y == 1);
+
+    const f = z;
+    const g: %?i32 = f;
+
+    const a = A{ .a = 1 };
+    const b: %?A = a;
+    assert((??%%b).a == 1);
+}
+
+test "implicitly cast from int to %?T" {
+    const f: %?i32 = 1;
+    comptime const g: %?i32 = 1;
+}
+
+test "return null from fn() -> %?&T" {
+    const a = returnNullFromMaybeTypeErrorRef();
+    const b = returnNullLitFromMaybeTypeErrorRef();
+    assert(%%a == null and %%b == null);
+}
+fn returnNullFromMaybeTypeErrorRef() -> %?&A {
+    const a: ?&A = null;
+    return a;
+}
+fn returnNullLitFromMaybeTypeErrorRef() -> %?&A {
+    return null;
+}
\ No newline at end of file