Implicit cast from T to %?T

closes #171
master
Raul Leal 2017-04-13 09:59:39 +00:00 committed by Andrew Kelley
parent 2e0b114fdc
commit 3266585606
3 changed files with 83 additions and 6 deletions

8
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"files.associations": {
"*.zig": "c",
"type_traits": "cpp",
"*.inc": "cpp",
"thread": "cpp"
}
}

View File

@ -5826,11 +5826,12 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
{ {
return true; return true;
} }
} else if ((other_type->id == TypeTableEntryIdNumLitFloat && } else if ((other_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||
const_val->data.x_bignum.kind == BigNumKindFloat) || (other_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt )) {
(other_type->id == TypeTableEntryIdNumLitInt && return true;
const_val->data.x_bignum.kind == BigNumKindInt)) } else if ((other_type->id == TypeTableEntryIdMaybe &&
{ other_type->data.maybe.child_type->id == TypeTableEntryIdInt &&
const_val->data.x_bignum.kind == BigNumKindInt)) {
return true; return true;
} }
@ -5894,6 +5895,18 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
return ImplicitCastMatchResultYes; return ImplicitCastMatchResultYes;
} }
// implicit conversion from T to %?T
if (expected_type->id == TypeTableEntryIdErrorUnion &&
expected_type->data.error.child_type->id == TypeTableEntryIdMaybe &&
ir_types_match_with_implicit_cast(
ira,
expected_type->data.error.child_type->data.maybe.child_type,
actual_type,
value))
{
return ImplicitCastMatchResultYes;
}
// implicit widening conversion // implicit widening conversion
if (expected_type->id == TypeTableEntryIdInt && if (expected_type->id == TypeTableEntryIdInt &&
actual_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdInt &&
@ -7067,6 +7080,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
} }
// explicit cast from T to %?T
if (wanted_type->id == TypeTableEntryIdErrorUnion &&
wanted_type->data.error.child_type->id == TypeTableEntryIdMaybe &&
actual_type->id != TypeTableEntryIdMaybe) {
if (types_match_const_cast_only(wanted_type->data.error.child_type->data.maybe.child_type, actual_type) ||
actual_type->id == TypeTableEntryIdNullLit ||
actual_type->id == TypeTableEntryIdNumLitInt ) {
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error.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;
}
}
// explicit cast from number literal to another type // explicit cast from number literal to another type
// explicit cast from number literal to &const integer // explicit cast from number literal to &const integer
if (actual_type->id == TypeTableEntryIdNumLitFloat || if (actual_type->id == TypeTableEntryIdNumLitFloat ||

View File

@ -65,7 +65,6 @@ fn testPeerResolveArrayConstSlice(b: bool) {
assert(mem.eql(u8, value2, "zz")); assert(mem.eql(u8, value2, "zz"));
} }
test "integer literal to &const int" { test "integer literal to &const int" {
const x: &const i32 = 3; const x: &const i32 = 3;
assert(*x == 3); assert(*x == 3);
@ -75,3 +74,41 @@ test "string literal to &const []const u8" {
const x: &const []const u8 = "hello"; const x: &const []const u8 = "hello";
assert(mem.eql(u8, *x, "hello")); assert(mem.eql(u8, *x, "hello"));
} }
test "implicitly cast from T to %?T" {
castToMaybeTypeError(1);
comptime castToMaybeTypeError(1);
}
const A = struct {
a: i32,
};
fn castToMaybeTypeError(z: i32) {
const x = i32(1);
const y: %?i32 = x;
assert(??%%y == 1);
const f = z;
const g: %?i32 = f;
const a = A{ .a = 1 };
const b: %?A = a;
assert((??%%b).a == 1);
}
test "implicitly cast from int to %?T" {
const f: %?i32 = 1;
comptime const g: %?i32 = 1;
}
test "return null from fn() -> %?&T" {
const a = returnNullFromMaybeTypeErrorRef();
const b = returnNullLitFromMaybeTypeErrorRef();
assert(%%a == null and %%b == null);
}
fn returnNullFromMaybeTypeErrorRef() -> %?&A {
const a: ?&A = null;
return a;
}
fn returnNullLitFromMaybeTypeErrorRef() -> %?&A {
return null;
}