1

I am getting familiar with Rust generics, but I can't figure out what's going wrong.

use std::collections::BTreeMap;

fn frequency<T: Ord + Clone>(vec: &Vec<T>) -> BTreeMap<T, u32> {
    let mut movie_reviews = BTreeMap::new();
    let mut vec_ = Vec::new();
    vec.push(1);
    movie_reviews
}

I have no clue why it expected type T:

error[E0308]: mismatched types
 --> src/lib.rs:6:14
  |
6 |     vec.push(1);
  |              ^ expected type parameter, found integral variable
  |
  = note: expected type `T`
             found type `{integer}`
Peter Hall
  • 53,120
  • 14
  • 139
  • 204
Felix Ha
  • 401
  • 5
  • 11
  • 1
    Can you provide your reasoning that led you to think that you could push a number into a vector of `T`? This `T` is universal in the context of this function, it could be anything that obeys the given constraints. – E_net4 Nov 14 '18 at 16:13
  • 3
    Side note, [&Vec as a function parameter is discouraged](https://stackoverflow.com/q/40006219/1233251), you can do `&[T]` instead. – E_net4 Nov 14 '18 at 16:14

2 Answers2

5

I have no clue why it expected type T

It's expecting a value of type T because you are trying to push a value into a Vec<T>.

The problem is that the only information you have given the compiler about T is that it is Ord + Clone - but neither of those traits say that 1 is a value of T. There is a trait called One in the num crate, which provides this:

extern crate num; // 0.2.0

use num::One;
use std::collections::BTreeMap;

fn frequency<T>(vec: &mut Vec<T>) -> BTreeMap<T, u32> 
where
    T: Ord + Clone + One,
{
    let mut movie_reviews = BTreeMap::new();
    vec.push(T::one());
    movie_reviews
}

As others have commented, your code has one or two other issues, which I won't address here since this will fix the error that you have asked about.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
2

In you code, you have two similarly names variables vec from the function definition that is an immutable reference to a Vec<T> (with T: Ord+Clone) and vec_ with is a Vec<_> (I've put an _ here to show that you let the compiler infer the type)

You cannot push 1 in vec: first you only have an immuable reference to it and push would need a mutable one, second vec is is a Vec of T which in that case can be pretty much everything that implements Ord and Clone and the compiler can't ensure you can push an integer in it.

You can however push 1 in vec_ and the compiler will infer the type of it to be a Vec of integers

Fredszaq
  • 3,091
  • 1
  • 18
  • 20