fix meta.cast behavior; add exhaustive tests

This commit is contained in:
Vexu 2020-09-14 21:20:41 +03:00
parent d073836894
commit 29fd0c6d61
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC

View File

@ -717,7 +717,7 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
}, },
.Optional => |opt| { .Optional => |opt| {
if (@typeInfo(opt.child) == .Pointer) { if (@typeInfo(opt.child) == .Pointer) {
return @ptrCast(DestType, @alignCast(dest_ptr, target)); return @ptrCast(DestType, @alignCast(dest_ptr.alignment, target));
} }
}, },
else => {}, else => {},
@ -725,23 +725,24 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
}, },
.Optional => |dest_opt| { .Optional => |dest_opt| {
if (@typeInfo(dest_opt.child) == .Pointer) { if (@typeInfo(dest_opt.child) == .Pointer) {
const dest_ptr = @typeInfo(dest_opt.child).Pointer;
switch (@typeInfo(TargetType)) { switch (@typeInfo(TargetType)) {
.Int, .ComptimeInt => { .Int, .ComptimeInt => {
return @intToPtr(DestType, target); return @intToPtr(DestType, target);
}, },
.Pointer => { .Pointer => {
return @ptrCast(DestType, @alignCast(@alignOf(dest_opt.child.Child), target)); return @ptrCast(DestType, @alignCast(dest_ptr.alignment, target));
}, },
.Optional => |target_opt| { .Optional => |target_opt| {
if (@typeInfo(target_opt.child) == .Pointer) { if (@typeInfo(target_opt.child) == .Pointer) {
return @ptrCast(DestType, @alignCast(@alignOf(dest_opt.child.Child), target)); return @ptrCast(DestType, @alignCast(dest_ptr.alignment, target));
} }
}, },
else => {}, else => {},
} }
} }
}, },
.Enum, .EnumLiteral => { .Enum => {
if (@typeInfo(TargetType) == .Int or @typeInfo(TargetType) == .ComptimeInt) { if (@typeInfo(TargetType) == .Int or @typeInfo(TargetType) == .ComptimeInt) {
return @intToEnum(DestType, target); return @intToEnum(DestType, target);
} }
@ -749,15 +750,18 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
.Int, .ComptimeInt => { .Int, .ComptimeInt => {
switch (@typeInfo(TargetType)) { switch (@typeInfo(TargetType)) {
.Pointer => { .Pointer => {
return @as(DestType, @ptrToInt(target)); return @intCast(DestType, @ptrToInt(target));
}, },
.Optional => |opt| { .Optional => |opt| {
if (@typeInfo(opt.child) == .Pointer) { if (@typeInfo(opt.child) == .Pointer) {
return @as(DestType, @ptrToInt(target)); return @intCast(DestType, @ptrToInt(target));
} }
}, },
.Enum, .EnumLiteral => { .Enum => {
return @as(DestType, @enumToInt(target)); return @intCast(DestType, @enumToInt(target));
},
.Int, .ComptimeInt => {
return @intCast(DestType, target);
}, },
else => {}, else => {},
} }
@ -776,10 +780,18 @@ test "std.meta.cast" {
var i = @as(i64, 10); var i = @as(i64, 10);
testing.expect(cast(?*c_void, 0) == @intToPtr(?*c_void, 0));
testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16)); testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16));
testing.expect(cast(u64, @as(u32, 10)) == @as(u64, 10));
testing.expect(cast(E, 1) == .One);
testing.expect(cast(u8, E.Two) == 2);
testing.expect(cast(*u64, &i).* == @as(u64, 10)); testing.expect(cast(*u64, &i).* == @as(u64, 10));
testing.expect(cast(*i64, @as(?*align(1) i64, &i)) == &i);
testing.expect(cast(?*u8, 2) == @intToPtr(*u8, 2));
testing.expect(cast(?*i64, @as(*align(1) i64, &i)) == &i);
testing.expect(cast(?*i64, @as(?*align(1) i64, &i)) == &i);
testing.expect(cast(E, 1) == .One);
testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(*u32, 4)));
testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(?*u32, 4)));
testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10)));
testing.expectEqual(@as(u8, 2), cast(u8, E.Two));
} }