Skip to content

Problem with type inference #90252

Open
Open
@SvetlinZarev

Description

@SvetlinZarev

I tried this code:

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!()
}

I expected to see this happen:
The code should have compiled without errors

Instead, this happened:

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

Meta

I've checked with 1.45 stable, 1.56 stable, 1.57 beta , 1.58 nightly

rustc --version --verbose:

`--> rustc --version --verbose
rustc 1.56.0 (09c42c458 2021-10-18)
binary: rustc
commit-hash: 09c42c45858d5f3aedfa670698275303a3d19afa
commit-date: 2021-10-18
host: x86_64-apple-darwin
release: 1.56.0
LLVM version: 13.0.0

Additional information

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![(0, 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 comming from .enumerate():

pub fn largest_rectangle_area(heights: Vec<i32>) -> i32 {
    let mut widths = vec![(0, 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![(0, 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
            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: https://stackoverflow.com/questions/69696784/cannot-infer-type-type-annotations-needed-but-the-type-is-already-known

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceC-discussionCategory: Discussion or questions that doesn't represent real issues.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions