Skip to content

Small tweaks in ToOwned::clone_into - #70201

Merged
bors merged 3 commits into
rust-lang:masterfrom
cuviper:clone_into
Apr 7, 2020
Merged

Small tweaks in ToOwned::clone_into#70201
bors merged 3 commits into
rust-lang:masterfrom
cuviper:clone_into

Conversation

@cuviper

Copy link
Copy Markdown
Member
  • <[T]>::clone_into is slightly more optimized.
  • CStr::clone_into is new, letting it reuse its allocation.
  • OsStr::clone_into now forwards to the underlying slice/Vec.

@rust-highfive

Copy link
Copy Markdown
Contributor

r? @dtolnay

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfiverust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 20, 2020
@cuviper

Copy link
Copy Markdown
MemberAuthor

To justify the slice optimization, here's output from compiler explorer. They are nearly the same, but note the smaller prologue and epilogue in the new split_at version, apparently indicating less register pressure if nothing else.

example::clone_into_orig:pushr15pushr14pushr12pushrbxpushraxmovr14,rdxmovr12,rsimovr15,rdimovrbx, qword ptr [rdx+16]cmprbx,rsijb .LBB1_2mov qword ptr [r14+16],r12movrbx,r12.LBB1_2:testrbx,rbxje .LBB1_4movrdi, qword ptr [r14]leardx,[4*rbx]movrsi,r15call qword ptr [rip+ memcpy@GOTPCREL].LBB1_4:learsi,[r15+4*rbx]subr12,rbxmovrdi,r14movrdx,r12addrsp,8poprbxpopr12popr14popr15jmp alloc::vec::Vec<T>::extend_from_sliceexample::clone_into_split:pushr15pushr14pushrbxmovr14,rdxmovrbx,rsimovrsi,rdimovrdx, qword ptr [rdx+16]cmprdx,rbxjb .LBB2_2mov qword ptr [r14+16],rbxmovrdx,rbx.LBB2_2:lear15,[rsi+4*rdx]subrbx,rdxtestrdx,rdxje .LBB2_4movrdi, qword ptr [r14]shlrdx,2call qword ptr [rip+ memcpy@GOTPCREL].LBB2_4:movrdi,r14movrsi,r15movrdx,rbxpoprbxpopr14popr15jmp alloc::vec::Vec<T>::extend_from_slice

@Centril

Copy link
Copy Markdown
Contributor

@bors try @rust-timer queue

@rust-timer

Copy link
Copy Markdown
Collaborator

Awaiting bors try build completion

@bors

bors commented Mar 20, 2020

Copy link
Copy Markdown
Collaborator

⌛ Trying commit 28791f6 with merge c462c8500772945a0f68a265dc1f8decf6b42e99...

@bors

bors commented Mar 21, 2020

Copy link
Copy Markdown
Collaborator

☀️ Try build successful - checks-azure
Build commit: c462c8500772945a0f68a265dc1f8decf6b42e99 (c462c8500772945a0f68a265dc1f8decf6b42e99)

@rust-timer

Copy link
Copy Markdown
Collaborator

Queued c462c8500772945a0f68a265dc1f8decf6b42e99 with parent 1057dc9, future comparison URL.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking try commit c462c8500772945a0f68a265dc1f8decf6b42e99, comparison URL.

@cuviper

Copy link
Copy Markdown
MemberAuthor

Seems neutral to compiler performance. I think clone_into and clone_from are not used very often.

@dtolnaydtolnay left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice!

@dtolnay

Copy link
Copy Markdown
Member

@bors r+

@bors

bors commented Mar 21, 2020

Copy link
Copy Markdown
Collaborator

📌 Commit 28791f6 has been approved by dtolnay

@borsbors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 21, 2020
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Mar 21, 2020
Small tweaks in ToOwned::clone_into
- `<[T]>::clone_into` is slightly more optimized.
- `CStr::clone_into` is new, letting it reuse its allocation.
- `OsStr::clone_into` now forwards to the underlying slice/`Vec`.
@Dylan-DPC-zz

Copy link
Copy Markdown

Failed in rollup #70237 (comment)

@bors r-

@borsbors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Mar 21, 2020
@dtolnay

Copy link
Copy Markdown
Member

The new test in c_str.rs fails on Windows x86_64-msvc-1:

---- ffi::c_str::tests::test_c_str_clone_into stdout ----thread '<unnamed>' panicked at 'assertion failed: `(left == right)` left: `0x210c5e05800`, right: `0x210c5e05830`', src\libstd\ffi\c_str.rs:1527:9note: run with `RUST_BACKTRACE=1` environment variable to display a backtracefailures: ffi::c_str::tests::test_c_str_clone_intotest result: FAILED. 743 passed; 1 failed; 2 ignored; 0 measured; 0 filtered out

@cuviper

Copy link
Copy Markdown
MemberAuthor

Hmm, maybe that test is assuming too much about the allocator. I could try it with equal lengths, but I'll confirm on Windows before I resubmit.

@dtolnay

Copy link
Copy Markdown
Member

It could just be there is #[cfg(windows)] codepath that is missing a clone_into function.

@joelpalmerjoelpalmer added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 6, 2020
It appears to codegen slightly more efficiently with `split_at` taking
two slices at once, rather than slicing across different calls.
It can try to keep its allocation by converting the inner `Box` to
`Vec`, using `clone_into` on the bytes, then convert back to `Box`.
@cuviper

Copy link
Copy Markdown
MemberAuthor

OK, I was able to confirm that failure on Windows, and now it passes when the strings are equal length.

@dtolnay

Copy link
Copy Markdown
Member

@bors r+

@bors

bors commented Apr 7, 2020

Copy link
Copy Markdown
Collaborator

📌 Commit f854070 has been approved by dtolnay

@borsbors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 7, 2020
Centril added a commit to Centril/rust that referenced this pull request Apr 7, 2020
Small tweaks in ToOwned::clone_into
- `<[T]>::clone_into` is slightly more optimized.
- `CStr::clone_into` is new, letting it reuse its allocation.
- `OsStr::clone_into` now forwards to the underlying slice/`Vec`.
@CentrilCentril mentioned this pull request Apr 7, 2020
@bors

bors commented Apr 7, 2020

Copy link
Copy Markdown
Collaborator

⌛ Testing commit f854070 with merge 83177ff73c809ab897cbc450cf19aee95d48f94a...

@Dylan-DPC-zz

Copy link
Copy Markdown

@bors retry (yield)

bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 7, 2020
…ievink
Rollup of 5 pull requests
Successful merges:
- rust-lang#70201 (Small tweaks in ToOwned::clone_into)
- rust-lang#70762 (Miri leak check: memory reachable through globals is not leaked)
- rust-lang#70846 (Keep codegen units unmerged when building compiler builtins)
- rust-lang#70854 (Use assoc int submodules)
- rust-lang#70857 (Don't import integer and float modules, use assoc consts 2)
Failed merges:
r? @ghost
@bors

bors commented Apr 7, 2020

Copy link
Copy Markdown
Collaborator

⌛ Testing commit f854070 with merge 42abbd8...

@bors
bors merged commit 795bc2c into rust-lang:masterApr 7, 2020
@cuviper
cuviper deleted the clone_into branch May 30, 2020 21:55
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 5, 2026
…-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang#155707rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
jhpratt added a commit to jhpratt/rust that referenced this pull request Jul 6, 2026
…-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang#155707rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Jul 8, 2026
…-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang#155707rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 8, 2026
…-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang#155707rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 8, 2026
…-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang#155707rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 8, 2026
…-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang#155707rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
jhpratt added a commit to jhpratt/rust that referenced this pull request Jul 9, 2026
…-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang#155707rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
jhpratt added a commit to jhpratt/rust that referenced this pull request Jul 9, 2026
…-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang#155707rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
rust-timer added a commit that referenced this pull request Jul 9, 2026
Rollup merge of #158807 - Vastargazing:tests/cstr-clone-into-alloc-error, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in #155707#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. #155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
pullBot pushed a commit to xtqqczze/rust-lang-miri that referenced this pull request Jul 10, 2026
…ror, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang/rust#155707rust-lang/rust#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang/rust#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
github-actionsBot pushed a commit to rust-lang/stdarch that referenced this pull request Jul 16, 2026
…ror, r=RalfJung
Add regression test for CString::clone_into unwind safety
Regression test for the panic-safety fix in rust-lang/rust#155707rust-lang/rust#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang/rust#155707 fixed this but didn't add a test.
The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job.
This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@cuviper@rust-highfive@Centril@rust-timer@bors@dtolnay@Dylan-DPC-zz@joelpalmer