Skip to content

incorrect type is inferred for a local variable holding a closure #92282

Open
@doy

Description

@doy

I tried this code:

use std::collections::HashMap;
use std::hash::Hash;

pub struct Foo<T>
where
    T: Hash + Eq + Clone + 'static,
{
    rule: Box<dyn Fn(&T) -> Option<Vec<(T, u64)>>>
}

impl<T> Foo<T>
where
    T: Hash + Eq + Clone + 'static
{
    pub fn new(rules: HashMap<T, Vec<(T, u64)>>) -> Self {
        let rule = Box::new(move |src| rules.get(src).map(|o| o.to_owned()));
        Self { rule }
    }
}

(https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=f40ec4a2d13b41aa91d6a48ee04214bf)

I expected to see this happen: this should compile, because this equivalent(?) code compiles:

use std::collections::HashMap;
use std::hash::Hash;

pub struct Foo<T>
where
    T: Hash + Eq + Clone + 'static,
{
    rule: Box<dyn Fn(&T) -> Option<Vec<(T, u64)>>>
}

impl<T> Foo<T>
where
    T: Hash + Eq + Clone + 'static
{
    pub fn new(rules: HashMap<T, Vec<(T, u64)>>) -> Self {
        Self { rule: Box::new(move |src| rules.get(src).map(|o| o.to_owned())) }
    }
}

(https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=2809e18e87c789f7591fe7ed57d13ba1)

the only difference here is the intermediate variable rule, which appears to be inferring an incorrect type for some reason. the code also compiles successfully if rule is given an explicit type annotation with the same type as defined in the struct.

Instead, this happened:

error: implementation of `FnOnce` is not general enough
  --> src/lib.rs:17:16
   |
17 |         Self { rule }
   |                ^^^^ implementation of `FnOnce` is not general enough
   |
   = note: closure with signature `fn(&'2 T) -> Option<Vec<(T, u64)>>` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`...
   = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2`

this seems maybe related to #87079 or #70263 but i can't tell if it's actually the same problem or not (this one isn't a problem with function arguments).

Meta

rustc --version --verbose:

1.59.0-nightly

(2021-12-23 c09a9529c51cde41c110)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions