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

Regression in type inference from Iterator.sum #25094

Closed
untitaker opened this issue May 4, 2015 · 16 comments
Closed

Regression in type inference from Iterator.sum #25094

untitaker opened this issue May 4, 2015 · 16 comments
Labels
A-typesystem Area: The type system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@untitaker
Copy link
Contributor

The following used to work (around the time where AdditiveIterator still existed):

fn main() {
    let content = vec!["a","aa","aaa","aaaa"];
    let lens = content.iter().map(|x| x.len());
    println!("{}", lens.sum());
}

http://is.gd/2jQlp7

The error message:

<anon>:4:25: 4:30 error: unable to infer enough type information about `_`; type annotations required [E0282]
<anon>:4     println!("{}", lens.sum());
                                 ^~~~~
@steveklabnik steveklabnik added the A-typesystem Area: The type system label May 7, 2015
@steveklabnik
Copy link
Member

/cc @nikomatsakis

@mitaa
Copy link
Contributor

mitaa commented Jun 8, 2015

Iterator::sum and Iterator::product use defaulted type parameters, which are, I think, not yet implemented for functions. (RFC 0213 #21939)

@mitaa
Copy link
Contributor

mitaa commented Jul 29, 2015

Testing with the shiny new Default Type Parameter Fallback:

#![feature(default_type_parameter_fallback)]
#![feature(iter_arith)]

fn main() {
    let a = [1, 2, 3, 4, 5];
    let it = a.iter();
    assert_eq!(it.sum(), 15);
}
test.rs:7:19: 7:24 error: the trait `core::ops::Add<&i32>` is not implemented for the type `<core::slice::Iter<'_, i32> as core::iter::Iterator>::Item` [E0277]
test.rs:7     assert_eq!(it.sum(), 15);

(example from the Iterator::sum documentation)

@untitaker
Copy link
Contributor Author

@mitaa It appears that your example currently fails with the same exact message as OP: https://is.gd/eA5RJ0

@Mark-Simulacrum
Copy link
Member

Nominating for compiler team discussion since this is a regression that slipped through a while back.

@Mark-Simulacrum Mark-Simulacrum added I-nominated T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 12, 2017
@Mark-Simulacrum
Copy link
Member

Copying over #36201 to close that:

fn total1(a: &[u32]) -> u32 { // OK
    a.iter().sum()
}

fn total3(a: &[u32]) -> u32 { // Error
    a.iter().sum() + 5u32
}
fn f() -> f64 { // Ok
   0.0f64 +  vec![1.0f64].into_iter().sum::<f64>()
}

fn f2() -> f64 { // Error
   0.0f64 +  vec![1.0f64].into_iter().sum()
}

@nikomatsakis
Copy link
Contributor

I believe this changed when sum() was stabilized -- it was rewritten to be generic over the sum type, which implies that it must be specified and cannot be inferred from context. Therefore, I think this is "not a bug" (nor, technically, a regression). I could be wrong though, maybe some details of our type inference changed -- if so, they seem likely to be bug fixes, though, since I think we are (correctly) refusing to guess types here.

@nikomatsakis
Copy link
Contributor

I'm inclined to close myself.

@StefanoD
Copy link

@nikomatsakis
This is a good example, that you don't have to "guess" types:

fn total3(a: &[u32]) -> u32 { // Error
    a.iter().sum() + 5u32
}

Everything is u32. So why doesn't this work?

@jimblandy
Copy link
Contributor

jimblandy commented May 25, 2017

I'm having a hard time understanding why it's inappropriate to infer usize here:

fn main() {
    let v: Vec<usize> = vec![1,2,3,4];
    assert_eq!(v.iter().sum(), 10_usize);
}

Rust says:

rustc 1.19.0-nightly (5b13bff52 2017-05-23)
error[E0282]: type annotations needed
 --> <anon>:3:25
  |
3 |     assert_eq!(v.iter().sum(), 10_usize);
  |                         ^^^ cannot infer type for `S`

error: aborting due to previous error

The passive voice in "type annotations are needed" begs the question, "by whom???"

@nikomatsakis
Copy link
Contributor

@StefanoD

Everything is u32. So why doesn't this work?

Because other things are addable to u32 besides u32. For example, there is an impl of Add<&u32> for u32 (and vice versa).

@nikomatsakis
Copy link
Contributor

@jimblandy

I'm having a hard time understanding why it's inappropriate to infer usize here:

Similarly, there are many PartialEq impls. Basically, sum results in a variable V, and we have to infer V: PartialEq<usize>. At the moment, we always refuse to guess the "self" type, so we just stop there. For other type parameters, if Self is known, we will sometimes infer them based on Self. I am not happy with these rules, but there are many things at play -- if anything, I'd like to infer less in many cases, because it leads to regressions when new impls are added. (Also, none of this is specific to sum().)

@nikomatsakis
Copy link
Contributor

Closing since this is behaving as expected, for better or worse. =)

@nikomatsakis
Copy link
Contributor

Oh, just some additional notes: the problem that @jimblandy highlighted is basically a dup of #20297 (so in some sense you could consider this issue a dup of that issue). You can see the effect of Self in that if you reverse the order of the assert_eq! arguments, things work again:

fn main() {
    let v: Vec<usize> = vec![1,2,3,4];
    assert_eq!(10_usize, v.iter().sum());
}

@tshepang
Copy link
Member

@nikomatsakis it's weird that if you swap the arguments, inference works again. Is that ok?

amacd31 added a commit to amacd31/hydromath_rs that referenced this issue Nov 28, 2017
It wasn't available when I was first working on this code, it is now, so
hooray!

Also implemented as sum::<f64> since the type inference doesn't quite
work in this context. Related discussion to this issue can be found on
github here: rust-lang/rust#25094
@dimo414
Copy link
Contributor

dimo414 commented Aug 1, 2019

Stumbled upon this bug via #36201; I appreciate (now) why "the sum type ... must be specified and cannot be inferred from context", but the error message seems like it could still be more helpful. In particular, could it suggest a likely annotation, e.g. "Did you mean .sum::<u32>()?"

FWIW in 1.36.0 the error message from the total3() example above is now:

error[E0283]: type annotations required: cannot resolve `_: std::iter::Sum<&u32>`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system 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

9 participants