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 fails even though all types are known #58517

Open
SeeSpring opened this issue Feb 16, 2019 · 12 comments
Open

Type inference fails even though all types are known #58517

SeeSpring opened this issue Feb 16, 2019 · 12 comments
Assignees
Labels
A-inference Area: Type inference C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@SeeSpring
Copy link
Contributor

SeeSpring commented Feb 16, 2019

The following code fails to compile, even though all types are known
https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=8de9e57e8de5cd8f2896f422d693f453

pub fn f(s: &str) {
    let mut it = s.split(|c: char| c == ',').fuse();
    let t = it.next().unwrap().parse::<usize>().unwrap();
}
   Compiling playground v0.0.1 (/playground)
error[E0282]: type annotations needed
 --> src/main.rs:3:13
  |
3 |     let t = it.next().unwrap().parse::<usize>().unwrap();
  |             ^^^^^^^^^^^^^^^^^^ cannot infer type for `T`
  |
  = note: type must be known at this point

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.
@talchas
Copy link

talchas commented Feb 16, 2019

Bisecting releases says it worked in 1.12.0, broke in 1.13.0

@jonas-schievink jonas-schievink added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-inference Area: Type inference C-bug Category: This is a bug. I-nominated regression-from-stable-to-stable Performance or correctness regression from one stable version to another. labels Feb 16, 2019
@jonas-schievink
Copy link
Contributor

Technically a stable regression, so marking as such - even though nobody seems to have been hit by it. It does pretty clearly look like a bug though.

@ExpHP
Copy link
Contributor

ExpHP commented Feb 19, 2019

Ran cargo-bisect-rustc on the nightlies:

3c5a0fa...e9bc1ba

This is still a pretty broad range...

@jonas-schievink
Copy link
Contributor

Only thing in that range that touches the typesystem seems to be #35883

@Mark-Simulacrum
Copy link
Member

May also be related to #35656

@jonas-schievink
Copy link
Contributor

Ah, I missed that one. That might be more likely, yeah (since specialization might now be involved, but before wasn't).

@pnkfelix
Copy link
Member

triage, P-medium. (Not a soundness issue, and appears to have a straight-forward if annoying work-around of introducing a local with an explicit type.) Leaving nominated label for discussion at next T-compiler meeting.

@pnkfelix pnkfelix added the P-medium Medium priority label Feb 28, 2019
@pnkfelix
Copy link
Member

Discussed briefuly at T-compiler meeting. assigning to self in attempt to ensure this doesn't just get lost. (I don't want to leave it nominated for discussion again at next week's meeting.)

@pnkfelix
Copy link
Member

I would like to double-check the running hypothesis that this was caused by the addition of FusedIterator in PR #35656 .

I briefly attempted to make a standalone test case that does not rely on core::str nor core::iter by transcribing the relevant traits and structure definitions, but the pieces here are pretty gnarly.

  • (Basically the choices for further minimization, as I see them, are either a bottom-up approach of trying to implement a minimal set of traits/structs from scratch that exhibit the same issue here, or a top-down approach of transcribing the relevant traits/structs from the core crate, and then ripping out as much as possible.)

Anyway, while investigating the behavior of the test itself, here are some potentially interesting observations:

  • Original bug report still reproduces: play
  • Removing the fuse() call yields a variant that compiles successfully: play
  • Replacing the closure argument passed to split with a char argument also yields a variant that compiles successfully: play
    • I would be curious to know why this is.
    • It might be due to some detail of how the two relevant impls in core::str::pattern are defined
    • Or it might have something to do with the level of distance between a concrete closure type vs the FnMut(char) -> bool in the impl declaration impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool

@estebank
Copy link
Contributor

The output from #65951 might shed some light:

error[E0282]: type annotations needed
 --> file12.rs:3:23
  |
3 |     let t = it.next().unwrap().parse::<usize>().unwrap();
  |             --------- ^^^^^^ cannot infer type for `T`
  |             |
  |             this method call resolves to `std::option::Option<<Self as std::iter::Iterator>::Item>`
  |
  = note: type must be known at this point

bors added a commit that referenced this issue Dec 11, 2019
Point at method call when type annotations are needed

- Point at method call instead of whole expression when type annotations are needed.
- Suggest use of turbofish on function and methods.

Fix #49391, fix #46333, fix #48089. CC #58517, #63502, #63082.

r? @nikomatsakis
bors added a commit that referenced this issue Dec 13, 2019
Point at method call when type annotations are needed

- Point at method call instead of whole expression when type annotations are needed.
- Suggest use of turbofish on function and methods.

Fix #49391, fix #46333, fix #48089. CC #58517, #63502, #63082.

Fixes #40015

r? @nikomatsakis
@SeeSpring
Copy link
Contributor Author

Seems to be due to specialization
Minimized version below
Playground

#![no_implicit_prelude]
#![feature(specialization)]

extern crate core;
extern crate std;

use core::marker::Sized;
use core::ops::FnMut;
use core::option::Option;
use std::panic;
use std::unimplemented;

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    fn fuse(self) -> Fuse<Self>
    where
        Self: Sized,
    {
        unimplemented!()
    }
}

trait FusedIterator: Iterator {}
pub struct Fuse<I>(I);
impl<I> Iterator for Fuse<I>
where
    I: Iterator,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        unimplemented!()
    }
}

impl<I> Iterator for Fuse<I> where I: FusedIterator {}

impl<'a, I> FusedIterator for Fuse<I> where I: Iterator {}

pub fn f(s: &Mystr) {
    let mut it = s.split(|c: char| c == ',').fuse();
    let t = it.next();
    let u = t.unwrap();
    let v = u.parse::<usize>().unwrap();
}

pub struct Mystr;

impl Mystr {
    pub fn split<'a, P>(&'a self, pat: P) -> Split<'a, P>
    where
        P: Pattern<'a>,
    {
        Split(pat.into_searcher(self))
    }
}

pub trait Pattern<'a> {
    type Searcher: Searcher<'a>;

    fn into_searcher(self, haystack: &'a Mystr) -> Self::Searcher;
}

impl<'a, F> Pattern<'a> for F
where
    F: FnMut(char) -> bool,
{
    type Searcher = CharPredicateSearcher<'a, F>;

    fn into_searcher(self, haystack: &'a Mystr) -> Self::Searcher {
        unimplemented!()
    }
}

pub struct CharPredicateSearcher<'a, F>(F, core::marker::PhantomData<&'a ()>)
where
    F: FnMut(char) -> bool;

unsafe impl<'a, F> Searcher<'a> for CharPredicateSearcher<'a, F> where F: FnMut(char) -> bool {}

pub unsafe trait Searcher<'a> {}

pub struct Split<'a, P>(<P as Pattern<'a>>::Searcher)
where
    P: Pattern<'a>;

impl<'a, P> Iterator for Split<'a, P>
where
    P: Pattern<'a>,
{
    type Item = &'a str;
    fn next(&mut self) -> Option<Self::Item> {
        unimplemented!()
    }
}

impl<'a, P> FusedIterator for Split<'a, P> where P: Pattern<'a> {}

fn main() {}

@Spoonbender
Copy link

Triage: original issue seems resolved, as the example provided in the original post now compiles. The latest example still won't compile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inference Area: Type inference C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants