Closed
Description
I tried the following code. It requires a binary crate and a library crate.
main.rs
fn main() {
let mut struct_c = lib::StructC::new();
let struct_a = lib::StructA { a: 1, b: 2, c: 3 };
lib::run(&mut struct_c, struct_a);
}
main's Cargo.toml
[package]
name = "compilerbug"
version = "0.1.0"
edition = "2024"
[dependencies]
lib = { path = "./lib" }
[profile.dev]
opt-level = 1
incremental = false
lib.rs
#[derive(Clone, Copy)]
pub struct StructA {
pub a: i32,
pub b: i32,
pub c: i32,
}
pub trait TraitA {}
pub struct StructB {}
impl StructB {
pub fn new() -> Self {
Self {}
}
}
impl TraitA for StructB {}
pub trait TraitB {
fn get_trait_a(&self, struct_a: StructA) -> Option<Box<dyn TraitA>> {
Some(Box::new(StructB::new()))
}
}
pub struct StructC {}
impl StructC {
pub fn new() -> Self {
Self {}
}
}
impl TraitB for StructC {
fn get_trait_a(&self, mut struct_a: StructA) -> Option<Box<dyn TraitA>> {
struct_a.a = i32::MAX;
Some(Box::new(StructB::new()))
}
}
#[inline(never)]
fn print_struct_a(struct_a: StructA) {
println!("{}", struct_a.a);
}
#[inline(never)]
pub fn run(trait_b: &mut dyn TraitB, struct_a: StructA) {
print_struct_a(struct_a);
trait_b.get_trait_a(struct_a);
print_struct_a(struct_a);
// Uncommenting the following will fix the code.
// println!("{}", struct_a.a);
}
lib's Cargo.toml
[package]
name = "lib"
version = "0.1.0"
edition = "2024"
Since struct_a
conforms to Copy
, passing struct_a
to get_trait_a()
should make a copy. Instead, when modifying struct_a
inside of get_trait_a()
, it modifies the original. When printing the struct a second time, the struct has been modified. To repro the bug, it requires opt-level >= 1
and incremental = false
.
I expected the output in my command line to be:
1
1
Instead, this happened:
1
2147483647
Meta
rustc --version --verbose
:
rustc 1.85.0 (4d91de4e4 2025-02-17)
binary: rustc
commit-hash: 4d91de4e48198da2e33413efdcd9cd2cc0c46688
commit-date: 2025-02-17
host: aarch64-apple-darwin
release: 1.85.0
LLVM version: 19.1.7
Metadata
Metadata
Assignees
Labels
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Category: This is a bug.Issue: Correct Rust code lowers to incorrect machine codeIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessCritical priorityRelevant to the compiler team, which will review and decide on the PR/issue.Performance or correctness regression from one stable version to another.