Skip to content

Commit

Permalink
document & impl the transmutation modeled by BikeshedIntrinsicFrom
Browse files Browse the repository at this point in the history
Documents that `BikeshedIntrinsicFrom` models transmute-via-union,
which is slightly more expressive than the transmute-via-cast
implemented by `transmute_copy`. Additionally, we provide an
implementation of transmute-via-union as a method on the
`BikeshedIntrinsicFrom` trait with additional documentation on
the boundary between trait invariants and caller obligations.

Whether or not transmute-via-union is the right kind of transmute
to model remains up for discussion [1]. Regardless, it seems wise
to document the present behavior.

[1] https://rust-lang.zulipchat.com/#narrow/stream/216762-project-safe-transmute/topic/What.20'kind'.20of.20transmute.20to.20model.3F/near/426331967
  • Loading branch information
jswrenn committed Aug 23, 2024
1 parent 4d5b3b1 commit 2540070
Show file tree
Hide file tree
Showing 17 changed files with 372 additions and 38 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_ty_utils/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,11 @@ fn resolve_associated_item<'tcx>(
tcx.item_name(trait_item_id)
),
}
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::TransmuteTrait) {
let name = tcx.item_name(trait_item_id);
assert_eq!(name, sym::transmute);
let args = tcx.erase_regions(rcvr_args);
Some(ty::Instance::new(trait_item_id, args))
} else {
Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args)
}
Expand Down
371 changes: 350 additions & 21 deletions library/core/src/mem/transmutability.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/mir-opt/issue_72181_1.main.built.after.mir
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() -> () {
StorageLive(_2);
StorageLive(_3);
_3 = ();
_2 = transmute::<(), Void>(move _3) -> bb4;
_2 = std::intrinsics::transmute::<(), Void>(move _3) -> bb4;
}

bb1: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
bb0: {
StorageLive(_2);
_2 = copy _1;
- _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable];
- _0 = std::intrinsics::transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable];
+ _0 = move _2 as i8 (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
bb0: {
StorageLive(_2);
_2 = copy _1;
- _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable];
- _0 = std::intrinsics::transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable];
+ _0 = move _2 as i8 (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
bb0: {
StorageLive(_2);
_2 = copy _1;
- _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable];
- _0 = std::intrinsics::transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable];
+ _0 = move _2 as *const T (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
bb0: {
StorageLive(_2);
_2 = copy _1;
- _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable];
- _0 = std::intrinsics::transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable];
+ _0 = move _2 as *const T (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

bb0: {
StorageLive(_1);
- _1 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable];
- _1 = std::intrinsics::transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable];
+ _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

bb0: {
StorageLive(_1);
- _1 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable];
- _1 = std::intrinsics::transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable];
+ _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

bb0: {
StorageLive(_1);
- _1 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable];
- _1 = std::intrinsics::transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable];
+ _1 = const 1_usize as &mut Never (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

bb0: {
StorageLive(_1);
- _1 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable];
- _1 = std::intrinsics::transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable];
+ _1 = const 1_usize as &mut Never (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

bb0: {
StorageLive(_1);
- _1 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable];
- _1 = std::intrinsics::transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable];
+ _1 = const 1_usize as &Never (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

bb0: {
StorageLive(_1);
- _1 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable];
- _1 = std::intrinsics::transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable];
+ _1 = const 1_usize as &Never (Transmute);
+ goto -> bb1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
bb0: {
StorageLive(_2);
_2 = copy _1;
- _0 = transmute::<(), Never>(move _2) -> unwind unreachable;
- _0 = std::intrinsics::transmute::<(), Never>(move _2) -> unwind unreachable;
+ _0 = move _2 as Never (Transmute);
+ unreachable;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
bb0: {
StorageLive(_2);
_2 = copy _1;
- _0 = transmute::<(), Never>(move _2) -> unwind unreachable;
- _0 = std::intrinsics::transmute::<(), Never>(move _2) -> unwind unreachable;
+ _0 = move _2 as Never (Transmute);
+ unreachable;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/closures/coerce-unsafe-to-closure.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
--> $DIR/coerce-unsafe-to-closure.rs:2:44
|
LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
| --- ^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
| |
| required by a bound introduced by this call
|
= help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
= help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `Option::<T>::map`
--> $SRC_DIR/core/src/option.rs:LL:COL
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/intrinsics/reify-intrinsic.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr
| expected due to this
|
= note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize`
found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`

error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
--> $DIR/reify-intrinsic.rs:11:13
|
LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
Expand Down

0 comments on commit 2540070

Please sign in to comment.