Mismatched types mutable and immutable


#1

Hello,

I cannot understand why I lost the mutability of both variables input and directions.

Please advise

#[derive(PartialEq, PartialOrd, Debug, Copy, Clone)]
enum Mobility {
    #[warn(dead_code)]
    Left,
    #[warn(dead_code)]
    Right,
    #[warn(dead_code)]
    NotMobile
}

use Mobility::*;

fn create_directions( input : & Vec<i32> ) -> Vec<Mobility> {
    // all input elements are mobile leftward
    let mut directions: Vec<Mobility> = input.iter().map( |_| Mobility::Left).collect();
    // the first one is not mobile
    directions[0] = Mobility::NotMobile;

    directions
}

pub fn permute( input : Vec<i32> ) -> Vec<Vec<i32>> {
    let mut res = Vec::new();

    let mut input = input;
    input.sort();

    let mut directions = create_directions( &input );

    // push 1, -2, -3
    print_permutation( &input, &directions );
    res.push( input.clone() );

    // ////////////////////////////////////////////////////////

    let largest = find_largest_mobile_element(&input, &directions);

    println!("\tinput      {:?}", input);
    println!("\tdirections {:?}", directions);
    println!("\tlargest    {:?} {}", largest.0, largest.1);
    let direction = largest.0;
    let mobile_position = largest.1;

    assert_eq!(Left, direction);
    assert_eq!(2, mobile_position);
    input.swap(mobile_position - 1, mobile_position);
    directions.swap(mobile_position - 1, mobile_position);
    // 1, -3, -2
    print_permutation(&input, &directions);
    res.push(input.clone());

    reset_directions_after_left_swap(&input, &directions, mobile_position);
    // ////////////////////////////////////////////////////////

    let largest = find_largest_mobile_element(&input, &directions);
    println!( "\tinput      {:?}", input );
    println!( "\tdirections {:?}", directions );
    println!( "\tlargest    {:?} {}", largest.0, largest.1 );
    let direction = largest.0;
    let mobile_position = largest.1;

    assert_eq!( Left, direction );
    assert_eq!( 1, mobile_position);
    input.swap( mobile_position - 1, mobile_position );
    directions.swap( mobile_position - 1, mobile_position );
    // 3, 1, -2
    print_permutation( &input, &directions );
    res.push( input.clone() );

    reset_directions_after_left_swap( &input, &directions, mobile_position );

    res
}

fn reset_directions_after_left_swap( input : & Vec<i32>, directions: & mut Vec<Mobility>, mobile_position: usize ) {
    let position_after_swap = mobile_position - 1;
    let is_first_element = position_after_swap == 0;


    if is_first_element ||
        // if next element in the same direction is larger than the choosen one
        input.get( position_after_swap -1 ) > input.get(position_after_swap ) {

        if let Some(element) = directions.get_mut( position_after_swap) {
            *element = Mobility::NotMobile;
        }

        /*let mut element_direction = directions.get(position_after_swap).unwrap();
        element_direction = &Mobility::NotMobile;*/
    }


}

fn find_largest_mobile_element( input: &Vec<i32>, directions : &Vec<Mobility> ) -> (Mobility, usize) {

    if input.len() == 0 {
        return (Mobility::NotMobile, 0);
    }

    let mut mobile_position : usize = 0;
    let mut max_value = input.get(mobile_position ).unwrap();
    let mut max_direction : Mobility = directions.get(mobile_position ).unwrap().clone();

    for index in 1..input.len() {
        let is_mobile = directions.get(index).unwrap() != &Mobility::NotMobile;
        let current_value = input.get(index).unwrap();
        /*
        println!("----------------------------------------");
        println!("   is mobile   {}", is_mobile);
        println!("   current val {}", current_value);
        println!("   max         {}", max_value);
        println!("   index       {}", index);
        */

        if is_mobile && current_value > max_value {
            max_value = current_value;
            mobile_position = index;
            max_direction = directions.get(index).unwrap().clone();
            println!( "\tmax found val={}, pos={}, dir={:?}", current_value, mobile_position, max_direction);
        }
    }

    let max_direction = max_direction.clone();

    (max_direction, mobile_position )
}

fn print_permutation( input : &Vec<i32>, directions : &Vec<Mobility>) {
    assert_eq!(input.len(), directions.len());
    let mut str = String::new();

    for index in 0..input.len() {

        let data : i32 = *input.get( index ).unwrap();
        let data = data.to_string();

        match directions.get(index).unwrap() {
            &NotMobile => str.push_str( &data),
            &Left => {
                str.push_str( "-");
                str.push_str( &data)
            },
            &Right => {
                str.push_str( "+");
                str.push_str( &data)
            },
        }

        str.push_str( ", ")
    }

    println!( "permutation {}", str );

}

Error messages

error[E0308]: mismatched types
  --> src\lib.rs:53:46
   |
53 |     reset_directions_after_left_swap(&input, &directions, mobile_position);
   |                                              ^^^^^^^^^^^ types differ in mutability
   |
   = note: expected type `&mut std::vec::Vec<Mobility>`
              found type `&std::vec::Vec<Mobility>`

error[E0308]: mismatched types
  --> src\lib.rs:71:47
   |
71 |     reset_directions_after_left_swap( &input, &directions, mobile_position );
   |                                               ^^^^^^^^^^^ types differ in mutability
   |
   = note: expected type `&mut std::vec::Vec<Mobility>`
              found type `&std::vec::Vec<Mobility>`

error: aborting due to 2 previous errors

Thank you


#2

You just need &mut directions there, not &directions


#3

Perfect ! Thank you ! I need to get used to this new language.:rofl:


#4

No problem.

Keep in mind that if you have a mut value, it means you as the owner have the option to mutate it. But, you can lend it out immutably or mutably, and that aspect is independent of the other. That’s why you still need to write &mut to borrow it mutably.