commit
1eecfdaa9b
17
src/ir.cpp
17
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
|
// explicit cast from child type of maybe type to maybe type
|
||||||
if (wanted_type->id == TypeTableEntryIdMaybe) {
|
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);
|
return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
|
||||||
} else if (actual_type->id == TypeTableEntryIdNumLitInt ||
|
} else if (actual_type->id == TypeTableEntryIdNumLitInt ||
|
||||||
actual_type->id == TypeTableEntryIdNumLitFloat)
|
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);
|
return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
|
||||||
} else {
|
} else {
|
||||||
return ira->codegen->invalid_instruction;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,77 @@ fn funcWithConstPtrPtr(x: &const &i32) void {
|
||||||
**x += 1;
|
**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" {
|
test "explicit cast from integer to error type" {
|
||||||
testCastIntToErr(error.ItBroke);
|
testCastIntToErr(error.ItBroke);
|
||||||
comptime testCastIntToErr(error.ItBroke);
|
comptime testCastIntToErr(error.ItBroke);
|
||||||
|
|
Loading…
Reference in New Issue