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

Assigning to variable causes type inference to fail #114873

Open
joshlf opened this issue Aug 16, 2023 · 4 comments
Open

Assigning to variable causes type inference to fail #114873

joshlf opened this issue Aug 16, 2023 · 4 comments
Labels
A-inference Area: Type inference

Comments

@joshlf
Copy link
Contributor

joshlf commented Aug 16, 2023

Prompted by @SkiFire13's suggestion in google/zerocopy#196 (comment).

I have the following code (minimized from the code linked above, so names will seem weird out of context; that doesn't have any bearing on the example):

use core::mem::MaybeUninit;

pub trait Projectable<F> {
    type Inner;
}

impl<T, F> Projectable<F> for MaybeUninit<T> {
    type Inner = T;
}

pub fn project<P, F, InnerToField>(
    _outer: &P,
    _inner_to_field: InnerToField,
)
where
    P: Projectable<F>,
    InnerToField: Fn(*const P::Inner) -> *const F,
{}

macro_rules! project {
    (&$c:ident $($f:tt)*) => {{
        unsafe {
            project(
                $c,
                |inner| ::core::ptr::addr_of!((*inner) $($f)*),
            )
        }
    }};
}

pub fn project_maybe_uninit_tuple(m: &MaybeUninit<(u8, u16)>) {
    project!(&m.1)
}

This compiles fine. However, if I move the |inner| ... closure to first be assigned to a variable:

macro_rules! project {
    (&$c:ident $($f:tt)*) => {{
        let inner_to_field = |inner| ::core::ptr::addr_of!((*inner) $($f)*);
        unsafe {
            project(
                $c,
                inner_to_field,
            )
        }
    }};
}

...it results in a type inference failure:

error[[E0282]](https://doc.rust-lang.org/stable/error_codes/E0282.html): type annotations needed
  --> src/lib.rs:22:60
   |
22 |         let inner_to_field = |inner| ::core::ptr::addr_of!((*inner) $($f)*);
   |                                                            ^^^^^^^^ cannot infer type
...
34 |     project!(&m.1)
   |     -------------- in this macro invocation
   |
   = note: this error originates in the macro `project` (in Nightly builds, run with -Z macro-backtrace for more info)

This is surprising to me, as the type constraints haven't changed at all. I'd assume that, if type inference had enough information to succeed with the first version of the code, it'd have enough information to succeed with the second version of the code.

Reporting this in case it's an inference bug.

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Aug 16, 2023
@compiler-errors
Copy link
Member

This is essentially expected. Closure signature inference relies on the fact that it's an argument to project to provide sufficient information about the signature to then be able to type-check the body of the closure.

@joshlf
Copy link
Contributor Author

joshlf commented Aug 16, 2023

Wouldn't using the variable as an argument in the same place provide the same type information?

@compiler-errors
Copy link
Member

No, because the closure is type-checked before checking the function call that uses it.

@joshlf
Copy link
Contributor Author

joshlf commented Aug 16, 2023

I see. I assume that that the type information provided when the closure is used in argument position is just a special case to help out that use case?

@compiler-errors compiler-errors added A-inference Area: Type inference and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inference Area: Type inference
Projects
None yet
Development

No branches or pull requests

3 participants