Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
));
- item_msg = format!("`{}`", access_place_desc.unwrap());
- if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
- reason = ", as it is not declared as mutable".to_string();
+ let imm_borrow_derefed = self.upvars[upvar_index.index()]
+ .place
+ .place
+ .deref_tys()
+ .any(|ty| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not)));
+
+ // If the place is immutable then:
+ //
+ // - Either we deref a immutable ref to get to our final place.
+ // - We don't capture derefs of raw ptrs
+ // - Or the final place is immut because the root variable of the capture
+ // isn't marked mut and we should suggest that to the user.
+ if imm_borrow_derefed {
+ // If we deref an immutable ref then the suggestion here doesn't help.
+ return;
} else {
- let name = self.upvars[upvar_index.index()].name;
- reason = format!(", as `{}` is not declared as mutable", name);
+ item_msg = format!("`{}`", access_place_desc.unwrap());
+ if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
+ reason = ", as it is not declared as mutable".to_string();
+ } else {
+ let name = self.upvars[upvar_index.index()].name;
+ reason = format!(", as `{}` is not declared as mutable", name);
+ }
}
}
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
));
+ let captured_place = &self.upvars[upvar_index.index()].place;
+
err.span_label(span, format!("cannot {ACT}", ACT = act));
- let upvar_hir_id = self.upvars[upvar_index.index()].var_hir_id;
+ let upvar_hir_id = captured_place.get_root_variable();
+
if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_hir_id) {
if let hir::PatKind::Binding(
hir::BindingAnnotation::Unannotated,