Skip to content

Commit 65e2539

Browse files
committed
Don't suggest adding a synthesized region name.
1 parent 6bf131f commit 65e2539

File tree

3 files changed

+72
-25
lines changed

3 files changed

+72
-25
lines changed

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@ use rustc::infer::InferCtxt;
1717
use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind};
1818
use rustc::ty::{TyCtxt, Ty, TyS, TyKind, Region, RegionKind, RegionVid};
1919
use rustc_data_structures::indexed_vec::IndexVec;
20-
use rustc_errors::Diagnostic;
20+
use rustc_errors::{Diagnostic, DiagnosticBuilder};
2121
use std::collections::VecDeque;
2222
use std::fmt;
23+
use syntax::symbol::keywords;
2324
use syntax_pos::Span;
2425

2526
mod region_name;
2627
mod var_name;
2728

29+
use self::region_name::RegionName;
30+
2831
/// Constraints that are considered interesting can be categorized to
2932
/// determine why they are interesting. Order of variants indicates
3033
/// sort order of the category, thereby influencing diagnostic output.
@@ -473,27 +476,44 @@ impl<'tcx> RegionInferenceContext<'tcx> {
473476
},
474477
}
475478

479+
self.add_static_impl_trait_suggestion(
480+
infcx, &mut diag, fr_name, fr_region, outlived_fr_region
481+
);
482+
483+
diag.buffer(errors_buffer);
484+
}
485+
486+
fn add_static_impl_trait_suggestion(
487+
&self,
488+
infcx: &InferCtxt<'_, '_, 'tcx>,
489+
diag: &mut DiagnosticBuilder<'_>,
490+
fr_name: RegionName,
491+
fr_region: Option<Region<'tcx>>,
492+
outlived_fr_region: Option<Region<'tcx>>,
493+
) {
476494
if let (Some(f), Some(RegionKind::ReStatic)) = (fr_region, outlived_fr_region) {
477495
if let Some(TyS {
478496
sty: TyKind::Anon(did, _),
479497
..
480498
}) = self.return_type_impl_trait(infcx, f) {
499+
let static_str = keywords::StaticLifetime.name();
481500
let span = infcx.tcx.def_span(*did);
482501
if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) {
483502
diag.span_suggestion(
484503
span,
485504
&format!(
486505
"you can add a constraint to the return type to make it last \
487-
less than `'static` and match {}",
488-
fr_name,
506+
less than `{}` and match `{}`",
507+
static_str, fr_name,
489508
),
490-
format!("{} + {}", snippet, fr_name),
509+
match fr_name {
510+
RegionName::Named(name) => format!("{} + {}", snippet, name),
511+
RegionName::Synthesized(_) => format!("{} + '_", snippet),
512+
},
491513
);
492514
}
493515
}
494516
}
495-
496-
diag.buffer(errors_buffer);
497517
}
498518

499519
// Finds some region R such that `fr1: R` and `R` is live at

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs

+44-17
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::fmt::{self, Display};
1112
use borrow_check::nll::region_infer::RegionInferenceContext;
1213
use borrow_check::nll::universal_regions::DefiningTy;
1314
use borrow_check::nll::ToRegionVid;
@@ -23,6 +24,24 @@ use syntax::ast::{Name, DUMMY_NODE_ID};
2324
use syntax::symbol::keywords;
2425
use syntax_pos::symbol::InternedString;
2526

27+
/// Name of a region used in error reporting. Variants denote the source of the region name -
28+
/// whether it was synthesized for the error message and therefore should not be used in
29+
/// suggestions; or whether it was found from the region.
30+
#[derive(Debug)]
31+
pub(crate) enum RegionName {
32+
Named(InternedString),
33+
Synthesized(InternedString),
34+
}
35+
36+
impl Display for RegionName {
37+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38+
match self {
39+
RegionName::Named(name) | RegionName::Synthesized(name) =>
40+
write!(f, "{}", name),
41+
}
42+
}
43+
}
44+
2645
impl<'tcx> RegionInferenceContext<'tcx> {
2746
/// Maps from an internal MIR region vid to something that we can
2847
/// report to the user. In some cases, the region vids will map
@@ -57,7 +76,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5776
fr: RegionVid,
5877
counter: &mut usize,
5978
diag: &mut DiagnosticBuilder,
60-
) -> InternedString {
79+
) -> RegionName {
6180
debug!("give_region_a_name(fr={:?}, counter={})", fr, counter);
6281

6382
assert!(self.universal_regions.is_universal_region(fr));
@@ -95,27 +114,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
95114
fr: RegionVid,
96115
counter: &mut usize,
97116
diag: &mut DiagnosticBuilder<'_>,
98-
) -> Option<InternedString> {
117+
) -> Option<RegionName> {
99118
let error_region = self.to_error_region(fr)?;
100119

101120
debug!("give_region_a_name: error_region = {:?}", error_region);
102121
match error_region {
103122
ty::ReEarlyBound(ebr) => {
104123
if ebr.has_name() {
105124
self.highlight_named_span(tcx, error_region, &ebr.name, diag);
106-
Some(ebr.name)
125+
Some(RegionName::Named(ebr.name))
107126
} else {
108127
None
109128
}
110129
}
111130

112-
ty::ReStatic => Some(keywords::StaticLifetime.name().as_interned_str()),
131+
ty::ReStatic => Some(RegionName::Named(
132+
keywords::StaticLifetime.name().as_interned_str()
133+
)),
113134

114135
ty::ReFree(free_region) => match free_region.bound_region {
115136
ty::BoundRegion::BrNamed(_, name) => {
116137
self.highlight_named_span(tcx, error_region, &name, diag);
117-
Some(name)
118-
}
138+
Some(RegionName::Named(name))
139+
},
119140

120141
ty::BoundRegion::BrEnv => {
121142
let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir");
@@ -132,7 +153,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
132153
let region_name = self.synthesize_region_name(counter);
133154
diag.span_label(
134155
args_span,
135-
format!("lifetime `{}` represents this closure's body", region_name),
156+
format!(
157+
"lifetime `{}` represents this closure's body",
158+
region_name
159+
),
136160
);
137161

138162
let closure_kind_ty = substs.closure_kind_ty(def_id, tcx);
@@ -227,7 +251,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
227251
fr: RegionVid,
228252
counter: &mut usize,
229253
diag: &mut DiagnosticBuilder<'_>,
230-
) -> Option<InternedString> {
254+
) -> Option<RegionName> {
231255
let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
232256
let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?;
233257

@@ -259,7 +283,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
259283
argument_index: usize,
260284
counter: &mut usize,
261285
diag: &mut DiagnosticBuilder<'_>,
262-
) -> Option<InternedString> {
286+
) -> Option<RegionName> {
263287
let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id)?;
264288
let fn_decl = infcx.tcx.hir.fn_decl(mir_node_id)?;
265289
let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index];
@@ -306,7 +330,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
306330
argument_ty: Ty<'tcx>,
307331
counter: &mut usize,
308332
diag: &mut DiagnosticBuilder<'_>,
309-
) -> Option<InternedString> {
333+
) -> Option<RegionName> {
310334
let type_name = with_highlight_region(needle_fr, *counter, || {
311335
infcx.extract_type_name(&argument_ty)
312336
});
@@ -361,7 +385,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
361385
argument_hir_ty: &hir::Ty,
362386
counter: &mut usize,
363387
diag: &mut DiagnosticBuilder<'_>,
364-
) -> Option<InternedString> {
388+
) -> Option<RegionName> {
365389
let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> = &mut Vec::new();
366390

367391
search_stack.push((argument_ty, argument_hir_ty));
@@ -457,7 +481,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
457481
counter: &mut usize,
458482
diag: &mut DiagnosticBuilder<'_>,
459483
search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>,
460-
) -> Option<InternedString> {
484+
) -> Option<RegionName> {
461485
// Did the user give explicit arguments? (e.g., `Foo<..>`)
462486
let args = last_segment.args.as_ref()?;
463487
let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
@@ -467,7 +491,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
467491
| hir::LifetimeName::Underscore => {
468492
let region_name = self.synthesize_region_name(counter);
469493
let ampersand_span = lifetime.span;
470-
diag.span_label(ampersand_span, format!("let's call this `{}`", region_name));
494+
diag.span_label(
495+
ampersand_span,
496+
format!("let's call this `{}`", region_name)
497+
);
471498
return Some(region_name);
472499
}
473500

@@ -544,7 +571,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
544571
fr: RegionVid,
545572
counter: &mut usize,
546573
diag: &mut DiagnosticBuilder<'_>,
547-
) -> Option<InternedString> {
574+
) -> Option<RegionName> {
548575
let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
549576
let (upvar_name, upvar_span) =
550577
self.get_upvar_name_and_span_for_region(tcx, mir, upvar_index);
@@ -573,7 +600,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
573600
fr: RegionVid,
574601
counter: &mut usize,
575602
diag: &mut DiagnosticBuilder<'_>,
576-
) -> Option<InternedString> {
603+
) -> Option<RegionName> {
577604
let tcx = infcx.tcx;
578605

579606
let return_ty = self.universal_regions.unnormalized_output_ty;
@@ -622,10 +649,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
622649

623650
/// Create a synthetic region named `'1`, incrementing the
624651
/// counter.
625-
fn synthesize_region_name(&self, counter: &mut usize) -> InternedString {
652+
fn synthesize_region_name(&self, counter: &mut usize) -> RegionName {
626653
let c = *counter;
627654
*counter += 1;
628655

629-
Name::intern(&format!("'{:?}", c)).as_interned_str()
656+
RegionName::Synthesized(Name::intern(&format!("'{:?}", c)).as_interned_str())
630657
}
631658
}

src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ error: unsatisfied lifetime constraints
1111
|
1212
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
1313
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
14-
help: you can add a constraint to the return type to make it last less than `'static` and match 'a
14+
help: you can add a constraint to the return type to make it last less than `'static` and match `'a`
1515
|
1616
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
1717
| ^^^^^^^^^^^^^^
@@ -21,7 +21,7 @@ error: unsatisfied lifetime constraints
2121
|
2222
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
2323
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
24-
help: you can add a constraint to the return type to make it last less than `'static` and match 'a
24+
help: you can add a constraint to the return type to make it last less than `'static` and match `'a`
2525
|
2626
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
2727
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)