Skip to content

Assigning to variable causes type inference to fail #114873

@joshlf

Description

@joshlf

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions