I have the following function:
pub fn largest_rectangle_area(heights: Vec<i32>) -> i32 {
let mut widths = vec![(0usize, heights.len()); heights.len()];
let mut stack = vec![];
for (idx, &x) in heights.iter().enumerate() {
while let Some(&pos) = stack.last() {
if x >= heights[pos] {
break;
}
widths[pos].1 = idx;
stack.pop();
}
stack.push(idx);
}
todo!()
}
Which fails to compile:
error[E0282]: type annotations needed
--> src/lib.rs:11:13
|
11 | widths[pos].1 = idx;
| ^^^^^^^^^^^ cannot infer type
|
= note: type must be known at this point
But if I change widths[pos].1 = idx
to widths[pos] = (0, idx)
the code compiles fine:
pub fn largest_rectangle_area(heights: Vec<i32>) -> i32 {
let mut widths = vec![(0usize, heights.len()); heights.len()];
let mut stack = vec![];
for (idx, &x) in heights.iter().enumerate() {
while let Some(&pos) = stack.last() {
if x >= heights[pos] {
break;
}
widths[pos] = (0, idx); // now it compiles fine
stack.pop();
}
stack.push(idx);
}
todo!()
}
It also compiles fine if I add type annotations for the stack
variable, which should be Vec<usize>
as its content is coming from .enumerate()
:
pub fn largest_rectangle_area(heights: Vec<i32>) -> i32 {
let mut widths = vec![(0usize, heights.len()); heights.len()];
let mut stack: Vec<usize> = vec![];
for (idx, &x) in heights.iter().enumerate() {
while let Some(&pos) = stack.last() {
if x >= heights[pos] {
break;
}
widths[pos].1 = idx; // now it compiles fine
stack.pop();
}
stack.push(idx);
}
todo!()
}
It also compiles fine if I add type annotations for widths
like that, but fails with the same error without that type annotation.
pub fn largest_rectangle_area(heights: Vec<i32>) -> i32 {
let mut widths = vec![(0usize, heights.len()); heights.len()];
let mut stack = vec![];
for (idx, &x) in heights.iter().enumerate() {
while let Some(&pos) = stack.last() {
if x >= heights[pos] {
break;
}
let at_pos: &mut (usize, usize) = &mut widths[pos]; // type annotations added here, although the vec is explicitly initialized with `(usize, usize)`
at_pos.1 = idx;
stack.pop();
}
stack.push(idx);
}
todo!()
}
So at the end I'm not sure If it fails to infer the type of pos
or the type of widths
A user at StackOverflow managed to create the following smaller reproducible example:
fn some_fn() {
let mut widths = vec![(0usize, 0usize); 100];
let mut stack = vec![];
//let mut stack:Vec<usize> = vec![]; //why explicit type definition is needed
let a = stack.pop().unwrap();
let idx = 0usize;
widths[a].1 = idx;
stack.push(idx);
}
Here is the SO question for reference: rust - "Cannot infer type - type annotations needed", but the type is already known - Stack Overflow
Do you have any idea what the issue might be ? Is this a known limitation or a bug in the compiler (I've also opened Problem with type inference · Issue #90252 · rust-lang/rust · GitHub)?