use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind};
use transform::nll;
+use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_set::{self, IdxSetBuf};
use rustc_data_structures::indexed_vec::{Idx};
node_id: id,
move_data: &mdpe.move_data,
param_env: param_env,
+ storage_drop_or_dead_error_reported: FxHashSet(),
};
let mut state = InProgress::new(flow_borrows,
node_id: ast::NodeId,
move_data: &'cx MoveData<'tcx>,
param_env: ParamEnv<'gcx>,
+ /// This field keeps track of when storage drop or dead errors are reported
+ /// in order to stop duplicate error reporting and identify the conditions required
+ /// for a "temporary value dropped here while still borrowed" error. See #45360.
+ storage_drop_or_dead_error_reported: FxHashSet<Local>,
}
// (forced to be `pub` due to its use as an associated type below.)
}
StatementKind::StorageDead(local) => {
- self.access_lvalue(ContextKind::StorageDead.new(location),
- (&Lvalue::Local(local), span),
- (Shallow(None), Write(WriteKind::StorageDead)),
- flow_state);
+ if self.storage_drop_or_dead_error_reported.insert(local) {
+ self.access_lvalue(ContextKind::StorageDead.new(location),
+ (&Lvalue::Local(local), span),
+ (Shallow(None), Write(WriteKind::StorageDead)),
+ flow_state);
+ }
}
}
}
let erased_ty = gcx.lift(&self.tcx.erase_regions(&ty)).unwrap();
let moves_by_default = erased_ty.moves_by_default(gcx, self.param_env, DUMMY_SP);
- if moves_by_default {
- // move of lvalue: check if this is move of already borrowed path
- self.access_lvalue(context, lvalue_span, (Deep, Write(WriteKind::Move)), flow_state);
- } else {
- // copy of lvalue: check if this is "copy of frozen path" (FIXME: see check_loans.rs)
- self.access_lvalue(context, lvalue_span, (Deep, Read(ReadKind::Copy)), flow_state);
+ // Check if error has already been reported to stop duplicate reporting.
+ let has_storage_drop_or_dead_error_reported = match *lvalue {
+ Lvalue::Local(local) => self.storage_drop_or_dead_error_reported.insert(local),
+ _ => false,
+ };
+
+ if !has_storage_drop_or_dead_error_reported {
+ if moves_by_default {
+ // move of lvalue: check if this is move of already borrowed path
+ self.access_lvalue(context, lvalue_span, (Deep, Write(WriteKind::Move)),
+ flow_state);
+ } else {
+ // copy of lvalue: check if this is "copy of frozen path"
+ // (FIXME: see check_loans.rs)
+ self.access_lvalue(context, lvalue_span, (Deep, Read(ReadKind::Copy)),
+ flow_state);
+ }
}
// Finally, check if path was already moved.