Mutable & Immutable Reference passing as a `self` parameter

struct AttendanceInfo<'a, T, A> {
    pub primary: &'a A,
    pub reasons: &'a [T]

impl<'a, T, A> Iterator for AttendanceInfo<'a, T, A> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        let (ele, rest) = self.reasons.split_first()?;
        self.reasons = rest;

fn main() {
    let primary_reason = String::from("This's the main reason");
    let collections = vec![String::from("123"), String::from("555")];

    let mut attendance_info = AttendanceInfo {
        reasons: &collections,
        primary: &primary_reason

    let attendance_info_ref = &mut attendance_info;
    let iter= attendance_info_ref.enumerate();

    println!("{:#?}", attendance_info);

I found out that the enumerate function takes self as a parameter. When I tried to pass an immutable reference, it failed immediately and resulted in the error error[E0507]: cannot move out of *attendance_info_ref which is behind a shared reference . However, it still works in the case of a mutable reference, as shown above. This is really confusing for me. Can anyone explain this behavior to me?

1 Like

that self refers to a type implements Iterator. in the standard library, there's a blanket implementation impl Iterator for &mut I where I: Iterator. so in your case, enumerate consumed the attendance_info_ref when it's type is &mut AttendanceInfo, because mut reference type &mut AttendanceInfo itself implements Iterator.

on the other hand, a immutable reference type is not a Iterator so the compiler first tries auto deref coercion, and found out that the deref-ed type AttendanceInfo does however implements Iterator, then it tries to use the deref target as the Self type of enumerate(), resulting an "cannot move out of shared reference" error.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.