authorgravatar for raulgrell@gmail.comRaul Leal <raulgrell@gmail.com> 2017-04-13 09:59:39+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-17 19:55:56-04:00
log32665856064dde5a08a64de8641c8bec9c6f352f
treed3bfd0cac9667ab0c0cd8b70658c8f4d1011db1a
parent2e0b114fdce1a10b8433438d8e2251cf708a72ec

Implicit cast from T to %?T

closes #171

3 files changed, 83 insertions(+), 6 deletions(-)

.vscode/settings.json created+8
...@@ -0,0 +1,8 @@
1{
2 "files.associations": {
3 "*.zig": "c",
4 "type_traits": "cpp",
5 "*.inc": "cpp",
6 "thread": "cpp"
7 }
8}
\ No newline at end of file
src/ir.cpp+37-5
...@@ -5826,11 +5826,12 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -5826,11 +5826,12 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
5826 {5826 {
5827 return true;5827 return true;
5828 }5828 }
5829 } else if ((other_type->id == TypeTableEntryIdNumLitFloat &&5829 } else if ((other_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||
5830 const_val->data.x_bignum.kind == BigNumKindFloat) ||5830 (other_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt )) {
5831 (other_type->id == TypeTableEntryIdNumLitInt &&5831 return true;
5832 const_val->data.x_bignum.kind == BigNumKindInt))5832 } else if ((other_type->id == TypeTableEntryIdMaybe &&
5833 {5833 other_type->data.maybe.child_type->id == TypeTableEntryIdInt &&
5834 const_val->data.x_bignum.kind == BigNumKindInt)) {
5834 return true;5835 return true;
5835 }5836 }
58365837
...@@ -5894,6 +5895,18 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,...@@ -5894,6 +5895,18 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
5894 return ImplicitCastMatchResultYes;5895 return ImplicitCastMatchResultYes;
5895 }5896 }
58965897
5898 // implicit conversion from T to %?T
5899 if (expected_type->id == TypeTableEntryIdErrorUnion &&
5900 expected_type->data.error.child_type->id == TypeTableEntryIdMaybe &&
5901 ir_types_match_with_implicit_cast(
5902 ira,
5903 expected_type->data.error.child_type->data.maybe.child_type,
5904 actual_type,
5905 value))
5906 {
5907 return ImplicitCastMatchResultYes;
5908 }
5909
5897 // implicit widening conversion5910 // implicit widening conversion
5898 if (expected_type->id == TypeTableEntryIdInt &&5911 if (expected_type->id == TypeTableEntryIdInt &&
5899 actual_type->id == TypeTableEntryIdInt &&5912 actual_type->id == TypeTableEntryIdInt &&
...@@ -7067,6 +7080,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -7067,6 +7080,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
7067 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);7080 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
7068 }7081 }
70697082
7083 // explicit cast from T to %?T
7084 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
7085 wanted_type->data.error.child_type->id == TypeTableEntryIdMaybe &&
7086 actual_type->id != TypeTableEntryIdMaybe) {
7087 if (types_match_const_cast_only(wanted_type->data.error.child_type->data.maybe.child_type, actual_type) ||
7088 actual_type->id == TypeTableEntryIdNullLit ||
7089 actual_type->id == TypeTableEntryIdNumLitInt ) {
7090 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error.child_type, value);
7091 if (type_is_invalid(cast1->value.type))
7092 return ira->codegen->invalid_instruction;
7093
7094 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
7095 if (type_is_invalid(cast2->value.type))
7096 return ira->codegen->invalid_instruction;
7097
7098 return cast2;
7099 }
7100 }
7101
7070 // explicit cast from number literal to another type7102 // explicit cast from number literal to another type
7071 // explicit cast from number literal to &const integer7103 // explicit cast from number literal to &const integer
7072 if (actual_type->id == TypeTableEntryIdNumLitFloat ||7104 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
test/cases/cast.zig+38-1
...@@ -65,7 +65,6 @@ fn testPeerResolveArrayConstSlice(b: bool) {...@@ -65,7 +65,6 @@ fn testPeerResolveArrayConstSlice(b: bool) {
65 assert(mem.eql(u8, value2, "zz"));65 assert(mem.eql(u8, value2, "zz"));
66}66}
6767
68
69test "integer literal to &const int" {68test "integer literal to &const int" {
70 const x: &const i32 = 3;69 const x: &const i32 = 3;
71 assert(*x == 3);70 assert(*x == 3);
...@@ -75,3 +74,41 @@ test "string literal to &const []const u8" {...@@ -75,3 +74,41 @@ test "string literal to &const []const u8" {
75 const x: &const []const u8 = "hello";74 const x: &const []const u8 = "hello";
76 assert(mem.eql(u8, *x, "hello"));75 assert(mem.eql(u8, *x, "hello"));
77}76}
77
78test "implicitly cast from T to %?T" {
79 castToMaybeTypeError(1);
80 comptime castToMaybeTypeError(1);
81}
82const A = struct {
83 a: i32,
84};
85fn castToMaybeTypeError(z: i32) {
86 const x = i32(1);
87 const y: %?i32 = x;
88 assert(??%%y == 1);
89
90 const f = z;
91 const g: %?i32 = f;
92
93 const a = A{ .a = 1 };
94 const b: %?A = a;
95 assert((??%%b).a == 1);
96}
97
98test "implicitly cast from int to %?T" {
99 const f: %?i32 = 1;
100 comptime const g: %?i32 = 1;
101}
102
103test "return null from fn() -> %?&T" {
104 const a = returnNullFromMaybeTypeErrorRef();
105 const b = returnNullLitFromMaybeTypeErrorRef();
106 assert(%%a == null and %%b == null);
107}
108fn returnNullFromMaybeTypeErrorRef() -> %?&A {
109 const a: ?&A = null;
110 return a;
111}
112fn returnNullLitFromMaybeTypeErrorRef() -> %?&A {
113 return null;
114}
\ No newline at end of file