]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
Suggest that values are dropped in the opposite order they are defined
[rust.git] / src / librustc_mir / borrow_check / nll / explain_borrow / mod.rs
index 2807a4e8857e0b91421dbf09506b2598f16fb48a..d43bc239806ce102d78690d8e9a439cb669c8e58 100644 (file)
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
-use borrow_check::{Context, MirBorrowckCtxt};
+use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
 use borrow_check::borrow_set::BorrowData;
 use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Mir};
+use rustc::mir::{Local, Location, Mir, Place};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagnosticBuilder;
 use util::liveness::{self, DefUse, LivenessMode};
@@ -22,11 +22,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// point from `context`. This is key for the "3-point errors"
     /// [described in the NLL RFC][d].
     ///
+    /// # Parameters
+    ///
+    /// - `borrow`: the borrow in question
+    /// - `context`: where the borrow occurs
+    /// - `kind_place`: if Some, this describes the statement that triggered the error.
+    ///   - first half is the kind of write, if any, being performed
+    ///   - second half is the place being accessed
+    /// - `err`: where the error annotations are going to be added
+    ///
     /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
     pub(in borrow_check) fn explain_why_borrow_contains_point(
         &mut self,
         context: Context,
         borrow: &BorrowData<'tcx>,
+        kind_place: Option<(WriteKind, &Place<'tcx>)>,
         err: &mut DiagnosticBuilder<'_>,
     ) {
         let regioncx = &&self.nonlexical_regioncx;
@@ -64,6 +74,17 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
                                         local_name
                                     ),
                                 );
+
+                                if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
+                                    if let Place::Local(borrowed_local) = place {
+                                        let dropped_local_scope = mir.local_decls[local].visibility_scope;
+                                        let borrowed_local_scope = mir.local_decls[*borrowed_local].visibility_scope;
+
+                                        if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
+                                            err.note("values in a scope are dropped in the opposite order they are defined");
+                                        }
+                                    }
+                                }
                             }
                             None => {
                                 err.span_label(