]> git.lizzy.rs Git - rust.git/blob - src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs
fc858a497597e5bad0f2e02bd935c33089a201d5
[rust.git] / src / librustc_infer / infer / error_reporting / nice_region_error / outlives_closure.rs
1 //! Error Reporting for Anonymous Region Lifetime Errors
2 //! where both the regions are anonymous.
3
4 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
5 use crate::infer::lexical_region_resolve::RegionResolutionError::SubSupConflict;
6 use crate::infer::SubregionOrigin;
7 use rustc_errors::ErrorReported;
8 use rustc_hir::{Expr, ExprKind::Closure, Node};
9 use rustc_middle::ty::RegionKind;
10
11 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
12     /// Print the error message for lifetime errors when binding escapes a closure.
13     ///
14     /// Consider a case where we have
15     ///
16     /// ```no_run
17     /// fn with_int<F>(f: F) where F: FnOnce(&isize) {
18     ///     let x = 3;
19     ///     f(&x);
20     /// }
21     /// fn main() {
22     ///     let mut x = None;
23     ///     with_int(|y| x = Some(y));
24     /// }
25     /// ```
26     ///
27     /// the output will be
28     ///
29     /// ```text
30     ///     let mut x = None;
31     ///         ----- borrowed data cannot be stored into here...
32     ///     with_int(|y| x = Some(y));
33     ///              ---          ^ cannot be stored outside of its closure
34     ///              |
35     ///              ...because it cannot outlive this closure
36     /// ```
37     pub(super) fn try_report_outlives_closure(&self) -> Option<ErrorReported> {
38         if let Some(SubSupConflict(_, origin, ref sub_origin, _, ref sup_origin, sup_region)) =
39             self.error
40         {
41             // #45983: when trying to assign the contents of an argument to a binding outside of a
42             // closure, provide a specific message pointing this out.
43             if let (
44                 &SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span),
45                 &RegionKind::ReFree(ref free_region),
46             ) = (&sub_origin, sup_region)
47             {
48                 let hir = &self.tcx().hir();
49                 if let Some(def_id) = free_region.scope.as_local() {
50                     let hir_id = hir.as_local_hir_id(def_id);
51                     if let Node::Expr(Expr { kind: Closure(_, _, _, closure_span, None), .. }) =
52                         hir.get(hir_id)
53                     {
54                         let sup_sp = sup_origin.span();
55                         let origin_sp = origin.span();
56                         let mut err = self.tcx().sess.struct_span_err(
57                             sup_sp,
58                             "borrowed data cannot be stored outside of its closure",
59                         );
60                         err.span_label(sup_sp, "cannot be stored outside of its closure");
61                         if origin_sp == sup_sp || origin_sp.contains(sup_sp) {
62                             // // sup_sp == origin.span():
63                             //
64                             // let mut x = None;
65                             //     ----- borrowed data cannot be stored into here...
66                             // with_int(|y| x = Some(y));
67                             //          ---          ^ cannot be stored outside of its closure
68                             //          |
69                             //          ...because it cannot outlive this closure
70                             //
71                             // // origin.contains(&sup_sp):
72                             //
73                             // let mut f: Option<&u32> = None;
74                             //     ----- borrowed data cannot be stored into here...
75                             // closure_expecting_bound(|x: &'x u32| {
76                             //                         ------------ ... because it cannot outlive this closure
77                             //     f = Some(x);
78                             //              ^ cannot be stored outside of its closure
79                             err.span_label(
80                                 *external_span,
81                                 "borrowed data cannot be stored into here...",
82                             );
83                             err.span_label(
84                                 *closure_span,
85                                 "...because it cannot outlive this closure",
86                             );
87                         } else {
88                             // FIXME: the wording for this case could be much improved
89                             //
90                             // let mut lines_to_use: Vec<&CrateId> = Vec::new();
91                             //                           - cannot infer an appropriate lifetime...
92                             // let push_id = |installed_id: &CrateId| {
93                             //     -------   ------------------------ borrowed data cannot outlive this closure
94                             //     |
95                             //     ...so that variable is valid at time of its declaration
96                             //     lines_to_use.push(installed_id);
97                             //                       ^^^^^^^^^^^^ cannot be stored outside of its closure
98                             err.span_label(origin_sp, "cannot infer an appropriate lifetime...");
99                             err.span_label(
100                                 *external_span,
101                                 "...so that variable is valid at time of its \
102                                             declaration",
103                             );
104                             err.span_label(
105                                 *closure_span,
106                                 "borrowed data cannot outlive this closure",
107                             );
108                         }
109                         err.emit();
110                         return Some(ErrorReported);
111                     }
112                 }
113             }
114         }
115         None
116     }
117 }