Skip to content

Type inference failure after switching to unboxed closure #19499

Closed
@japaric

Description

@japaric

STR

#![feature(unboxed_closures)]

trait IteratorExt2<A> {
    fn inspect2<F>(self, f: F) -> Inspect<A, Self, F> where F: FnMut(&A);
}

struct Inspect<A, I, F> where I: Iterator<A>, F: FnMut(&A) {
    iter: I,
    f: F,
}

fn main() {
    let xs = [1u, 2, 3, 4];
    // Trigger
    let mut n = 0;  // Err
    //let mut n = 0u;  // Ok

    let ys = xs.iter()
               .map(|&x| x)
               .inspect2(|_| n += 1)
                //~^ error: unable to infer enough type information about `closure`; type annotations required
               //.inspect2(|&mut: _| n += 1)  // This doesn't work either (same error as above)
               .collect::<Vec<uint>>();

    // NOTE: This constrains `n` to be `uint`
    assert_eq!(n, xs.len());
    assert_eq!(xs[], ys[]);
}

impl<A, I> IteratorExt2<A> for I where I: Iterator<A> {
    fn inspect2<F>(self, f: F) -> Inspect<A, I, F> where F: FnMut(&A) {
        Inspect {
            iter: self,
            f: f,
        }
    }
}

impl<A, I, F> Inspect<A, I, F> where I: Iterator<A>, F: FnMut(&A) {
    #[inline]
    fn do_inspect(&mut self, elt: Option<A>) -> Option<A> {
        match elt {
            Some(ref a) => (self.f)(a),
            None => ()
        }

        elt
    }
}

impl<A, I, F> Iterator<A> for Inspect<A, I, F> where I: Iterator<A>, F: FnMut(&A) {
    fn next(&mut self) -> Option<A> {
        let next = self.iter.next();
        self.do_inspect(next)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

Version

#19449 on top of 21ba1d5

The code under main is actually a test (see test_inspect in libcoretest/iter.rs) that was passing with the boxed version of Inspect, but after moving Inspect to unboxed closures (as seen above) compiling that test now errors due to a type inference failure.

To fix the compilation n had to be type annotated: let mut n = 0u, however this shouldn't be necessary because assert_eq!(n, xs.len()) should already force n to be uint.

TL;DR This should compile because it has enough type information, but for some reason it doesn't.

cc @nikomatsakis

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-type-systemArea: Type system

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions