authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-26 03:20:46-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-02-26 03:20:46-05:00
log1eecfdaa9b9c04e50058695b8df9978ef47f121a
tree72f0b31cfeda469d31ec69ec9c2277577494ba27
parent08d595b4724217f0b2b10cd3b9e31a71698cf5c1
parentf11b9480192dea44acb92cb9edd7a91c7c73cd2f
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #785 from bnoordhuis/fix731

allow implicit cast from `S` to `?&const S`

2 files changed, 86 insertions(+), 2 deletions(-)

src/ir.cpp+15-2
......@@ -8817,16 +8817,29 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
88178817
88188818 // explicit cast from child type of maybe type to maybe type
88198819 if (wanted_type->id == TypeTableEntryIdMaybe) {
8820 if (types_match_const_cast_only(ira, wanted_type->data.maybe.child_type, actual_type, source_node).id == ConstCastResultIdOk) {
8820 TypeTableEntry *wanted_child_type = wanted_type->data.maybe.child_type;
8821 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node).id == ConstCastResultIdOk) {
88218822 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
88228823 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
88238824 actual_type->id == TypeTableEntryIdNumLitFloat)
88248825 {
8825 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type, true)) {
8826 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
88268827 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
88278828 } else {
88288829 return ira->codegen->invalid_instruction;
88298830 }
8831 } else if (wanted_child_type->id == TypeTableEntryIdPointer &&
8832 wanted_child_type->data.pointer.is_const &&
8833 is_container(actual_type)) {
8834 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_child_type, value);
8835 if (type_is_invalid(cast1->value.type))
8836 return ira->codegen->invalid_instruction;
8837
8838 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
8839 if (type_is_invalid(cast2->value.type))
8840 return ira->codegen->invalid_instruction;
8841
8842 return cast2;
88308843 }
88318844 }
88328845
test/cases/cast.zig+71
......@@ -32,6 +32,77 @@ fn funcWithConstPtrPtr(x: &const &i32) void {
3232 **x += 1;
3333}
3434
35test "implicitly cast a container to a const pointer of it" {
36 const z = Struct(void) { .x = void{} };
37 assert(0 == @sizeOf(@typeOf(z)));
38 assert(void{} == Struct(void).pointer(z).x);
39 assert(void{} == Struct(void).pointer(&z).x);
40 assert(void{} == Struct(void).maybePointer(z).x);
41 assert(void{} == Struct(void).maybePointer(&z).x);
42 assert(void{} == Struct(void).maybePointer(null).x);
43 const s = Struct(u8) { .x = 42 };
44 assert(0 != @sizeOf(@typeOf(s)));
45 assert(42 == Struct(u8).pointer(s).x);
46 assert(42 == Struct(u8).pointer(&s).x);
47 assert(42 == Struct(u8).maybePointer(s).x);
48 assert(42 == Struct(u8).maybePointer(&s).x);
49 assert(0 == Struct(u8).maybePointer(null).x);
50 const u = Union { .x = 42 };
51 assert(42 == Union.pointer(u).x);
52 assert(42 == Union.pointer(&u).x);
53 assert(42 == Union.maybePointer(u).x);
54 assert(42 == Union.maybePointer(&u).x);
55 assert(0 == Union.maybePointer(null).x);
56 const e = Enum.Some;
57 assert(Enum.Some == Enum.pointer(e));
58 assert(Enum.Some == Enum.pointer(&e));
59 assert(Enum.Some == Enum.maybePointer(e));
60 assert(Enum.Some == Enum.maybePointer(&e));
61 assert(Enum.None == Enum.maybePointer(null));
62}
63
64fn Struct(comptime T: type) type {
65 return struct {
66 const Self = this;
67 x: T,
68
69 fn pointer(self: &const Self) Self {
70 return *self;
71 }
72
73 fn maybePointer(self: ?&const Self) Self {
74 const none = Self { .x = if (T == void) void{} else 0 };
75 return *(self ?? &none);
76 }
77 };
78}
79
80const Union = union {
81 x: u8,
82
83 fn pointer(self: &const Union) Union {
84 return *self;
85 }
86
87 fn maybePointer(self: ?&const Union) Union {
88 const none = Union { .x = 0 };
89 return *(self ?? &none);
90 }
91};
92
93const Enum = enum {
94 None,
95 Some,
96
97 fn pointer(self: &const Enum) Enum {
98 return *self;
99 }
100
101 fn maybePointer(self: ?&const Enum) Enum {
102 return *(self ?? &Enum.None);
103 }
104};
105
35106test "explicit cast from integer to error type" {
36107 testCastIntToErr(error.ItBroke);
37108 comptime testCastIntToErr(error.ItBroke);