|
10 | 10 |
|
11 | 11 | use rustc::hir;
|
12 | 12 | use rustc::hir::Node;
|
13 |
| -use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Mir}; |
14 |
| -use rustc::mir::{Mutability, Place, Projection, ProjectionElem, Static}; |
15 |
| -use rustc::ty::{self, TyCtxt}; |
| 13 | +use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir}; |
| 14 | +use rustc::mir::{Mutability, Operand, Place, Projection, ProjectionElem, Static, Terminator}; |
| 15 | +use rustc::mir::TerminatorKind; |
| 16 | +use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt}; |
16 | 17 | use rustc_data_structures::indexed_vec::Idx;
|
17 | 18 | use syntax_pos::Span;
|
18 | 19 |
|
| 20 | +use dataflow::move_paths::InitLocation; |
19 | 21 | use borrow_check::MirBorrowckCtxt;
|
20 | 22 | use util::borrowck_errors::{BorrowckErrors, Origin};
|
21 | 23 | use util::collect_writes::FindAssignments;
|
22 | 24 | use util::suggest_ref_mut;
|
23 | 25 |
|
24 |
| -#[derive(Copy, Clone, Debug)] |
| 26 | +#[derive(Copy, Clone, Debug, Eq, PartialEq)] |
25 | 27 | pub(super) enum AccessKind {
|
26 | 28 | MutableBorrow,
|
27 | 29 | Mutate,
|
@@ -393,6 +395,63 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
393 | 395 | );
|
394 | 396 | }
|
395 | 397 |
|
| 398 | + Place::Projection(box Projection { |
| 399 | + base: Place::Local(local), |
| 400 | + elem: ProjectionElem::Deref, |
| 401 | + }) if error_access == AccessKind::MutableBorrow => { |
| 402 | + err.span_label(span, format!("cannot {ACT}", ACT = act)); |
| 403 | + |
| 404 | + let mpi = self.move_data.rev_lookup.find_local(*local); |
| 405 | + for i in self.move_data.init_path_map[mpi].iter() { |
| 406 | + if let InitLocation::Statement(location) = self.move_data.inits[*i].location { |
| 407 | + if let Some( |
| 408 | + Terminator { |
| 409 | + kind: TerminatorKind::Call { |
| 410 | + func: Operand::Constant(box Constant { |
| 411 | + literal: Const { |
| 412 | + ty: &TyS { |
| 413 | + sty: TyKind::FnDef(id, substs), |
| 414 | + .. |
| 415 | + }, |
| 416 | + .. |
| 417 | + }, |
| 418 | + .. |
| 419 | + }), |
| 420 | + .. |
| 421 | + }, |
| 422 | + .. |
| 423 | + } |
| 424 | + ) = &self.mir.basic_blocks()[location.block].terminator { |
| 425 | + if self.tcx.parent(id) == self.tcx.lang_items().index_trait() { |
| 426 | + |
| 427 | + let mut found = false; |
| 428 | + self.tcx.for_each_relevant_impl( |
| 429 | + self.tcx.lang_items().index_mut_trait().unwrap(), |
| 430 | + substs.type_at(0), |
| 431 | + |_relevant_impl| { |
| 432 | + found = true; |
| 433 | + } |
| 434 | + ); |
| 435 | + |
| 436 | + let extra = if found { |
| 437 | + String::from("") |
| 438 | + } else { |
| 439 | + format!(", but it is not implemented for `{}`", |
| 440 | + substs.type_at(0)) |
| 441 | + }; |
| 442 | + |
| 443 | + err.help( |
| 444 | + &format!( |
| 445 | + "trait `IndexMut` is required to modify indexed content{}", |
| 446 | + extra, |
| 447 | + ), |
| 448 | + ); |
| 449 | + } |
| 450 | + } |
| 451 | + } |
| 452 | + } |
| 453 | + } |
| 454 | + |
396 | 455 | _ => {
|
397 | 456 | err.span_label(span, format!("cannot {ACT}", ACT = act));
|
398 | 457 | }
|
|
0 commit comments