Skip to content

String cloning is not optimized the same way as String construction #88905

Closed
@SadiinsoSnowfall

Description

@SadiinsoSnowfall

I don't know if it is really worth looking into, but I think I found some weird behavior in the rust compiler:
Let's consider the two following functions (godbolt link):

pub fn nop(a: &String) {
    a.as_str().to_owned();
}

pub fn complex(a: &String) {
    a.to_owned();
}

They both allocate a String struct but do not use or return it. Rustc is able to optimize away the first one, but not the second one.
If we dig deeper, we can observe that the compiler is not able to optimize away the to_owned and clone method when called on a string. Let's look at the following functions (godbolt link):

pub fn a() {
    "ok".to_owned();
}

pub fn b() {
    "ok".to_owned().clone();
}

pub fn c() {
    "ok".to_owned().as_str().to_owned();
}

pub fn d() {
    "ok".to_owned().to_owned();
}

pub fn e() {
    String::from("ok");
}

The fonctions a, c and e are optimized away even on opt-level 2. Whereas the functions b and d are not and still produce calls to alloc, dealloc, drop_in_place, etc...

Looking at the stdlib code, <&str>::to_owned internally calls <&[u8]>::to_owned, which calls <&[u8]>::to_vec, which calls <&[u8]>::to_vec_in which ends up calling hack::to_vec.

String::to_string calls String::to_owned which calls String::clone which calls Vec<u8>::clone which calls <&[u8]>::to_vec_in with the only difference from the <&str>::to_owned path being that the possibly custom allocator of the Vec internal buffer is cloned and passed to <&[u8]>::to_vec_in in Vec<u8>::clone.

Is it possible that rustc is not able to correctly inline the allocator functions when the default allocator is not directly assumed ?

This was tested on Rustc 1.55 and `Rustc 1.57.0-nightly (b69fe57 2021-09-10)

This issue has been assigned to @notriddle via this comment.

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions