-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Open
Labels
A-trait-systemArea: Trait systemArea: Trait systemC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language teamT-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.
Description
I'm not sure if this is a bug or not.
trait ToI32 {
type I32: Default + std::ops::AddAssign;
}
impl<T> ToI32 for T {
type I32 = i32;
}
fn make<U: Default>(msg: &str) -> U {
println!("{msg}");
U::default()
}
fn foo<T: ToI32>() {
*&mut make::<<T as ToI32>::I32>("left") += make::<<T as ToI32>::I32>("right");
}
fn bar<T>() {
*&mut make::<<T as ToI32>::I32>("left") += make::<<T as ToI32>::I32>("right");
}
fn main() {
foo::<()>();
bar::<()>();
}
I expected foo
and bar
to behave the same way. Instead, I got the following output:
left
right
right
left
It is documented in the reference that the evaluation order of compound assignment expressions depends on whether the types involved are primitives or not. That is, for primitives, the right operand is evaluated first, but for other types, the left operand is evaluated first.
It seems that adding a ToI32
trait bound causes the compiler to no longer see that the type involved is i32
, causing the evaluation order to change.
Meta
Reproducible on the playground with version 1.91.0-nightly (2025-09-10 565a9ca63e9df4b223fe)
hanna-kruppe
Metadata
Metadata
Assignees
Labels
A-trait-systemArea: Trait systemArea: Trait systemC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language teamT-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.