Skip to content

Conversation

@ShoyuVanilla
Copy link
Member

Fixes #19021

I think that this issue was quite hard to find (I wonder how David found this out 😄 )

For instance, removing lang item annotation #[lang = "owned_box"], making the last expression of the fn main() into a plain match expression instead of a closure, or annotating the closure return type to the following code won't trigger the issue.

use core::ops::Deref;

#[lang = "owned_box"]
struct Box<T>(T);

impl<T> Deref for Box<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

struct Foo;

fn main() {
    let x = Box(Foo);
    let y = &Foo;
    || match x {
        ref x => x,
        _ => y,
    };
}

The path in which above code triggers the issue is quite interweaven, but the root cause is that we are applying resulting adjustments of the CoreceMany to the wrong expression; we are applying it always to the very expression that we are coercing from.

If the next arm/branch of the CoerceMany can coerce into the previous merge_ty, this is not a problem.
But if the previous merge_ty has to be coerced into the type of next arm/branch, the adjustments must be applied to the previous CoerceMany expressions.

So, in the above code, when calling CoerceMany::coerce with the second arm, the match expression's type is inferred as &Foo and the first branch must be coerced into it.
But adjustments for this coercion [Deref, Deref, Borrow] is applied to the next arm, y, and since y = &Foo cannot be dereferenced twice, and this causes the issue.

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 7, 2025
//^^^^^^^^^ expected *mut i32, got &'? i32
_ => t as *const i32,
// ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)
Copy link
Member Author

Choose a reason for hiding this comment

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

This test also illustrates the issue; as the x = match 1 { ... } is inferred as *const i32, the MutToconstPointer adjustment must be applied to t as *mut i32, not t as *const i32

Copy link
Member

@Veykril Veykril left a comment

Choose a reason for hiding this comment

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

Thanks!

@Veykril Veykril added this pull request to the merge queue Feb 12, 2025
Merged via the queue into rust-lang:master with commit c9838ec Feb 12, 2025
9 checks passed
@ShoyuVanilla ShoyuVanilla deleted the issue-19021 branch February 12, 2025 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Overloaded deref on type Foo is not a projection

3 participants