]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
Unify API of `Scalar` and `ScalarMaybeUndef`
[rust.git] / src / librustc_mir / borrow_check / nll / explain_borrow / mod.rs
1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use borrow_check::borrow_set::BorrowData;
12 use borrow_check::nll::region_infer::Cause;
13 use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
14 use rustc::mir::Place;
15 use rustc_errors::DiagnosticBuilder;
16
17 mod find_use;
18
19 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20     /// Adds annotations to `err` explaining *why* the borrow contains the
21     /// point from `context`. This is key for the "3-point errors"
22     /// [described in the NLL RFC][d].
23     ///
24     /// # Parameters
25     ///
26     /// - `borrow`: the borrow in question
27     /// - `context`: where the borrow occurs
28     /// - `kind_place`: if Some, this describes the statement that triggered the error.
29     ///   - first half is the kind of write, if any, being performed
30     ///   - second half is the place being accessed
31     /// - `err`: where the error annotations are going to be added
32     ///
33     /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
34     pub(in borrow_check) fn explain_why_borrow_contains_point(
35         &mut self,
36         context: Context,
37         borrow: &BorrowData<'tcx>,
38         kind_place: Option<(WriteKind, &Place<'tcx>)>,
39         err: &mut DiagnosticBuilder<'_>,
40     ) {
41         debug!(
42             "explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})",
43             context, borrow, kind_place,
44         );
45
46         let regioncx = &self.nonlexical_regioncx;
47         let mir = self.mir;
48         let tcx = self.tcx;
49
50         let borrow_region_vid = regioncx.to_region_vid(borrow.region);
51
52         debug!(
53             "explain_why_borrow_contains_point: borrow_region_vid={:?}",
54             borrow_region_vid
55         );
56
57         let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, context.loc);
58
59         debug!(
60             "explain_why_borrow_contains_point: region_sub={:?}",
61             region_sub
62         );
63
64         match find_use::find(mir, regioncx, tcx, region_sub, context.loc) {
65             Some(Cause::LiveVar(_local, location)) => {
66                 err.span_label(
67                     mir.source_info(location).span,
68                     "borrow later used here".to_string(),
69                 );
70             }
71
72             Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name {
73                 Some(local_name) => {
74                     err.span_label(
75                         mir.source_info(location).span,
76                         format!("borrow later used here, when `{}` is dropped", local_name),
77                     );
78
79                     if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
80                         if let Place::Local(borrowed_local) = place {
81                             let dropped_local_scope = mir.local_decls[local].visibility_scope;
82                             let borrowed_local_scope =
83                                 mir.local_decls[*borrowed_local].visibility_scope;
84
85                             if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
86                                 err.note(
87                                     "values in a scope are dropped \
88                                      in the opposite order they are defined",
89                                 );
90                             }
91                         }
92                     }
93                 }
94
95                 None => {}
96             },
97
98             None => {
99                 if let Some(region) = regioncx.to_error_region(region_sub) {
100                     self.tcx.note_and_explain_free_region(
101                         err,
102                         "borrowed value must be valid for ",
103                         region,
104                         "...",
105                     );
106                 }
107             }
108         }
109     }
110 }