commit def4fbc9ab704b1add5c3af40692b3d26594e58e (tree)
parent 2e0b114fdce1a10b8433438d8e2251cf708a72ec
Author: Andrew Kelley <superjoe30@gmail.com>
Date: Mon, 17 Apr 2017 20:15:39 -0400
Merge branch 'raulgrell-master'
Diffstat:
2 files changed, 90 insertions(+), 5 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
@@ -5826,12 +5826,26 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
{
return true;
}
- } else if ((other_type->id == TypeTableEntryIdNumLitFloat &&
- const_val->data.x_bignum.kind == BigNumKindFloat) ||
- (other_type->id == TypeTableEntryIdNumLitInt &&
- const_val->data.x_bignum.kind == BigNumKindInt))
+ } else if ((other_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||
+ (other_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt ))
{
return true;
+ } else if (other_type->id == TypeTableEntryIdMaybe) {
+ TypeTableEntry *child_type = other_type->data.maybe.child_type;
+ if ((child_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||
+ (child_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt ))
+ {
+ return true;
+ } else if (child_type->id == TypeTableEntryIdInt && const_val->data.x_bignum.kind == BigNumKindInt) {
+ if (bignum_fits_in_bits(&const_val->data.x_bignum,
+ child_type->data.integral.bit_count,
+ child_type->data.integral.is_signed))
+ {
+ return true;
+ }
+ } else if (child_type->id == TypeTableEntryIdFloat && const_val->data.x_bignum.kind == BigNumKindFloat) {
+ return true;
+ }
}
const char *num_lit_str = (const_val->data.x_bignum.kind == BigNumKindFloat) ? "float" : "integer";
@@ -5894,6 +5908,16 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
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
if (expected_type->id == TypeTableEntryIdInt &&
actual_type->id == TypeTableEntryIdInt &&
@@ -7067,6 +7091,29 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
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)
+ {
+ TypeTableEntry *wanted_child_type = wanted_type->data.error.child_type->data.maybe.child_type;
+ if (types_match_const_cast_only(wanted_child_type, actual_type) ||
+ actual_type->id == TypeTableEntryIdNullLit ||
+ actual_type->id == TypeTableEntryIdNumLitInt ||
+ actual_type->id == TypeTableEntryIdNumLitFloat)
+ {
+ 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 &const integer
if (actual_type->id == TypeTableEntryIdNumLitFloat ||
diff --git a/test/cases/cast.zig b/test/cases/cast.zig
@@ -65,7 +65,6 @@ fn testPeerResolveArrayConstSlice(b: bool) {
assert(mem.eql(u8, value2, "zz"));
}
-
test "integer literal to &const int" {
const x: &const i32 = 3;
assert(*x == 3);
@@ -75,3 +74,41 @@ test "string literal to &const []const u8" {
const x: &const []const u8 = "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;
+}
+\ No newline at end of file