Skip to content

Commit 37e18b1

Browse files
committed
Updated suggestion/help messages.
1 parent 7a89e93 commit 37e18b1

File tree

3 files changed

+44
-48
lines changed

3 files changed

+44
-48
lines changed

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

+39-41
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc::hir::def_id::DefId;
1515
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
1616
use rustc::infer::InferCtxt;
1717
use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind};
18-
use rustc::ty::{self, TyCtxt, Region, RegionKind, RegionVid};
18+
use rustc::ty::{self, TyCtxt, RegionVid};
1919
use rustc_data_structures::indexed_vec::IndexVec;
2020
use rustc_errors::{Diagnostic, DiagnosticBuilder};
2121
use std::collections::VecDeque;
@@ -347,9 +347,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
347347
);
348348

349349
// Check if we can use one of the "nice region errors".
350-
let fr_region = self.to_error_region(fr);
351-
let outlived_fr_region = self.to_error_region(outlived_fr);
352-
if let (Some(f), Some(o)) = (fr_region, outlived_fr_region) {
350+
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
353351
let tables = infcx.tcx.typeck_tables_of(mir_def_id);
354352
let nice = NiceRegionError::new_from_span(infcx.tcx, span, o, f, Some(tables));
355353
if let Some(_error_reported) = nice.try_report_from_nll() {
@@ -362,17 +360,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
362360
self.universal_regions.is_local_free_region(outlived_fr),
363361
);
364362

365-
debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} fr_region={:?} \
366-
outlived_fr_region={:?} category={:?}",
367-
fr_is_local, outlived_fr_is_local, fr_region, outlived_fr_region, category);
363+
debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
364+
fr_is_local, outlived_fr_is_local, category);
368365
match (category, fr_is_local, outlived_fr_is_local) {
369366
(ConstraintCategory::Assignment, true, false) |
370367
(ConstraintCategory::CallArgument, true, false) =>
371-
self.report_escaping_data_error(mir, infcx, mir_def_id, fr, fr_region, outlived_fr,
372-
outlived_fr_region, category, span, errors_buffer),
368+
self.report_escaping_data_error(mir, infcx, mir_def_id, fr, outlived_fr,
369+
category, span, errors_buffer),
373370
_ =>
374-
self.report_general_error(mir, infcx, mir_def_id, fr, fr_is_local, fr_region,
375-
outlived_fr, outlived_fr_is_local, outlived_fr_region,
371+
self.report_general_error(mir, infcx, mir_def_id, fr, fr_is_local,
372+
outlived_fr, outlived_fr_is_local,
376373
category, span, errors_buffer),
377374
};
378375
}
@@ -383,9 +380,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
383380
infcx: &InferCtxt<'_, '_, 'tcx>,
384381
mir_def_id: DefId,
385382
fr: RegionVid,
386-
fr_region: Option<Region<'tcx>>,
387383
outlived_fr: RegionVid,
388-
outlived_fr_region: Option<Region<'tcx>>,
389384
category: ConstraintCategory,
390385
span: Span,
391386
errors_buffer: &mut Vec<Diagnostic>,
@@ -398,8 +393,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
398393

399394
if fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none() {
400395
return self.report_general_error(mir, infcx, mir_def_id,
401-
fr, true, fr_region,
402-
outlived_fr, false, outlived_fr_region,
396+
fr, true, outlived_fr, false,
403397
category, span, errors_buffer);
404398
}
405399

@@ -439,10 +433,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
439433
mir_def_id: DefId,
440434
fr: RegionVid,
441435
fr_is_local: bool,
442-
fr_region: Option<Region<'tcx>>,
443436
outlived_fr: RegionVid,
444437
outlived_fr_is_local: bool,
445-
outlived_fr_region: Option<Region<'tcx>>,
446438
category: ConstraintCategory,
447439
span: Span,
448440
errors_buffer: &mut Vec<Diagnostic>,
@@ -477,7 +469,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
477469
}
478470

479471
self.add_static_impl_trait_suggestion(
480-
infcx, &mut diag, fr_name, fr_region, outlived_fr_region
472+
infcx, &mut diag, fr, fr_name, outlived_fr,
481473
);
482474

483475
diag.buffer(errors_buffer);
@@ -487,11 +479,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
487479
&self,
488480
infcx: &InferCtxt<'_, '_, 'tcx>,
489481
diag: &mut DiagnosticBuilder<'_>,
482+
fr: RegionVid,
483+
// We need to pass `fr_name` - computing it again will label it twice.
490484
fr_name: RegionName,
491-
fr_region: Option<Region<'tcx>>,
492-
outlived_fr_region: Option<Region<'tcx>>,
485+
outlived_fr: RegionVid,
493486
) {
494-
if let (Some(f), Some(ty::RegionKind::ReStatic)) = (fr_region, outlived_fr_region) {
487+
if let (
488+
Some(f),
489+
Some(ty::RegionKind::ReStatic)
490+
) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
495491
if let Some(ty::TyS {
496492
sty: ty::TyKind::Anon(did, substs),
497493
..
@@ -500,6 +496,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
500496
.map(|id| infcx.tcx.return_type_impl_trait(id))
501497
.unwrap_or(None)
502498
{
499+
// Check whether or not the impl trait return type is intended to capture
500+
// data with the static lifetime.
501+
//
502+
// eg. check for `impl Trait + 'static` instead of `impl Trait`.
503503
let has_static_predicate = {
504504
let predicates_of = infcx.tcx.predicates_of(*did);
505505
let bounds = predicates_of.instantiate(infcx.tcx, substs);
@@ -509,7 +509,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
509509
if let ty::Predicate::TypeOutlives(binder) = predicate {
510510
if let ty::OutlivesPredicate(
511511
_,
512-
RegionKind::ReStatic
512+
ty::RegionKind::ReStatic
513513
) = binder.skip_binder() {
514514
found = true;
515515
break;
@@ -523,33 +523,31 @@ impl<'tcx> RegionInferenceContext<'tcx> {
523523
debug!("add_static_impl_trait_suggestion: has_static_predicate={:?}",
524524
has_static_predicate);
525525
let static_str = keywords::StaticLifetime.name();
526+
// If there is a static predicate, then the only sensible suggestion is to replace
527+
// fr with `'static`.
526528
if has_static_predicate {
527-
let span = self.get_span_of_named_region(infcx.tcx, f, &fr_name);
528-
if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) {
529-
diag.span_suggestion(
530-
span,
531-
&format!(
532-
"you can add a constraint to the definition of `{}` to require it \
533-
outlive `{}`",
534-
fr_name, static_str,
535-
),
536-
format!("{}: {}", snippet, static_str),
537-
);
538-
}
529+
diag.help(
530+
&format!(
531+
"consider replacing `{}` with `{}`",
532+
fr_name, static_str,
533+
),
534+
);
539535
} else {
536+
// Otherwise, we should suggest adding a constraint on the return type.
540537
let span = infcx.tcx.def_span(*did);
541538
if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) {
539+
let suggestable_fr_name = match fr_name {
540+
RegionName::Named(name) => format!("{}", name),
541+
RegionName::Synthesized(_) => "'_".to_string(),
542+
};
542543
diag.span_suggestion(
543544
span,
544545
&format!(
545-
"you can add a constraint to the return type to make it last \
546-
less than `{}` and match `{}`",
547-
static_str, fr_name,
546+
"to allow this impl Trait to capture borrowed data with lifetime \
547+
`{}`, add `{}` as a constraint",
548+
fr_name, suggestable_fr_name,
548549
),
549-
match fr_name {
550-
RegionName::Named(name) => format!("{} + {}", snippet, name),
551-
RegionName::Synthesized(_) => format!("{} + '_", snippet),
552-
},
550+
format!("{} + {}", snippet, suggestable_fr_name),
553551
);
554552
}
555553
}

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

+2-4
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: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint
1515
|
1616
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
1717
| ^^^^^^^^^^^^^^
@@ -21,10 +21,8 @@ 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 definition of `'a` to require it outlive `'static`
2524
|
26-
LL | fn with_bound<'a: 'static>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
27-
| ^^^^^^^^^^^
25+
= help: consider replacing `'a` with `'static`
2826

2927
error: unsatisfied lifetime constraints
3028
--> $DIR/must_outlive_least_region_or_bound.rs:29:5

src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
55
| - let's call the lifetime of this reference `'1`
66
LL | self.x.iter().map(|a| a.0)
77
| ^^^^^^ cast requires that `'1` must outlive `'static`
8-
help: you can add a constraint to the return type to make it last less than `'static` and match '1
8+
help: to allow this impl Trait to capture borrowed data with lifetime `'1`, add `'_` as a constraint
99
|
10-
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '1 {
10+
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: unsatisfied lifetime constraints
@@ -17,7 +17,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
1717
| -- lifetime `'a` defined here
1818
LL | self.x.iter().map(|a| a.0)
1919
| ^^^^^^ cast requires that `'a` must outlive `'static`
20-
help: you can add a constraint to the return type to make it last less than `'static` and match 'a
20+
help: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint
2121
|
2222
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)