|
10 | 10 |
|
11 | 11 | use borrow_check::nll::region_infer::RegionInferenceContext;
|
12 | 12 | use borrow_check::nll::ToRegionVid;
|
| 13 | +use borrow_check::nll::universal_regions::DefiningTy; |
13 | 14 | use rustc::hir;
|
14 | 15 | use rustc::hir::def_id::DefId;
|
15 | 16 | use rustc::infer::InferCtxt;
|
@@ -72,7 +73,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
72 | 73 | })
|
73 | 74 | .or_else(|| {
|
74 | 75 | self.give_name_if_anonymous_region_appears_in_output(
|
75 |
| - infcx.tcx, mir, fr, counter, diag) |
| 76 | + infcx, mir, mir_def_id, fr, counter, diag) |
76 | 77 | })
|
77 | 78 | .unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr))
|
78 | 79 | }
|
@@ -107,13 +108,46 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
107 | 108 | },
|
108 | 109 |
|
109 | 110 | ty::BoundRegion::BrEnv => {
|
110 |
| - let closure_span = tcx.hir.span_if_local(mir_def_id).unwrap(); |
111 |
| - let region_name = self.synthesize_region_name(counter); |
112 |
| - diag.span_label( |
113 |
| - closure_span, |
114 |
| - format!("lifetime `{}` represents the closure body", region_name), |
115 |
| - ); |
116 |
| - Some(region_name) |
| 111 | + let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); |
| 112 | + let def_ty = self.universal_regions.defining_ty; |
| 113 | + |
| 114 | + if let DefiningTy::Closure(def_id, substs) = def_ty { |
| 115 | + let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) |
| 116 | + = tcx.hir.expect_expr(mir_node_id).node |
| 117 | + { |
| 118 | + span |
| 119 | + } else { |
| 120 | + bug!("Closure is not defined by a closure expr"); |
| 121 | + }; |
| 122 | + let region_name = self.synthesize_region_name(counter); |
| 123 | + diag.span_label( |
| 124 | + args_span, |
| 125 | + format!("lifetime `{}` represents this closure's body", region_name), |
| 126 | + ); |
| 127 | + |
| 128 | + let closure_kind_ty = substs.closure_kind_ty(def_id, tcx); |
| 129 | + let note = match closure_kind_ty.to_opt_closure_kind() { |
| 130 | + Some(ty::ClosureKind::Fn) => { |
| 131 | + "closure implements `Fn`, so references to captured variables \ |
| 132 | + can't escape the closure" |
| 133 | + } |
| 134 | + Some(ty::ClosureKind::FnMut) => { |
| 135 | + "closure implements `FnMut`, so references to captured variables \ |
| 136 | + can't escape the closure" |
| 137 | + } |
| 138 | + Some(ty::ClosureKind::FnOnce) => { |
| 139 | + bug!("BrEnv in a `FnOnce` closure"); |
| 140 | + } |
| 141 | + None => bug!("Closure kind not inferred in borrow check"), |
| 142 | + }; |
| 143 | + |
| 144 | + diag.note(note); |
| 145 | + |
| 146 | + Some(region_name) |
| 147 | + } else { |
| 148 | + // Can't have BrEnv in functions, constants or generators. |
| 149 | + bug!("BrEnv outside of closure."); |
| 150 | + } |
117 | 151 | }
|
118 | 152 |
|
119 | 153 | ty::BoundRegion::BrAnon(_) | ty::BoundRegion::BrFresh(_) => None,
|
@@ -543,28 +577,51 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
543 | 577 | /// or be early bound (named, not in argument).
|
544 | 578 | fn give_name_if_anonymous_region_appears_in_output(
|
545 | 579 | &self,
|
546 |
| - tcx: TyCtxt<'_, '_, 'tcx>, |
| 580 | + infcx: &InferCtxt<'_, '_, 'tcx>, |
547 | 581 | mir: &Mir<'tcx>,
|
| 582 | + mir_def_id: DefId, |
548 | 583 | fr: RegionVid,
|
549 | 584 | counter: &mut usize,
|
550 | 585 | diag: &mut DiagnosticBuilder<'_>,
|
551 | 586 | ) -> Option<InternedString> {
|
| 587 | + let tcx = infcx.tcx; |
| 588 | + |
552 | 589 | let return_ty = self.universal_regions.unnormalized_output_ty;
|
553 | 590 | debug!(
|
554 | 591 | "give_name_if_anonymous_region_appears_in_output: return_ty = {:?}",
|
555 | 592 | return_ty
|
556 | 593 | );
|
557 |
| - if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { |
| 594 | + if !infcx.tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { |
558 | 595 | return None;
|
559 | 596 | }
|
560 | 597 |
|
561 |
| - let region_name = self.synthesize_region_name(counter); |
| 598 | + let type_name = with_highlight_region(fr, *counter, || { |
| 599 | + infcx.extract_type_name(&return_ty) |
| 600 | + }); |
| 601 | + |
| 602 | + let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); |
| 603 | + |
| 604 | + let (return_span, mir_description) = if let hir::ExprKind::Closure(_, _, _, span, gen_move) |
| 605 | + = tcx.hir.expect_expr(mir_node_id).node |
| 606 | + { |
| 607 | + ( |
| 608 | + tcx.sess.codemap().end_point(span), |
| 609 | + if gen_move.is_some() { " of generator" } else { " of closure" } |
| 610 | + ) |
| 611 | + } else { |
| 612 | + // unreachable? |
| 613 | + (mir.span, "") |
| 614 | + }; |
| 615 | + |
562 | 616 | diag.span_label(
|
563 |
| - mir.span, |
564 |
| - format!("lifetime `{}` appears in return type", region_name), |
| 617 | + return_span, |
| 618 | + format!("return type{} is {}", mir_description, type_name), |
565 | 619 | );
|
566 | 620 |
|
567 |
| - Some(region_name) |
| 621 | + // This counter value will already have been used, so this function will increment it |
| 622 | + // so the next value will be used next and return the region name that would have been |
| 623 | + // used. |
| 624 | + Some(self.synthesize_region_name(counter)) |
568 | 625 | }
|
569 | 626 |
|
570 | 627 | /// Create a synthetic region named `'1`, incrementing the
|
|
0 commit comments