Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 50a7499

Browse files
authoredMar 16, 2025
Unrolled build for rust-lang#137864
Rollup merge of rust-lang#137864 - compiler-errors:unsafe-binder-gvn, r=oli-obk Don't drop `Rvalue::WrapUnsafeBinder` during GVN ...and instead use `Value::WrapUnsafeBinder` to properly propagate consts through `wrap_binder!()` in GVN. Fixes rust-lang#137846 r? oli-obk
2 parents 9f274ba + 13134dd commit 50a7499

File tree

4 files changed

+102
-2
lines changed

4 files changed

+102
-2
lines changed
 

‎compiler/rustc_mir_transform/src/gvn.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -872,8 +872,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
872872
self.simplify_place_projection(place, location);
873873
return self.new_pointer(*place, AddressKind::Address(mutbl));
874874
}
875-
Rvalue::WrapUnsafeBinder(ref mut op, _) => {
876-
return self.simplify_operand(op, location);
875+
Rvalue::WrapUnsafeBinder(ref mut op, ty) => {
876+
let value = self.simplify_operand(op, location)?;
877+
Value::Cast {
878+
kind: CastKind::Transmute,
879+
value,
880+
from: op.ty(self.local_decls, self.tcx),
881+
to: ty,
882+
}
877883
}
878884

879885
// Operations.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
- // MIR for `propagate` before GVN
2+
+ // MIR for `propagate` after GVN
3+
4+
fn propagate() -> unsafe<> i32 {
5+
let mut _0: unsafe<> i32;
6+
let _1: i32;
7+
let mut _3: i32;
8+
scope 1 {
9+
debug x => _1;
10+
let _2: unsafe<> i32;
11+
scope 2 {
12+
debug binder => _2;
13+
}
14+
}
15+
16+
bb0: {
17+
- StorageLive(_1);
18+
+ nop;
19+
_1 = const 1_i32;
20+
StorageLive(_2);
21+
StorageLive(_3);
22+
- _3 = copy _1;
23+
- _2 = wrap_binder!(move _3; unsafe<> i32);
24+
+ _3 = const 1_i32;
25+
+ _2 = const {transmute(0x00000001): unsafe<> i32};
26+
StorageDead(_3);
27+
- _0 = move _2;
28+
+ _0 = const {transmute(0x00000001): unsafe<> i32};
29+
StorageDead(_2);
30+
- StorageDead(_1);
31+
+ nop;
32+
return;
33+
}
34+
}
35+

‎tests/mir-opt/gvn_on_unsafe_binder.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// skip-filecheck
2+
//@ test-mir-pass: GVN
3+
4+
// EMIT_MIR gvn_on_unsafe_binder.test.GVN.diff
5+
// EMIT_MIR gvn_on_unsafe_binder.propagate.GVN.diff
6+
7+
#![feature(unsafe_binders)]
8+
9+
use std::unsafe_binder::wrap_binder;
10+
11+
// Test for ICE <https://github.com/rust-lang/rust/issues/137846>.
12+
fn test() {
13+
unsafe {
14+
let x = 1;
15+
let binder: unsafe<'a> &'a i32 = wrap_binder!(&x);
16+
}
17+
}
18+
19+
// Test that GVN propagates const values through unsafe binders.
20+
//
21+
// The lifetime `'a` is redundant (and doesn't print when we print out the type).
22+
// However, we need it so that rustfmt doesn't rip out the `unsafe<>` part for now.
23+
fn propagate() -> unsafe<'a> i32 {
24+
unsafe {
25+
let x = 1;
26+
let binder: unsafe<'a> i32 = wrap_binder!(x);
27+
binder
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
- // MIR for `test` before GVN
2+
+ // MIR for `test` after GVN
3+
4+
fn test() -> () {
5+
let mut _0: ();
6+
let _1: i32;
7+
let mut _3: &i32;
8+
scope 1 {
9+
debug x => _1;
10+
let _2: unsafe<'a> &'a i32;
11+
scope 2 {
12+
debug binder => _2;
13+
}
14+
}
15+
16+
bb0: {
17+
StorageLive(_1);
18+
_1 = const 1_i32;
19+
StorageLive(_2);
20+
StorageLive(_3);
21+
_3 = &_1;
22+
_2 = wrap_binder!(move _3; unsafe<'a> &'a i32);
23+
StorageDead(_3);
24+
_0 = const ();
25+
StorageDead(_2);
26+
StorageDead(_1);
27+
return;
28+
}
29+
}
30+

0 commit comments

Comments
 (0)
Failed to load comments.