error[E0502]: cannot borrow `char_array` as mutable because it is also borrowed as immutable


#1
use std::io;

    fn main() 
    {
    	let mut main_string = String::new();

    	println!("Please enter the string : ");
    	io::stdin().read_line(&mut main_string)
    			   .expect("Failed to read the input value");

    	main_string  = main_string.trim().to_string();
    	println!("The trimmed string is : {}",main_string );

    	let repeating_character = recurring_string_parser(main_string);

    	println!("The character which is first repeating is {}",repeating_character );

        
    }

    fn recurring_string_parser(main_string: String)->char
    {
    	let mut char_array  = Vec::new();
    	for  each_char in main_string.chars()
    	{
    		let mut some_val = char_array.iter().find(|&&c| c == each_char);
    		
    		match some_val {
    			Some(ch) => return each_char,
    			_ => println!("do nothing"),
    		}
    		char_array.push(each_char);
    		println!(" The charcater is {:?}",some_val);
    	}

    	return 'a';
    }

I am a beginner in Rust, so I am writing a small program to identify the first recurring character in a string. I am getting the following error is above code:

error[E0502]: cannot borrow `char_array` as mutable because it is also borrowed as immutable
  --> src/main.rs:32:3
   |
26 | 		let mut some_val = char_array.iter().find(|&&c| c == each_char);
   | 		                   ---------- immutable borrow occurs here
...
32 | 		char_array.push(each_char);
   | 		^^^^^^^^^^ mutable borrow occurs here
33 | 		println!(" The charcater is {:?}",some_val);
34 | 	}
   | 	- immutable borrow ends here

Sorry for the shabby output snippet.

Can anyone please help as to what is it that I am doing wrong? It would be of great help if someone could explain it as well because I am finding it difficult to grasp the concept of mutablity borrowing.


#2

find returns a reference to the found element rather than the element itself. It’s like "the result is the 5th element in char_array".

Because of the reference Rust doesn’t allow you to modify char_array, because you could accidentally make the reference invalid. Even adding new elements may require rewriting entire vector, making some_val point to previous no longer valid data of the vec.

The solution here is to create a copy of the character found: char_array.iter().find(|&&c| c == each_char).cloned(). Or alternatively char_array.iter().cloned().find(…). Characters are cheaper to clone than to reference, so the performance is same or better, and Rust won’t be worrying about preserving validity of a reference you don’t really need here.


#3

Thank you very much, your solution worked. But the char_array.iter().find(|&&c| c == each_char).clone() did not work, it gave the same error. The .cloned() worked. If you don’t mind explain could you explain, why is this the case . Also, are there any resources which teaches about the basic concepts of Rust language, other than the official Rust Lang book.


#4

find returns an Option<&char> here and cloning that just gives you another Option<&char> because that clones the Option itself. Replace clone with cloned which returns an Option<char> - in general, Option<&T>::cloned() gives you an Option<T> so long as T implements Clone.


#5

Thank you for the explanation.Now I am starting to understand the references in Rust.