borrow-checker 是一个编译期的检查。在实际的程序中,在编译期看到 `*r1` 的时候,通常是很难确定其实际对象是什么的。(虽然在你的这个简单的程序中可以比较容易确定,但是这种情况在实际的程序中会是比较少见的。)所以 borrow-check 不会把 `*r1` 跟 `s` 当成同一个对象进行检查。 同时,在 r2 存在时,r1 已经不能使用了。因为使用 r1, 通常就意味着要对 `*r1` 进行 borrow 。borrow-checker 会在 r2 存在时阻止再次对 `*r1` 进行 borrow。 比如: let mut s = String::from("s"); let r1 = &mut s; { let r2 = &mut (*r1); let l = r1.len(); // ERROR r2.push('2'); r1.push('3'); // ERROR println!("{}", r2); } println!("{}", r1); 因为,此处的两个对 r1 的使用,分别需要对 `*r1` 进行 borrow / mutable borrow 。而 r2 的存在使得对 `*r1` 进行此类操作不可能。 所以,同时还是只有一个“可用的”对 s 的 mutable borrow。 let r1 = &mut s; { let r2 = &mut s; dbg!(r2); } dbg!(r1); 不会有这个效果。如果 `let r1 = &mut s` 合法,那么 `r1` 跟 `r2` 将是同时可用的。