Skip to content

Fails to optimize away trivial ownership move of Vec in high optimization levels #140057

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

Open
ZhonghaoPan-nju opened this issue Apr 20, 2025 · 1 comment
Labels
C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.

Comments

@ZhonghaoPan-nju
Copy link

I tried these codes:
https://godbolt.org/z/3je47cr9a

#![allow(dead_code)]
#![allow(non_camel_case_types)]

struct trie_node {
    content: Vec<String>,
    children: Vec<trie_node>,
}

#[no_mangle]
fn print_str_vector(vector: Vec<String>) {
    for string in &vector {
        println!("{}", *string);
    }
}

pub fn main() {
    let mut node: trie_node = trie_node {
        content: Vec::new(),
        children: Vec::new(),
    };
    let v = vec!["123".to_string(), "abc".to_string()];
    node.content = vec!["123".to_string(), "abc".to_string()];
    print_str_vector(v);
    print_str_vector(node.content.clone());
}

and:

#![allow(dead_code)]
#![allow(non_camel_case_types)]
struct trie_node {
    content: Vec<String>,
    children: Vec<trie_node>,
}

#[no_mangle]
fn print_str_vector(vector: Vec<String>) {
    for string in &vector {
        println!("{}", *string);
    }
}
pub fn main() {
    let mut node: trie_node = trie_node {
        content: Vec::new(),
        children: Vec::new(),
    };
    let v = vec!["123".to_string(), "abc".to_string()];
    node.content = vec!["123".to_string(), "abc".to_string()];
    print_str_vector(v);
    let temp_bridge_1080 = node.content;
    print_str_vector(temp_bridge_1080.clone());
}

I expected to see this happen:
Both expressions should produce identical assembly code.

Instead, this happened:
The second version of the code generated approximately 200 more lines of assembly compared to the first version.

The additional assembly appears to stem from the line: let temp_bridge_1080 = node.content;
Since this is a simple move operation (zero-cost abstraction in Rust), it should not introduce any runtime overhead or code bloat. This suggests a potential missed optimization opportunity in the compiler.

Could you please review them? Thank you!

Meta

rustc 1.85.0-nightly (d117b7f21 2024-12-31)
binary: rustc
commit-hash: d117b7f211835282b3b177dc64245fff0327c04c
commit-date: 2024-12-31
host: x86_64-unknown-linux-gnu
release: 1.85.0-nightly
LLVM version: 19.1.6
@ZhonghaoPan-nju ZhonghaoPan-nju added the C-bug Category: This is a bug. label Apr 20, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 20, 2025
@saethlin
Copy link
Member

Something very odd is going on here. In the good example, the drop_in_place<trie_node> code is directly recursive, and in the bad example, drop_in_place<trie_node> calls drop_in_place<[trie_node]>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.
Projects
None yet
Development

No branches or pull requests

3 participants