Cannot infer type for type parameter `T` when use `range` function on the associated BTreeMap

Here is the code:

use std::collections::BTreeMap;
use std::ops::Bound::Included;

fn main() {
    let mut map = BTreeMap::new();
    map.insert("a", 0);
    map.insert("b", 1);
    map.insert("c", 2);
    for (&key, &value) in map.range((Included("a"), Included("c"))) {
      println!("{key}: {value}");
    }
}

Then I got a compiler error:

Compiling playground v0.0.1 (/playground)
error[E0283]: type annotations needed
 --> src/main.rs:9:31
  |
9 |     for (&key, &value) in map.range((Included("a"), Included("c"))) {
  |                               ^^^^^ cannot infer type of the type parameter `T` declared on the associated function `range`
  |
  = note: cannot satisfy `_: Ord`
note: required by a bound in `BTreeMap::<K, V, A>::range`
help: consider specifying the type arguments in the function call
  |
9 |     for (&key, &value) in map.range::<T, R>((Included("a"), Included("c"))) {
  |                                    ++++++++

However, when I tried to replace the key with type i32, or, fully qualified the range function's generics, the compiler did't report the error anymore, like this:

use std::collections::BTreeMap;
use std::ops::Bound::{ Included, self };

fn main() {
    // i32
    let mut map = BTreeMap::new();
    map.insert(0, 0);
    map.insert(1, 1);
    map.insert(2, 2);
    for (&key, &value) in map.range((Included(0), Included(2))) {
      println!("{key}: {value}");
    }

    // fully qualified
    let mut map = BTreeMap::new();
    map.insert("a", 0);
    map.insert("b", 1);
    map.insert("c", 2);
    for (&key, &value) in map.range::<&str, (Bound<&str>, Bound<&str>)>((Included("a"), Included("c"))) {
      println!("{key}: {value}");
    }
}

Why can't the compiler inter that T is &str?

I'm guessing it has to do with the number of Borrow impls. There are several types for which Borrow<str> is implemented, but Borrow<i32> is only implemented for i32 (via the blanket impl in std).

1 Like

These both work for example, and the compiler wasn't going to assume they were semantically equivalent.

    for (&key, &value) in map.range::< str, _>((Included("a"), Included("c"))) {
    for (&key, &value) in map.range::<&str, _>((Included("a"), Included("c"))) {
    //                                ^
2 Likes