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.
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.
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;
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].
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
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(
37 borrow: &BorrowData<'tcx>,
38 kind_place: Option<(WriteKind, &Place<'tcx>)>,
39 err: &mut DiagnosticBuilder<'_>,
42 "explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})",
43 context, borrow, kind_place,
46 let regioncx = &self.nonlexical_regioncx;
50 let borrow_region_vid = regioncx.to_region_vid(borrow.region);
53 "explain_why_borrow_contains_point: borrow_region_vid={:?}",
57 let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, context.loc);
60 "explain_why_borrow_contains_point: region_sub={:?}",
64 match find_use::find(mir, regioncx, tcx, region_sub, context.loc) {
65 Some(Cause::LiveVar(_local, location)) => {
67 mir.source_info(location).span,
68 "borrow later used here".to_string(),
72 Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name {
75 mir.source_info(location).span,
76 format!("borrow later used here, when `{}` is dropped", local_name),
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;
85 if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
87 "values in a scope are dropped \
88 in the opposite order they are defined",
99 if let Some(region) = regioncx.to_error_region(region_sub) {
100 self.tcx.note_and_explain_free_region(
102 "borrowed value must be valid for ",