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
58265826 {
58275827 return true;
58285828 }
5829 } else if ((other_type->id == TypeTableEntryIdNumLitFloat &&
5830 const_val->data.x_bignum.kind == BigNumKindFloat) ||
5831 (other_type->id == TypeTableEntryIdNumLitInt &&
5832 const_val->data.x_bignum.kind == BigNumKindInt))
5833 {
5829 } else if ((other_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||
5830 (other_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt )) {
5831 return true;
5832 } else if ((other_type->id == TypeTableEntryIdMaybe &&
5833 other_type->data.maybe.child_type->id == TypeTableEntryIdInt &&
5834 const_val->data.x_bignum.kind == BigNumKindInt)) {
58345835 return true;
58355836 }
58365837
......@@ -5894,6 +5895,18 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
58945895 return ImplicitCastMatchResultYes;
58955896 }
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
58975910 // implicit widening conversion
58985911 if (expected_type->id == TypeTableEntryIdInt &&
58995912 actual_type->id == TypeTableEntryIdInt &&
......@@ -7067,6 +7080,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
70677080 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
70687081 }
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
70707102 // explicit cast from number literal to another type
70717103 // explicit cast from number literal to &const integer
70727104 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
test/cases/cast.zig+38-1
......@@ -65,7 +65,6 @@ fn testPeerResolveArrayConstSlice(b: bool) {
6565 assert(mem.eql(u8, value2, "zz"));
6666}
6767
68
6968test "integer literal to &const int" {
7069 const x: &const i32 = 3;
7170 assert(*x == 3);
......@@ -75,3 +74,41 @@ test "string literal to &const []const u8" {
7574 const x: &const []const u8 = "hello";
7675 assert(mem.eql(u8, *x, "hello"));
7776}
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