Rust Environment Differences Between LeetCode and Desktop

I am mainly using Rust to solve LeetCode problems. On more than one occasion, I have noticed strange differences between the Rust environment on LeetCode and the one on my desktop. I hope that someone can offer some insight into the reasons for these differences, and how to bring the environments closer together.

The latest example of this problem is my solution for 986. Interval List Intersections (desktop version below, and for LeetCode I remove the declaration of Solution and the main function), that compiles and runs fine on desktop. On LeetCode however, the compiler complains about comparing references against values, among other things. Both environments report to be on version 1.58.1 of rustc. I have pasted in the error messages below.

With some modifications (less concise, uglier), the code compiles on both desktop and LeetCode, and gets AC (below).

Code that compiles on desktop but not on LeetCode:

struct Solution {}

#[derive(Clone, Copy, PartialEq)]
enum IntervalEvent {
    FirstOpen,
    FirstClose,
    SecondOpen,
    SecondClose,
}

enum IntervalState {
    Closed,
    FirstOpen,
    SecondOpen,
    Open(i32),
}

impl Solution {
    pub fn interval_intersection(
        first_list: Vec<Vec<i32>>,
        second_list: Vec<Vec<i32>>,
    ) -> Vec<Vec<i32>> {
        let mut first_it = first_list
            .into_iter()
            .flat_map(|item| {
                [
                    (item[0], IntervalEvent::FirstOpen),
                    (item[1], IntervalEvent::FirstClose),
                ]
                .into_iter()
            })
            .peekable();
        let mut second_it = second_list
            .into_iter()
            .flat_map(|item| {
                [
                    (item[0], IntervalEvent::SecondOpen),
                    (item[1], IntervalEvent::SecondClose),
                ]
                .into_iter()
            })
            .peekable();

        let mut state = IntervalState::Closed;
        let mut rez = vec![];

        loop {
            let next_event = match (first_it.peek().copied(), second_it.peek().copied()) {
                (None, None) => break,
                (None, Some((time, event))) => {
                    second_it.next();
                    (time, event)
                }
                (Some((time, event)), None) => {
                    first_it.next();
                    (time, event)
                }
                (Some((time1, event1)), Some((time2, event2))) => {
                    if time1 < time2 || (time1 == time2 && event1 == IntervalEvent::FirstOpen) {
                        first_it.next();
                        (time1, event1)
                    } else {
                        second_it.next();
                        (time2, event2)
                    }
                }
            };

            state = match (&state, next_event) {
                (IntervalState::Closed, (_, IntervalEvent::FirstOpen)) => IntervalState::FirstOpen,
                (IntervalState::Closed, (_, IntervalEvent::SecondOpen)) => {
                    IntervalState::SecondOpen
                }
                (IntervalState::FirstOpen, (t, IntervalEvent::SecondOpen))
                | (IntervalState::SecondOpen, (t, IntervalEvent::FirstOpen)) => {
                    IntervalState::Open(t)
                }
                (IntervalState::FirstOpen, (_, IntervalEvent::FirstClose))
                | (IntervalState::SecondOpen, (_, IntervalEvent::SecondClose)) => {
                    IntervalState::Closed
                }
                (IntervalState::Open(start_time), (end_time, IntervalEvent::FirstClose)) => {
                    rez.push(vec![*start_time, end_time]);
                    IntervalState::SecondOpen
                }
                (IntervalState::Open(start_time), (end_time, IntervalEvent::SecondClose)) => {
                    rez.push(vec![*start_time, end_time]);
                    IntervalState::FirstOpen
                }
                _ => state,
            }
        }

        rez
    }
}

fn main() {
    println!(
        "{:?}",
        Solution::interval_intersection(
            vec![vec![0, 2], vec![5, 10], vec![13, 23], vec![24, 25]],
            vec![vec![1, 5], vec![8, 12], vec![15, 24], vec![25, 26]]
        )
    );
}

Output on LeetCode:

Line 57, Char 67: can't compare `&IntervalEvent` with `IntervalEvent` (solution.rs)
   |
57 |                     if time1 < time2 || (time1 == time2 && event1 == IntervalEvent::FirstOpen) {
   |                                                                   ^^ no implementation for `&IntervalEvent == IntervalEvent`
   |
   = help: the trait `PartialEq<IntervalEvent>` is not implemented for `&IntervalEvent`
Line 74, Char 41: mismatched types (solution.rs)
   |
74 |                     IntervalState::Open(t)
   |                                         ^ expected `i32`, found `&i32`
   |
help: consider dereferencing the borrow
   |
74 |                     IntervalState::Open(*t)
   |                                         +
Line 81, Char 48: mismatched types (solution.rs)
   |
81 |                     rez.push(vec![*start_time, end_time]);
   |                                                ^^^^^^^^ expected `i32`, found `&i32`
   |
help: consider dereferencing the borrow
   |
81 |                     rez.push(vec![*start_time, *end_time]);
   |                                                +
Line 85, Char 48: mismatched types (solution.rs)
   |
85 |                     rez.push(vec![*start_time, end_time]);
   |                                                ^^^^^^^^ expected `i32`, found `&i32`
   |
help: consider dereferencing the borrow
   |
85 |                     rez.push(vec![*start_time, *end_time]);
   |                                                +
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `prog` due to 4 previous errors
mv: cannot stat '/leetcode/rust_compile/target/release/prog': No such file or directory

Revised version that gets AC:

struct Solution {}

#[derive(Clone, Copy, PartialEq)]
enum IntervalEvent {
    FirstOpen,
    FirstClose,
    SecondOpen,
    SecondClose,
}

enum IntervalState {
    Closed,
    FirstOpen,
    SecondOpen,
    Open(i32),
}

impl Solution {
    pub fn interval_intersection(
        first_list: Vec<Vec<i32>>,
        second_list: Vec<Vec<i32>>,
    ) -> Vec<Vec<i32>> {
        let mut first_it = first_list
            .into_iter()
            .flat_map(|item| {
                vec![
                    (item[0], IntervalEvent::FirstOpen),
                    (item[1], IntervalEvent::FirstClose),
                ]
                .into_iter()
            })
            .peekable();
        let mut second_it = second_list
            .into_iter()
            .flat_map(|item| {
                vec![
                    (item[0], IntervalEvent::SecondOpen),
                    (item[1], IntervalEvent::SecondClose),
                ]
                .into_iter()
            })
            .peekable();

        let mut state = IntervalState::Closed;
        let mut rez = vec![];

        loop {
            let next_event = match (first_it.peek(), second_it.peek()) {
                (None, None) => break,
                (None, Some((time, event))) => {
                    let rv = (*time, *event);
                    second_it.next();
                    rv
                }
                (Some((time, event)), None) => {
                    let rv = (*time, *event);
                    first_it.next();
                    rv
                }
                (Some((time1, event1)), Some((time2, event2))) => {
                    if time1 < time2 || (time1 == time2 && *event1 == IntervalEvent::FirstOpen) {
                        let rv = (*time1, *event1);
                        first_it.next();
                        rv
                    } else {
                        let rv = (*time2, *event2);
                        second_it.next();
                        rv
                    }
                }
            };

            state = match (&state, next_event) {
                (IntervalState::Closed, (_, IntervalEvent::FirstOpen)) => IntervalState::FirstOpen,
                (IntervalState::Closed, (_, IntervalEvent::SecondOpen)) => {
                    IntervalState::SecondOpen
                }
                (IntervalState::FirstOpen, (t, IntervalEvent::SecondOpen))
                | (IntervalState::SecondOpen, (t, IntervalEvent::FirstOpen)) => {
                    IntervalState::Open(t)
                }
                (IntervalState::FirstOpen, (_, IntervalEvent::FirstClose))
                | (IntervalState::SecondOpen, (_, IntervalEvent::SecondClose)) => {
                    IntervalState::Closed
                }
                (IntervalState::Open(start_time), (end_time, IntervalEvent::FirstClose)) => {
                    rez.push(vec![*start_time, end_time]);
                    IntervalState::SecondOpen
                }
                (IntervalState::Open(start_time), (end_time, IntervalEvent::SecondClose)) => {
                    rez.push(vec![*start_time, end_time]);
                    IntervalState::FirstOpen
                }
                _ => state,
            }
        }

        rez
    }
}

fn main() {
    println!(
        "{:?}",
        Solution::interval_intersection(
            vec![vec![0, 2], vec![5, 10], vec![13, 23], vec![24, 25]],
            vec![vec![1, 5], vec![8, 12], vec![15, 24], vec![25, 26]]
        )
    );
}
Comments (1)