Skip to content
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

fix: Apply adjustments to proper expr when invoking CoerceMany #19111

Merged
merged 1 commit into from
Feb 12, 2025

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
2 => t as &i32,
//^^^^^^^^^ 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