How to specify type parameter when it's unused?

Consider the following playground

enum Shape<I>
where
    I: Iterator<Item = (f64, f64)>
{
    Path(I),
    Rect(f64, f64)
}

fn foo<I>(shape: Shape<I>) 
where
    I: Iterator<Item = (f64, f64)>
{

    match shape {
        Shape::Path(_) => {},
        Shape::Rect(_, _) => {}
    }
}

fn main() {
    // fine
    let iter = vec![(1.0, 2.0)].into_iter();
    foo(Shape::Path(iter));
    
    // error: type annotations needed
    foo(Shape::Rect(1.0, 2.0));
}

What's the idiomatic way to work around this...

I can fake it like this... but... is there a better solution?

type FakeType = Box<dyn Iterator<Item = (f64,f64)>>;
foo::<FakeType>(Shape::Rect(1.0, 2.0));

I think this should work, not tested

foo(Shape::Rect::<std::iter::Empty<_>>(1.0, 2.0));
1 Like

Indeed it does!

Is that the basic idea though... gotta sorta lie to the compiler about the type, there's no way for it to magically tell "this type isn't even used, so no need to specify it"?

The compiler does need to know the type. It's going to be generating all of the code-paths in that match, and it can't build the Path code-path if you don't specify the type.

2 Likes

I would like to add that this problem may indicate a design issue. If you have a case where you need to fake the type of the variant, then maybe the enum should be separated to structs.

Considering this particular case, I think the design around enums is correct imho (modelling different variants of shapes), but Path is a collection of points, so changing it to a slice instead of an iterator means that the only missing info is a lifetime, and then the compiler can infer it everywhere...

Food for thought!

playground

enum Shape<'a>
{
    Path(&'a [(f64, f64)]),
    Rect(f64, f64)
}

fn foo(shape: Shape) {

    match shape {
        Shape::Path(_) => {},
        Shape::Rect(_, _) => {}
    }
}

fn main() {
    foo(Shape::Path(&[(1.0, 2.0)]));
    foo(Shape::Rect(1.0, 2.0));
}

never might eventually fill the gap. Unlikely though; since (assuming you know a bit of c/c++ terminology) function declarations could be free from the type but it still used in definitions, which should ideally never impact an API bound.

1 Like