zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 1eecfdaa9b9c04e50058695b8df9978ef47f121a (tree)
parent 08d595b4724217f0b2b10cd3b9e31a71698cf5c1
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Mon, 26 Feb 2018 03:20:46 -0500

Merge pull request #785 from bnoordhuis/fix731

allow implicit cast from `S` to `?&const S`
Diffstat:
Msrc/ir.cpp | 17+++++++++++++++--
Mtest/cases/cast.zig | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/src/ir.cpp b/src/ir.cpp @@ -8817,16 +8817,29 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst // explicit cast from child type of maybe type to maybe type if (wanted_type->id == TypeTableEntryIdMaybe) { - if (types_match_const_cast_only(ira, wanted_type->data.maybe.child_type, actual_type, source_node).id == ConstCastResultIdOk) { + TypeTableEntry *wanted_child_type = wanted_type->data.maybe.child_type; + if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node).id == ConstCastResultIdOk) { return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); } else if (actual_type->id == TypeTableEntryIdNumLitInt || actual_type->id == TypeTableEntryIdNumLitFloat) { - if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type, true)) { + if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); } else { return ira->codegen->invalid_instruction; } + } else if (wanted_child_type->id == TypeTableEntryIdPointer && + wanted_child_type->data.pointer.is_const && + is_container(actual_type)) { + IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_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; } } diff --git a/test/cases/cast.zig b/test/cases/cast.zig @@ -32,6 +32,77 @@ fn funcWithConstPtrPtr(x: &const &i32) void { **x += 1; } +test "implicitly cast a container to a const pointer of it" { + const z = Struct(void) { .x = void{} }; + assert(0 == @sizeOf(@typeOf(z))); + assert(void{} == Struct(void).pointer(z).x); + assert(void{} == Struct(void).pointer(&z).x); + assert(void{} == Struct(void).maybePointer(z).x); + assert(void{} == Struct(void).maybePointer(&z).x); + assert(void{} == Struct(void).maybePointer(null).x); + const s = Struct(u8) { .x = 42 }; + assert(0 != @sizeOf(@typeOf(s))); + assert(42 == Struct(u8).pointer(s).x); + assert(42 == Struct(u8).pointer(&s).x); + assert(42 == Struct(u8).maybePointer(s).x); + assert(42 == Struct(u8).maybePointer(&s).x); + assert(0 == Struct(u8).maybePointer(null).x); + const u = Union { .x = 42 }; + assert(42 == Union.pointer(u).x); + assert(42 == Union.pointer(&u).x); + assert(42 == Union.maybePointer(u).x); + assert(42 == Union.maybePointer(&u).x); + assert(0 == Union.maybePointer(null).x); + const e = Enum.Some; + assert(Enum.Some == Enum.pointer(e)); + assert(Enum.Some == Enum.pointer(&e)); + assert(Enum.Some == Enum.maybePointer(e)); + assert(Enum.Some == Enum.maybePointer(&e)); + assert(Enum.None == Enum.maybePointer(null)); +} + +fn Struct(comptime T: type) type { + return struct { + const Self = this; + x: T, + + fn pointer(self: &const Self) Self { + return *self; + } + + fn maybePointer(self: ?&const Self) Self { + const none = Self { .x = if (T == void) void{} else 0 }; + return *(self ?? &none); + } + }; +} + +const Union = union { + x: u8, + + fn pointer(self: &const Union) Union { + return *self; + } + + fn maybePointer(self: ?&const Union) Union { + const none = Union { .x = 0 }; + return *(self ?? &none); + } +}; + +const Enum = enum { + None, + Some, + + fn pointer(self: &const Enum) Enum { + return *self; + } + + fn maybePointer(self: ?&const Enum) Enum { + return *(self ?? &Enum.None); + } +}; + test "explicit cast from integer to error type" { testCastIntToErr(error.ItBroke); comptime testCastIntToErr(error.ItBroke);