about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2017-12-12 17:29:37 -0300
committerNiko Matsakis <niko@alum.mit.edu>2017-12-20 14:38:10 -0500
commit3a185a510db5e5334d56d804e50efd41fc1e220d (patch)
treeca5d453b429db922d108767912958fe46d4365c8
parent6d2987ca031e9ec63ad452c21ef302025d553c6c (diff)
downloadrust-3a185a510db5e5334d56d804e50efd41fc1e220d.tar.gz
rust-3a185a510db5e5334d56d804e50efd41fc1e220d.zip
Add three point error handling to borrowck
Closes #45988
-rw-r--r--src/librustc/mir/mod.rs9
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs14
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs210
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs1
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs18
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/test/ui/nll/capture-ref-in-struct.rs2
-rw-r--r--src/test/ui/nll/capture-ref-in-struct.stderr3
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument.stderr3
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-nested.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr3
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-ref.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr3
-rw-r--r--src/test/ui/nll/get_default.rs2
-rw-r--r--src/test/ui/nll/get_default.stderr3
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs3
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr3
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-with-fragment.rs2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr3
-rw-r--r--src/test/ui/nll/maybe-initialized-drop.rs2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop.stderr2
24 files changed, 274 insertions, 23 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index efde224c3e1..f410865a6cd 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -21,6 +21,7 @@ use rustc_data_structures::control_flow_graph::ControlFlowGraph;
 use rustc_serialize as serialize;
 use hir::def::CtorKind;
 use hir::def_id::DefId;
+use mir::visit::MirVisitable;
 use ty::subst::{Subst, Substs};
 use ty::{self, AdtDef, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
@@ -868,6 +869,14 @@ impl<'tcx> BasicBlockData<'tcx> {
             }
         }
     }
+
+    pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
+        if index < self.statements.len() {
+            &self.statements[index]
+        } else {
+            &self.terminator
+        }
+    }
 }
 
 impl<'tcx> Debug for TerminatorKind<'tcx> {
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 971b5eb2275..bc1b3edbb6a 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -14,7 +14,6 @@ use rustc::mir::{BorrowKind, Field, Local, Location, Operand};
 use rustc::mir::{Place, ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::ty::{self, RegionKind};
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_errors::DiagnosticBuilder;
 
 use std::rc::Rc;
 
@@ -134,19 +133,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         err.emit();
     }
 
-    fn explain_why_borrow_contains_point(
-        &self,
-        context: Context,
-        borrow: &BorrowData<'_>,
-        err: &mut DiagnosticBuilder<'_>,
-    ) {
-        if let Some(regioncx) = &self.nonlexical_regioncx {
-            if let Some(cause) = regioncx.why_region_contains_point(borrow.region, context.loc) {
-                cause.label_diagnostic(self.mir, err);
-            }
-        }
-    }
-
     /// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of
     /// the local assigned at `location`.
     /// This is done by searching in statements succeeding `location`
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
new file mode 100644
index 00000000000..bfb7e793eee
--- /dev/null
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -0,0 +1,210 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use borrow_check::{Context, MirBorrowckCtxt};
+use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
+use dataflow::BorrowData;
+use rustc::mir::{Local, Location, Mir};
+use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::DiagnosticBuilder;
+use util::liveness::{self, DefUse, LivenessMode};
+
+impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
+    pub(in borrow_check) fn explain_why_borrow_contains_point(
+        &self,
+        context: Context,
+        borrow: &BorrowData<'_>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if let Some(regioncx) = &self.nonlexical_regioncx {
+            if let Some(cause) = regioncx.why_region_contains_point(borrow.region, context.loc) {
+                let mir = self.mir;
+
+                cause.label_diagnostic(mir, err);
+
+                match *cause.root_cause() {
+                    Cause::LiveVar(local, location) => {
+                        match find_regular_use(&mir, regioncx, borrow, location, local) {
+                            Some(p) => {
+                                err.span_label(
+                                    mir.source_info(p).span,
+                                    format!("borrow later used here"),
+                                );
+                            }
+
+                            None => {
+                                span_bug!(
+                                    mir.source_info(context.loc).span,
+                                    "Cause should end in a LiveVar"
+                                );
+                            }
+                        }
+                    }
+
+                    Cause::DropVar(local, location) => {
+                        match find_drop_use(&mir, regioncx, borrow, location, local) {
+                            Some(p) => {
+                                let local_name = &mir.local_decls[local].name.unwrap();
+
+                                err.span_label(
+                                    mir.source_info(p).span,
+                                    format!(
+                                        "borrow later used here, when `{}` is dropped",
+                                        local_name
+                                    ),
+                                );
+                            }
+
+                            None => {
+                                span_bug!(
+                                    mir.source_info(context.loc).span,
+                                    "Cause should end in a DropVar"
+                                );
+                            }
+                        }
+                    }
+
+                    _ => (),
+                }
+            }
+        }
+    }
+}
+
+fn find_regular_use<'gcx, 'tcx>(
+    mir: &'gcx Mir,
+    regioncx: &'tcx RegionInferenceContext,
+    borrow: &'tcx BorrowData,
+    start_point: Location,
+    local: Local,
+) -> Option<Location> {
+    let mut uf = UseFinder {
+        mir,
+        regioncx,
+        borrow,
+        start_point,
+        local,
+        liveness_mode: LivenessMode {
+            include_regular_use: true,
+            include_drops: false,
+        },
+    };
+
+    uf.find()
+}
+
+fn find_drop_use<'gcx, 'tcx>(
+    mir: &'gcx Mir,
+    regioncx: &'tcx RegionInferenceContext,
+    borrow: &'tcx BorrowData,
+    start_point: Location,
+    local: Local,
+) -> Option<Location> {
+    let mut uf = UseFinder {
+        mir,
+        regioncx,
+        borrow,
+        start_point,
+        local,
+        liveness_mode: LivenessMode {
+            include_regular_use: false,
+            include_drops: true,
+        },
+    };
+
+    uf.find()
+}
+
+struct UseFinder<'gcx, 'tcx> {
+    mir: &'gcx Mir<'gcx>,
+    regioncx: &'tcx RegionInferenceContext<'tcx>,
+    borrow: &'tcx BorrowData<'tcx>,
+    start_point: Location,
+    local: Local,
+    liveness_mode: LivenessMode,
+}
+
+impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
+    fn find(&mut self) -> Option<Location> {
+        let mut stack = vec![];
+        let mut visited = FxHashSet();
+
+        stack.push(self.start_point);
+        while let Some(p) = stack.pop() {
+            if !self.regioncx.region_contains_point(self.borrow.region, p) {
+                continue;
+            }
+
+            if !visited.insert(p) {
+                continue;
+            }
+
+            let block_data = &self.mir[p.block];
+            let (defined, used) = self.def_use(p, block_data.visitable(p.statement_index));
+
+            if used {
+                return Some(p);
+            } else if !defined {
+                if p.statement_index < block_data.statements.len() {
+                    stack.push(Location {
+                        statement_index: p.statement_index + 1,
+                        ..p
+                    });
+                } else {
+                    stack.extend(
+                        block_data
+                            .terminator()
+                            .successors()
+                            .iter()
+                            .map(|&basic_block| Location {
+                                statement_index: 0,
+                                block: basic_block,
+                            }),
+                    );
+                }
+            }
+        }
+
+        None
+    }
+
+    fn def_use(&self, location: Location, thing: &MirVisitable<'tcx>) -> (bool, bool) {
+        let mut visitor = DefUseVisitor {
+            defined: false,
+            used: false,
+            local: self.local,
+            liveness_mode: self.liveness_mode,
+        };
+
+        thing.apply(location, &mut visitor);
+
+        (visitor.defined, visitor.used)
+    }
+}
+
+struct DefUseVisitor {
+    defined: bool,
+    used: bool,
+    local: Local,
+    liveness_mode: LivenessMode,
+}
+
+impl<'tcx> Visitor<'tcx> for DefUseVisitor {
+    fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
+        if local == self.local {
+            match liveness::categorize(context, self.liveness_mode) {
+                Some(DefUse::Def) => self.defined = true,
+                Some(DefUse::Use) => self.used = true,
+                None => (),
+            }
+        }
+    }
+}
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 98a74f06703..f96e107efa3 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -27,6 +27,7 @@ use util::pretty::{self, ALIGN};
 use self::mir_util::PassWhere;
 
 mod constraint_generation;
+pub mod explain_borrow;
 pub(crate) mod region_infer;
 mod renumber;
 mod subtype_constraint_generation;
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 6f3e6cb1ec5..5e921cc330d 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1229,4 +1229,22 @@ impl Cause {
             }
         }
     }
+
+    pub(crate) fn root_cause(&self) -> &Cause {
+        match self {
+            Cause::LiveVar(..) |
+            Cause::DropVar(..) |
+            Cause::LiveOther(..) |
+            Cause::UniversalRegion(..) => {
+                self
+            }
+
+            Cause::Outlives {
+                original_cause,
+                ..
+            } => {
+                original_cause.root_cause()
+            }
+        }
+    }
 }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 4d26230e061..a7efdaf0826 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -23,6 +23,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(decl_macro)]
+#![feature(dyn_trait)]
 #![feature(i128_type)]
 #![feature(inclusive_range_syntax)]
 #![feature(inclusive_range)]
diff --git a/src/test/ui/nll/capture-ref-in-struct.rs b/src/test/ui/nll/capture-ref-in-struct.rs
index 5eae5d92471..6e234a966d1 100644
--- a/src/test/ui/nll/capture-ref-in-struct.rs
+++ b/src/test/ui/nll/capture-ref-in-struct.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Znll -Zborrowck=mir
+// compile-flags:-Znll -Zborrowck=mir -Znll-dump-cause
 
 // Test that a structure which tries to store a pointer to `y` into
 // `p` (indirectly) fails to compile.
diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr
index 3812ff40407..7b3f7d25dd0 100644
--- a/src/test/ui/nll/capture-ref-in-struct.stderr
+++ b/src/test/ui/nll/capture-ref-in-struct.stderr
@@ -6,6 +6,9 @@ error[E0597]: `y` does not live long enough
 ...
 37 |     }
    |      - borrowed value only lives until here
+38 | 
+39 |     deref(p);
+   |           - borrow later used here
    |
    = note: borrowed value must be valid for lifetime '_#5r...
 
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.rs b/src/test/ui/nll/closure-requirements/escape-argument.rs
index 7e918c6431d..17fadf0a297 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.rs
+++ b/src/test/ui/nll/closure-requirements/escape-argument.rs
@@ -22,7 +22,7 @@
 // basically checking that the MIR type checker correctly enforces the
 // closure signature.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Znll -Zborrowck=mir -Znll-dump-cause -Zverbose
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index 94019798600..09d5617b08e 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -31,6 +31,9 @@ error[E0597]: `y` does not live long enough
 38 |         //~^ ERROR `y` does not live long enough [E0597]
 39 |     }
    |      - borrowed value only lives until here
+40 | 
+41 |     deref(p);
+   |           - borrow later used here
    |
    = note: borrowed value must be valid for lifetime '_#6r...
 
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
index 05700ae00ad..984c9fe7c34 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
@@ -15,7 +15,7 @@
 //
 // except that the closure does so via a second closure.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Znll -Zborrowck=mir -Znll-dump-cause -Zverbose
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
index 277e5201416..430fb711c63 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -58,6 +58,9 @@ error[E0597]: `y` does not live long enough
 ...
 36 |       }
    |        - borrowed value only lives until here
+37 | 
+38 |       deref(p);
+   |             - borrow later used here
    |
    = note: borrowed value must be valid for lifetime '_#4r...
 
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
index 93d8bfafcba..499ebd65955 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
@@ -19,7 +19,7 @@
 // `'b`.  This relationship is propagated to the closure creator,
 // which reports an error.
 
-// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// compile-flags:-Znll -Zborrowck=mir -Znll-dump-cause -Zverbose
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
index 709e6bc2de1..090bacbc17d 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -35,6 +35,9 @@ error[E0597]: `y` does not live long enough
 ...
 36 |     }
    |      - borrowed value only lives until here
+37 | 
+38 |     deref(p);
+   |           - borrow later used here
    |
    = note: borrowed value must be valid for lifetime '_#4r...
 
diff --git a/src/test/ui/nll/get_default.rs b/src/test/ui/nll/get_default.rs
index e5944e75e42..7c52a0c87af 100644
--- a/src/test/ui/nll/get_default.rs
+++ b/src/test/ui/nll/get_default.rs
@@ -13,7 +13,7 @@
 // a variety of errors from the older, AST-based machinery (notably
 // borrowck), and then we get the NLL error at the end.
 
-// compile-flags:-Znll -Zborrowck=compare
+// compile-flags:-Znll -Zborrowck=compare -Znll-dump-cause
 
 struct Map {
 }
diff --git a/src/test/ui/nll/get_default.stderr b/src/test/ui/nll/get_default.stderr
index fff2684af13..ed2c305090c 100644
--- a/src/test/ui/nll/get_default.stderr
+++ b/src/test/ui/nll/get_default.stderr
@@ -42,6 +42,9 @@ error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as imm
 43 |             Some(v) => {
 44 |                 map.set(String::new()); // Both AST and MIR error here
    |                 ^^^ mutable borrow occurs here
+...
+47 |                 return v;
+   |                        - borrow later used here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs
index 0047f6d5923..184dfe320d3 100644
--- a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs
+++ b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Z nll
+//compile-flags: -Z emit-end-regions -Zborrowck=mir -Z nll -Znll-dump-cause
+
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
index 389334f9c1d..b161a068c04 100644
--- a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
+++ b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
@@ -6,6 +6,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
 ...
 31 |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
    |     ^^^^^ assignment to borrowed `x` occurs here
+32 |     // FIXME ^ Should not error in the future with implicit dtors, only manually implemented ones
+33 | }
+   |  - borrow later used here, when `foo` is dropped
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
index 3242136f005..beb2c87f8f3 100644
--- a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
+++ b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Z nll
+//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll -Znll-dump-cause
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr b/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr
index 9edeca2d188..072818c7ce1 100644
--- a/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr
+++ b/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr
@@ -6,6 +6,8 @@ error[E0506]: cannot assign to `x` because it is borrowed
 ...
 31 |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
    |     ^^^^^ assignment to borrowed `x` occurs here
+32 | }
+   |  - borrow later used here, when `foo` is dropped
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
index 3e32818b8dc..39cad8acee1 100644
--- a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
+++ b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Z nll
+//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll -Znll-dump-cause
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
index 24d0d6d04c8..89117c2bfea 100644
--- a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
+++ b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
@@ -6,6 +6,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
 ...
 32 |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
    |     ^^^^^ assignment to borrowed `x` occurs here
+33 |     // FIXME ^ This currently errors and it should not.
+34 | }
+   |  - borrow later used here, when `foo` is dropped
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/maybe-initialized-drop.rs b/src/test/ui/nll/maybe-initialized-drop.rs
index 291fcbd73f3..767c5b9b8be 100644
--- a/src/test/ui/nll/maybe-initialized-drop.rs
+++ b/src/test/ui/nll/maybe-initialized-drop.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir -Z nll
+//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll -Znll-dump-cause
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/nll/maybe-initialized-drop.stderr b/src/test/ui/nll/maybe-initialized-drop.stderr
index 7b1b55d133a..626307a80ed 100644
--- a/src/test/ui/nll/maybe-initialized-drop.stderr
+++ b/src/test/ui/nll/maybe-initialized-drop.stderr
@@ -5,6 +5,8 @@ error[E0506]: cannot assign to `x` because it is borrowed
    |                          ------ borrow of `x` occurs here
 26 |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
    |     ^^^^^ assignment to borrowed `x` occurs here
+27 | }
+   |  - borrow later used here, when `wrap` is dropped
 
 error: aborting due to previous error