diff --git a/src/AstGen.zig b/src/AstGen.zig index c93bab8294..81cb93671e 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -7526,18 +7526,8 @@ fn as( rhs: Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const dest_type = try typeExpr(gz, scope, lhs); - switch (ri.rl) { - .none, .discard, .ref, .ty, .coerced_ty => { - const result = try reachableExpr(gz, scope, .{ .rl = .{ .ty = dest_type } }, rhs, node); - return rvalue(gz, ri, result, node); - }, - .ptr => |result_ptr| { - return asRlPtr(gz, scope, ri, node, result_ptr.inst, rhs, dest_type); - }, - .inferred_ptr => |result_ptr| { - return asRlPtr(gz, scope, ri, node, result_ptr, rhs, dest_type); - }, - } + const result = try reachableExpr(gz, scope, .{ .rl = .{ .ty = dest_type } }, rhs, node); + return rvalue(gz, ri, result, node); } fn unionInit( @@ -7562,24 +7552,6 @@ fn unionInit( return rvalue(gz, ri, result, node); } -fn asRlPtr( - gz: *GenZir, - scope: *Scope, - ri: ResultInfo, - src_node: Ast.Node.Index, - result_ptr: Zir.Inst.Ref, - operand_node: Ast.Node.Index, - dest_type: Zir.Inst.Ref, -) InnerError!Zir.Inst.Ref { - if (gz.astgen.nodes_need_rl.contains(src_node)) { - const casted_ptr = try gz.addPlNode(.coerce_result_ptr, src_node, Zir.Inst.Bin{ .lhs = dest_type, .rhs = result_ptr }); - return reachableExpr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = casted_ptr } } }, operand_node, src_node); - } else { - const result = try reachableExpr(gz, scope, .{ .rl = .{ .ty = dest_type } }, operand_node, src_node); - return rvalue(gz, ri, result, src_node); - } -} - fn bitCast( gz: *GenZir, scope: *Scope, diff --git a/src/AstRlAnnotate.zig b/src/AstRlAnnotate.zig index 2a84de64d0..5b42212fa5 100644 --- a/src/AstRlAnnotate.zig +++ b/src/AstRlAnnotate.zig @@ -800,6 +800,8 @@ fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: } fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, args: []const Ast.Node.Index) !bool { + _ = ri; // Currently, no builtin consumes its result location. + const tree = astrl.tree; const main_tokens = tree.nodes.items(.main_token); const builtin_token = main_tokens[node]; @@ -818,11 +820,8 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. }, .as => { _ = try astrl.expr(args[0], block, ResultInfo.type_only); - const rhs_consumes_rl = try astrl.expr(args[1], block, ri); - if (rhs_consumes_rl) { - try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); - } - return rhs_consumes_rl; + _ = try astrl.expr(args[1], block, ResultInfo.type_only); + return false; }, .bit_cast => { _ = try astrl.expr(args[0], block, ResultInfo.none); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 334259661d..34d18f6717 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -2502,3 +2502,21 @@ test "numeric coercions with undefined" { to = 42.0; try expectEqual(@as(f32, 42.0), to); } + +test "@as does not corrupt values with incompatible representations" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + + const x: f32 = @as(f16, blk: { + if (false) { + // Trick the compiler into trying to use a result pointer if it can! + break :blk .{undefined}; + } + break :blk 1.23; + }); + try std.testing.expectApproxEqAbs(@as(f32, 1.23), x, 0.001); +}