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

Type inference problem with lifetimes and assoiated types #28046

Open
malbarbo opened this Issue Aug 27, 2015 · 6 comments

Comments

Projects
None yet
6 participants
@malbarbo
Copy link
Contributor

malbarbo commented Aug 27, 2015

I am trying to get some lifetime polymorphism but I unable to do so because of some bugs (#24424, #23958). This time it seems that the type inference is not working.

use std::ops::Range;

pub trait Iter {
    type Type: Iterator;
}

pub trait T {
    fn f<'a>(&'a self) -> <&'a Self as Iter>::Type where &'a Self: Iter;
}

pub struct S;

impl<'a> Iter for &'a S {
    type Type = Range<usize>;
} 

impl T for S {
    fn f<'a>(&'a self) -> <&'a Self as Iter>::Type where &'a Self: Iter {
        0usize..10
    }
}

fn main() {}

gives

<anon>:19:9: 19:19 error: mismatched types:
 expected `<&'a S as Iter>::Type`,
    found `core::ops::Range<usize>`
(expected associated type,
    found struct `core::ops::Range`) [E0308]
<anon>:19         0usize..10
                  ^~~~~~~~~~
<anon>:19:9: 19:19 help: see the detailed explanation for E0308
error: aborting due to previous error
playpen: application terminated with error code 101
@eefriedman

This comment has been minimized.

Copy link
Contributor

eefriedman commented Aug 27, 2015

Slightly simplified testcase:

use std::ops::Range;

pub trait Iter {
    type Type: Iterator;
}

pub struct S;

impl<'a> Iter for &'a S {
    type Type = Range<usize>;
} 

impl S {
    fn f<'a>(&'a self) -> Range<usize> where &'a S: Iter {
        let x: <&'static S as Iter>::Type = 0usize..10;
        x
    }
}

fn main() {}

Basically, the compiler is getting confused by the where clause: it sees the bound on the implementation, and "resolves" the associated type based on that, rather than actually trying to look up the type. The problem is that the bound is trivial: depending on it actually reduces the amount of information available, rather than increasing it.

Related to #27987, I think; CC @arielb1.

@arielb1

This comment has been minimized.

Copy link
Contributor

arielb1 commented Aug 27, 2015

This is one of the tentacles of #21974 - the only relation to #27987 is that we would have ignored the poisonous where-clause if its lifetime was 'static. The issue can be fixed by just not specifying the where-clause:

use std::ops::Range;

pub trait Iter {
    type Type: Iterator;
}

pub trait T {
    fn f<'a>(&'a self) -> <&'a Self as Iter>::Type where &'a Self: Iter;
}

pub struct S;

impl<'a> Iter for &'a S {
    type Type = Range<usize>;
} 

impl T for S {
    fn f<'a>(&'a self) -> <&'a Self as Iter>::Type
            // need some (holding) bound on 'a to make it early-bound
            where &'a (): Sized {
        0usize..10
    }
}

fn main() {}
@eefriedman

This comment has been minimized.

Copy link
Contributor

eefriedman commented Aug 27, 2015

Is there an existing bug report about the where &'a (): Sized thing?

@arielb1

This comment has been minimized.

Copy link
Contributor

arielb1 commented Aug 29, 2015

@eefriedman

It's not a bug, just a less-than-optimally-documented feature (early-bound vs. late-bound regions). See my comment at enum Region and the links referenced therein. Its the same reason you can't write

fn foo<'a>(){}
fn main() {
    foo::<'static>() //~ ERROR too many lifetime parameters provided
}
@eefriedman

This comment has been minimized.

Copy link
Contributor

eefriedman commented Aug 29, 2015

Ah, right... we need to decide somehow whether the lifetime is part of the function type.

@brson

This comment has been minimized.

Copy link
Contributor

brson commented Mar 9, 2017

Current error:



rustc 1.15.1 (021bd294c 2017-02-08)
error[E0308]: mismatched types
  --> <anon>:19:9
   |
19 |         0usize..10
   |         ----------
   |         |
   |         expected associated type, found struct `std::ops::Range`
   |         in this macro invocation
   |
   = note: expected type `<&'a S as Iter>::Type`
   = note:    found type `std::ops::Range<usize>`

error: aborting due to previous error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.