Skip to content

Initial implementation of UnsafePinned and UnsafeUnpin (RFC 3467) #136964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

Sky9x
Copy link
Contributor

@Sky9x Sky9x commented Feb 13, 2025

Tracking issue: #125735

An attempt at an initial implementation for RFC 3467

cc @RalfJung

@rustbot
Copy link
Collaborator

rustbot commented Feb 13, 2025

r? @Noratrieb

rustbot has assigned @Noratrieb.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Feb 13, 2025
@Sky9x
Copy link
Contributor Author

Sky9x commented Feb 13, 2025

@rustbot label T-libs-api T-lang T-opsem F-unsafe_pinned S-waiting-on-author -S-waiting-on-review

@rustbot rustbot added F-unsafe_pinned `#![feature(unsafe_pinned)]` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. T-opsem Relevant to the opsem team and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 13, 2025
@rustbot
Copy link
Collaborator

rustbot commented Feb 13, 2025

Failed to set assignee to ghost: invalid assignee

Note: Only org members with at least the repository "read" role, users with write permissions, or people who have commented on the PR may be assigned.

Comment on lines -1067 to +1071
if self.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::Unpin) =>
if self.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::Unpin)
|| self.cx().is_lang_item(
goal.predicate.def_id(),
TraitSolverLangItem::UnsafeUnpin,
) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still very unsure if this is ok, I think so? I'm not sure how to "wrap" coroutine fields in UnsafePinned (and if that would make any difference from just not implementing UnsafePinned directly)

Comment on lines -730 to +731
if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
if self.tcx().is_lang_item(def_id, LangItem::Unpin)
|| self.tcx().is_lang_item(def_id, LangItem::UnsafeUnpin) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also unsure about this, just matching the logic in the new solver for now?

Comment on lines -26 to -28
// We rely on the fact that async/await futures are immovable in order to create
// self-referential borrows in the underlying coroutine.
impl<T: Coroutine<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dubious change

@Sky9x
Copy link
Contributor Author

Sky9x commented Feb 13, 2025

Unresolved question from the RFC:

How do we transition code that relies on Unpin opting-out of aliasing guarantees to the new type? Here's a plan: define the PhantomPinned type as UnsafePinned<()>.

Not exactly possible as PhantomPinned would no longer be a unit struct. I opted for instead adding an impl !UnsafeUnpin for PhantomPinned

Places in the standard library that use impl !Unpin for and the generator lowering are adjusted to use UnsafePinned instead.

still need to figure out generator lowering

Then as long as nobody outside the standard library used the unstable impl !Unpin for, switching the noalias-opt-out to the UnsafeUnpin trait is actually backwards compatible with the (never explicitly supported) Unpin hack!
However, if we ever make UnsafePinned location-relevant (i.e., only data inside the UnsafePinned is allowed to have aliases), then unsafe code in the ecosystem needs to be adjusted.
The justification for this is that currently this code relies on undocumented unstable behavior (using !Unpin to opt-out of aliasing guarantees), so we are in our right to declare it unsound.
Of course we should give the ecosystem time to migrate to the new approach before we actually start doing optimizations that exploit this UB.

hopefully since all (stable) ecosystem code uses PhantomPinned which is now explicitly !UnsafeUnpin, this won't actually cause any issues?

@rust-log-analyzer

This comment has been minimized.

@Sky9x
Copy link
Contributor Author

Sky9x commented Feb 13, 2025

In response to #125735 (comment):

Does this mean !UnsafePinned implies !Freeze? What semantic effect would that have?

@Sky9x

This comment was marked as resolved.

@@ -70,15 +70,15 @@ impl NewPermission {
access: None,
protector: None,
}
} else if pointee.is_unpin(*cx.tcx, cx.typing_env()) {
} else if pointee.is_unsafe_unpin(*cx.tcx, cx.typing_env()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the right check. This needs to check whether the type contains an UnsafeUnpin, not whether the type literally is UnsafeUnpin. IOW, this needs to work similar to is_freeze.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC this check is just a hack and allows too much code; I'm working on updating miri but the changes are non trivial. Am I going in the right direction by adding an UnpinSensitive variant to NewPermission and adding a visit_unpin_sensitive equivalent to visit_freeze_sensitive?

Copy link
Member

@RalfJung RalfJung Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is a hack but please preserve the hack for this PR. There's no reason to fix everything at once, that just makes for a monster PR that will be impossible to review.

So, no new NewPermission variants in this PR please.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-18 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#22 exporting to docker image format
#22 sending tarball 31.5s done
#22 DONE 34.7s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Starting the server...
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
failures:

---- [codegen] tests/codegen/function-arguments.rs stdout ----

error: verification with 'FileCheck' failed
status: exit status: 1
command: "/usr/lib/llvm-18/bin/FileCheck" "--input-file" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/function-arguments/function-arguments.ll" "/checkout/tests/codegen/function-arguments.rs" "--check-prefix=CHECK" "--allow-unused-prefixes" "--dump-input-context" "100"
--- stderr -------------------------------
/checkout/tests/codegen/function-arguments.rs:254:11: error: CHECK: expected string not found in input
/checkout/tests/codegen/function-arguments.rs:254:11: error: CHECK: expected string not found in input
// CHECK: @trait_box(ptr noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
          ^
/checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/function-arguments/function-arguments.ll:519:106: note: scanning from here
define void @trait_raw(ptr noundef %_1.0, ptr noalias noundef readonly align 8 dereferenceable(32) %_1.1) unnamed_addr #1 {
/checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/function-arguments/function-arguments.ll:525:1: note: possible intended match here
/checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/function-arguments/function-arguments.ll:525:1: note: possible intended match here
define void @trait_box(ptr noundef nonnull align 1 %0, ptr noalias noundef readonly align 8 dereferenceable(32) %1) unnamed_addr #1 {

Input file: /checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/function-arguments/function-arguments.ll
Check file: /checkout/tests/codegen/function-arguments.rs


-dump-input=help explains the following input dump.
Input was:
<<<<<<
             .
             .
             .
             .
           419: } 
           420:  
           421: ; Function Attrs: nonlazybind uwtable 
           422: define void @raw_option_nonnull_struct(ptr noundef %_1) unnamed_addr #1 { 
           424:  ret void 
           425: } 
           426:  
           426:  
           427: ; Function Attrs: nonlazybind uwtable 
           428: define noundef nonnull align 4 ptr @_box(ptr noalias noundef nonnull align 4 %x) unnamed_addr #1 { 
           430:  ret ptr %x 
           431: } 
           432:  
           432:  
           433: ; Function Attrs: nonlazybind uwtable 
           434: define void @_box_custom(ptr noundef nonnull align 4 %x.0, ptr noalias noundef nonnull readonly align 1 %x.1) unnamed_addr #1 { 
           436:  %_2 = alloca [16 x i8], align 8 
           436:  %_2 = alloca [16 x i8], align 8 
           437:  call void @llvm.lifetime.start.p0(i64 16, ptr %_2) 
           438:  store ptr %x.0, ptr %_2, align 8 
           439:  %0 = getelementptr inbounds i8, ptr %_2, i64 8 
           440:  store ptr %x.1, ptr %0, align 8 
           441: ; call core::ptr::drop_in_place<alloc::boxed::Box<i32,&alloc::alloc::Global>> 
           442:  call void @"_ZN4core3ptr76drop_in_place$LT$alloc..boxed..Box$LT$i32$C$$RF$alloc..alloc..Global$GT$$GT$17h4b2cc69c08b520dfE"(ptr noalias noundef align 8 dereferenceable(16) %_2) 
           443:  call void @llvm.lifetime.end.p0(i64 16, ptr %_2) 
           444:  ret void 
           445: } 
           446:  
           447: ; Function Attrs: nonlazybind uwtable 
           448: define noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x) unnamed_addr #1 { 
           450:  ret ptr %x 
           451: } 
           452:  
           452:  
           453: ; Function Attrs: nonlazybind uwtable 
           454: define void @struct_return(ptr dead_on_unwind noalias nocapture noundef writable sret([32 x i8]) align 4 dereferenceable(32) %_0) unnamed_addr #1 { 
           456:  %_1 = alloca [32 x i8], align 4 
           456:  %_1 = alloca [32 x i8], align 4 
           457:  call void @llvm.lifetime.start.p0(i64 32, ptr %_1) 
           458:  call void @llvm.memset.p0.i64(ptr align 4 %_1, i8 0, i64 32, i1 false) 
           459:  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %_0, ptr align 4 %_1, i64 32, i1 false) 
           460:  call void @llvm.lifetime.end.p0(i64 32, ptr %_1) 
           461:  ret void 
           462: } 
           463:  
           464: ; Function Attrs: nonlazybind uwtable 
           465: define void @helper(i64 noundef %_1) unnamed_addr #1 { 
           467:  ret void 
           468: } 
           469:  
           469:  
           470: ; Function Attrs: nonlazybind uwtable 
           471: define void @slice(ptr noalias noundef nonnull readonly align 1 %_1.0, i64 noundef %_1.1) unnamed_addr #1 { 
           473:  ret void 
           474: } 
           475:  
           475:  
           476: ; Function Attrs: nonlazybind uwtable 
           477: define void @mutable_slice(ptr noalias noundef nonnull align 1 %_1.0, i64 noundef %_1.1) unnamed_addr #1 { 
           479:  ret void 
           480: } 
           481:  
           481:  
           482: ; Function Attrs: nonlazybind uwtable 
           483: define void @unsafe_slice(ptr noundef nonnull align 2 %_1.0, i64 noundef %_1.1) unnamed_addr #1 { 
           485:  ret void 
           486: } 
           487:  
           487:  
           488: ; Function Attrs: nonlazybind uwtable 
           489: define void @raw_slice(ptr noundef %_1.0, i64 noundef %_1.1) unnamed_addr #1 { 
           491:  ret void 
           492: } 
           493:  
           493:  
           494: ; Function Attrs: nonlazybind uwtable 
           495: define void @str(ptr noalias noundef nonnull readonly align 1 %_1.0, i64 noundef %_1.1) unnamed_addr #1 { 
           497:  ret void 
           498: } 
           499:  
           499:  
           500: ; Function Attrs: nonlazybind uwtable 
           501: define void @trait_borrow(ptr noundef nonnull align 1 %_1.0, ptr noalias noundef readonly align 8 dereferenceable(32) %_1.1) unnamed_addr #1 { 
           503:  ret void 
           504: } 
           505:  
           505:  
           506: ; Function Attrs: nonlazybind uwtable 
           507: define void @option_trait_borrow(ptr noundef align 1 %x.0, ptr %x.1) unnamed_addr #1 { 
           509:  ret void 
           510: } 
           511:  
           511:  
           512: ; Function Attrs: nonlazybind uwtable 
           513: define void @option_trait_borrow_mut(ptr noundef align 1 %x.0, ptr %x.1) unnamed_addr #1 { 
           515:  ret void 
           516: } 
           517:  
           517:  
           518: ; Function Attrs: nonlazybind uwtable 
           519: define void @trait_raw(ptr noundef %_1.0, ptr noalias noundef readonly align 8 dereferenceable(32) %_1.1) unnamed_addr #1 { 
check:254'0                                                                                                              X~~~~~~~~~~~~~~~~~~ error: no match found
check:254'0     ~~~~~~~
           521:  ret void 
check:254'0     ~~~~~~~~~~
           522: } 
           522: } 
check:254'0     ~~
           523:  
check:254'0     ~
           524: ; Function Attrs: nonlazybind uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           525: define void @trait_box(ptr noundef nonnull align 1 %0, ptr noalias noundef readonly align 8 dereferenceable(32) %1) unnamed_addr #1 { 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'1     ?                                                                                                                                      possible intended match
check:254'0     ~~~~~~~
           527:  %_1 = alloca [16 x i8], align 8 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           528:  store ptr %0, ptr %_1, align 8 
           528:  store ptr %0, ptr %_1, align 8 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           529:  %2 = getelementptr inbounds i8, ptr %_1, i64 8 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           530:  store ptr %1, ptr %2, align 8 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           531: ; call core::ptr::drop_in_place<alloc::boxed::Box<dyn core::ops::drop::Drop+core::marker::Unpin>> 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           532:  call void @"_ZN4core3ptr99drop_in_place$LT$alloc..boxed..Box$LT$dyn$u20$core..ops..drop..Drop$u2b$core..marker..Unpin$GT$$GT$17h89ccce1c156455b1E"(ptr noalias noundef align 8 dereferenceable(16) %_1) 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           533:  ret void 
check:254'0     ~~~~~~~~~~
           534: } 
check:254'0     ~~
check:254'0     ~
check:254'0     ~
           536: ; Function Attrs: nonlazybind uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           537: define { ptr, ptr } @trait_option(ptr noundef align 1 %x.0, ptr %x.1) unnamed_addr #1 { 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~~~~~~~
check:254'0     ~~~~~~~
           539:  %0 = insertvalue { ptr, ptr } poison, ptr %x.0, 0 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           540:  %1 = insertvalue { ptr, ptr } %0, ptr %x.1, 1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           541:  ret { ptr, ptr } %1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~
           542: } 
check:254'0     ~~
check:254'0     ~
check:254'0     ~
           544: ; Function Attrs: nonlazybind uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           545: define { ptr, i64 } @return_slice(ptr noalias noundef nonnull readonly align 2 %x.0, i64 noundef %x.1) unnamed_addr #1 { 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~~~~~~~
check:254'0     ~~~~~~~
           547:  %0 = insertvalue { ptr, i64 } poison, ptr %x.0, 0 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           548:  %1 = insertvalue { ptr, i64 } %0, i64 %x.1, 1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           549:  ret { ptr, i64 } %1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~
           550: } 
check:254'0     ~~
check:254'0     ~
check:254'0     ~
           552: ; Function Attrs: nonlazybind uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           553: define { i16, i16 } @enum_id_1(i16 noundef %x.0, i16 %x.1) unnamed_addr #1 { 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~~~~~~~
check:254'0     ~~~~~~~
           555:  %0 = insertvalue { i16, i16 } poison, i16 %x.0, 0 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           556:  %1 = insertvalue { i16, i16 } %0, i16 %x.1, 1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           557:  ret { i16, i16 } %1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~
           558: } 
check:254'0     ~~
check:254'0     ~
check:254'0     ~
           560: ; Function Attrs: nonlazybind uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           561: define { i1, i8 } @enum_id_2(i1 noundef zeroext %x.0, i8 %x.1) unnamed_addr #1 { 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~~~~~~~
check:254'0     ~~~~~~~
           563:  %0 = insertvalue { i1, i8 } poison, i1 %x.0, 0 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           564:  %1 = insertvalue { i1, i8 } %0, i8 %x.1, 1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           565:  ret { i1, i8 } %1 
check:254'0     ~~~~~~~~~~~~~~~~~~~
           566: } 
check:254'0     ~~
check:254'0     ~
check:254'0     ~
           568: ; Function Attrs: nonlazybind uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           569: define { ptr, ptr } @dyn_star(ptr noundef %x.0, ptr noalias noundef readonly align 8 dereferenceable(24) %x.1) unnamed_addr #1 { 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~~~~~~~
check:254'0     ~~~~~~~
           571:  %0 = insertvalue { ptr, ptr } poison, ptr %x.0, 0 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           572:  %1 = insertvalue { ptr, ptr } %0, ptr %x.1, 1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           573:  ret { ptr, ptr } %1 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~
           574: } 
check:254'0     ~~
check:254'0     ~
check:254'0     ~
           576: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           577: declare void @llvm.assume(i1 noundef) #2 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           579: ; Function Attrs: nounwind nonlazybind allockind("free") uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           580: declare void @__rust_dealloc(ptr allocptr noundef, i64 noundef, i64 noundef) unnamed_addr #3 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           582: ; Function Attrs: nounwind nonlazybind uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           583: declare noundef i32 @rust_eh_personality(i32 noundef, i32 noundef, i64 noundef, ptr noundef, ptr noundef) unnamed_addr #4 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
           585: ; core::panicking::panic_in_cleanup 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           586: ; Function Attrs: cold minsize noinline noreturn nounwind nonlazybind optsize uwtable 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           587: declare void @_RNvNtCsdiibBpiQMuG_4core9panicking16panic_in_cleanup() unnamed_addr #5 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           589: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write) 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           590: declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #6 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           592: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           593: declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #7 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           595: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           596: declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #8 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           598: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           599: declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #8 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           601: attributes #0 = { inlinehint nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           602: attributes #1 = { nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           603: attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           604: attributes #3 = { nounwind nonlazybind allockind("free") uwtable "alloc-family"="__rust_alloc" "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           605: attributes #4 = { nounwind nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           606: attributes #5 = { cold minsize noinline noreturn nounwind nonlazybind optsize uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           607: attributes #6 = { nocallback nofree nounwind willreturn memory(argmem: write) } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           608: attributes #7 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           609: attributes #8 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           610: attributes #9 = { nounwind } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           611: attributes #10 = { cold } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~
           612: attributes #11 = { cold noreturn nounwind } 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           614: !llvm.module.flags = !{!0, !1} 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           615: !llvm.ident = !{!2} 
check:254'0     ~~~~~~~~~~~~~~~~~~~~
check:254'0     ~
check:254'0     ~
           617: !0 = !{i32 8, !"PIC Level", i32 2} 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           618: !1 = !{i32 2, !"RtLibUseGOT", i32 1} 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           619: !2 = !{!"rustc version 1.86.0-nightly (035206063 2025-02-14)"} 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           620: !3 = !{} 
check:254'0     ~~~~~~~~~
           621: !4 = !{i64 1, i64 -9223372036854775807} 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           622: !5 = !{i64 1} 
check:254'0     ~~~~~~~~~~~~~~
           623: !6 = !{i64 8} 
check:254'0     ~~~~~~~~~~~~~~
           624: !7 = !{i64 0, i64 -9223372036854775808} 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           625: !8 = !{i64 1, i64 0} 
check:254'0     ~~~~~~~~~~~~~~~~~~~~~
------------------------------------------



@RalfJung
Copy link
Member

RalfJung commented Feb 14, 2025

The initial PR that adds the new type should probably not remove the Unpin trait hack from codegen or Miri -- they should still look for the Unpin trait as before, and additionally recursively search for UnsafePinned. Removing Unpin risks breaking a bunch of code so we should be a bit careful about how we land this.

Comment on lines +952 to +955
/// Note that for backwards compatibility with the new [`UnsafePinned`] wrapper
/// type, placing this marker in your struct acts as if you wrapped the entire
/// struct in an `UnsafePinned`. This type will likely eventually be deprecated,
/// and all new code should be using `UnsafePinned` instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a stable guarantee we want to make, at least not yet.

@Sky9x
Copy link
Contributor Author

Sky9x commented Feb 14, 2025

Thanks for all the feedback, Ralf. I'm splitting this PR into multiple smaller ones, starting with just the libs changes in #137043.

@Sky9x Sky9x closed this Feb 14, 2025
@Sky9x Sky9x deleted the unsafe-pinned branch February 14, 2025 21:30
jhpratt added a commit to jhpratt/rust that referenced this pull request Apr 13, 2025
…ross35,RalfJung,WaffleLapkin

Initial `UnsafePinned` implementation [Part 1: Libs]

Initial libs changes necessary to unblock further work on [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html).
Tracking issue: rust-lang#125735

This PR is split off from rust-lang#136964, and includes just the libs changes:
- `UnsafePinned` struct
- private `UnsafeUnpin` structural auto trait
- Lang items for both
- Compiler changes necessary to block niches on `UnsafePinned`

This PR does not change codegen, miri, the existing `!Unpin` hack, or anything else. That work is to be split into later PRs.

---

cc `@RalfJung` `@Noratrieb`

`@rustbot` label F-unsafe_pinned T-libs-api
jhpratt added a commit to jhpratt/rust that referenced this pull request Apr 13, 2025
…ross35,RalfJung,WaffleLapkin

Initial `UnsafePinned` implementation [Part 1: Libs]

Initial libs changes necessary to unblock further work on [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html).
Tracking issue: rust-lang#125735

This PR is split off from rust-lang#136964, and includes just the libs changes:
- `UnsafePinned` struct
- private `UnsafeUnpin` structural auto trait
- Lang items for both
- Compiler changes necessary to block niches on `UnsafePinned`

This PR does not change codegen, miri, the existing `!Unpin` hack, or anything else. That work is to be split into later PRs.

---

cc ``@RalfJung`` ``@Noratrieb``

``@rustbot`` label F-unsafe_pinned T-libs-api
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Apr 14, 2025
Rollup merge of rust-lang#137043 - Sky9x:unsafe-pinned-pt1-libs, r=tgross35,RalfJung,WaffleLapkin

Initial `UnsafePinned` implementation [Part 1: Libs]

Initial libs changes necessary to unblock further work on [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html).
Tracking issue: rust-lang#125735

This PR is split off from rust-lang#136964, and includes just the libs changes:
- `UnsafePinned` struct
- private `UnsafeUnpin` structural auto trait
- Lang items for both
- Compiler changes necessary to block niches on `UnsafePinned`

This PR does not change codegen, miri, the existing `!Unpin` hack, or anything else. That work is to be split into later PRs.

---

cc ``@RalfJung`` ``@Noratrieb``

``@rustbot`` label F-unsafe_pinned T-libs-api
github-actions bot pushed a commit to model-checking/verify-rust-std that referenced this pull request Apr 19, 2025
…ross35,RalfJung,WaffleLapkin

Initial `UnsafePinned` implementation [Part 1: Libs]

Initial libs changes necessary to unblock further work on [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html).
Tracking issue: rust-lang#125735

This PR is split off from rust-lang#136964, and includes just the libs changes:
- `UnsafePinned` struct
- private `UnsafeUnpin` structural auto trait
- Lang items for both
- Compiler changes necessary to block niches on `UnsafePinned`

This PR does not change codegen, miri, the existing `!Unpin` hack, or anything else. That work is to be split into later PRs.

---

cc ``@RalfJung`` ``@Noratrieb``

``@rustbot`` label F-unsafe_pinned T-libs-api
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-unsafe_pinned `#![feature(unsafe_pinned)]` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. T-opsem Relevant to the opsem team WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants