Skip to content

Commit

Permalink
Updated suggestion/help messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtwco committed Sep 13, 2018
1 parent 7a89e93 commit 37e18b1
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 48 deletions.
Expand Up @@ -15,7 +15,7 @@ use rustc::hir::def_id::DefId;
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc::infer::InferCtxt;
use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind};
use rustc::ty::{self, TyCtxt, Region, RegionKind, RegionVid};
use rustc::ty::{self, TyCtxt, RegionVid};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
use std::collections::VecDeque;
Expand Down Expand Up @@ -347,9 +347,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
);

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

debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} fr_region={:?} \
outlived_fr_region={:?} category={:?}",
fr_is_local, outlived_fr_is_local, fr_region, outlived_fr_region, category);
debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
fr_is_local, outlived_fr_is_local, category);
match (category, fr_is_local, outlived_fr_is_local) {
(ConstraintCategory::Assignment, true, false) |
(ConstraintCategory::CallArgument, true, false) =>
self.report_escaping_data_error(mir, infcx, mir_def_id, fr, fr_region, outlived_fr,
outlived_fr_region, category, span, errors_buffer),
self.report_escaping_data_error(mir, infcx, mir_def_id, fr, outlived_fr,
category, span, errors_buffer),
_ =>
self.report_general_error(mir, infcx, mir_def_id, fr, fr_is_local, fr_region,
outlived_fr, outlived_fr_is_local, outlived_fr_region,
self.report_general_error(mir, infcx, mir_def_id, fr, fr_is_local,
outlived_fr, outlived_fr_is_local,
category, span, errors_buffer),
};
}
Expand All @@ -383,9 +380,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
infcx: &InferCtxt<'_, '_, 'tcx>,
mir_def_id: DefId,
fr: RegionVid,
fr_region: Option<Region<'tcx>>,
outlived_fr: RegionVid,
outlived_fr_region: Option<Region<'tcx>>,
category: ConstraintCategory,
span: Span,
errors_buffer: &mut Vec<Diagnostic>,
Expand All @@ -398,8 +393,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {

if fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none() {
return self.report_general_error(mir, infcx, mir_def_id,
fr, true, fr_region,
outlived_fr, false, outlived_fr_region,
fr, true, outlived_fr, false,
category, span, errors_buffer);
}

Expand Down Expand Up @@ -439,10 +433,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
mir_def_id: DefId,
fr: RegionVid,
fr_is_local: bool,
fr_region: Option<Region<'tcx>>,
outlived_fr: RegionVid,
outlived_fr_is_local: bool,
outlived_fr_region: Option<Region<'tcx>>,
category: ConstraintCategory,
span: Span,
errors_buffer: &mut Vec<Diagnostic>,
Expand Down Expand Up @@ -477,7 +469,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}

self.add_static_impl_trait_suggestion(
infcx, &mut diag, fr_name, fr_region, outlived_fr_region
infcx, &mut diag, fr, fr_name, outlived_fr,
);

diag.buffer(errors_buffer);
Expand All @@ -487,11 +479,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
diag: &mut DiagnosticBuilder<'_>,
fr: RegionVid,
// We need to pass `fr_name` - computing it again will label it twice.
fr_name: RegionName,
fr_region: Option<Region<'tcx>>,
outlived_fr_region: Option<Region<'tcx>>,
outlived_fr: RegionVid,
) {
if let (Some(f), Some(ty::RegionKind::ReStatic)) = (fr_region, outlived_fr_region) {
if let (
Some(f),
Some(ty::RegionKind::ReStatic)
) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
if let Some(ty::TyS {
sty: ty::TyKind::Anon(did, substs),
..
Expand All @@ -500,6 +496,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.map(|id| infcx.tcx.return_type_impl_trait(id))
.unwrap_or(None)
{
// Check whether or not the impl trait return type is intended to capture
// data with the static lifetime.
//
// eg. check for `impl Trait + 'static` instead of `impl Trait`.
let has_static_predicate = {
let predicates_of = infcx.tcx.predicates_of(*did);
let bounds = predicates_of.instantiate(infcx.tcx, substs);
Expand All @@ -509,7 +509,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
if let ty::Predicate::TypeOutlives(binder) = predicate {
if let ty::OutlivesPredicate(
_,
RegionKind::ReStatic
ty::RegionKind::ReStatic
) = binder.skip_binder() {
found = true;
break;
Expand All @@ -523,33 +523,31 @@ impl<'tcx> RegionInferenceContext<'tcx> {
debug!("add_static_impl_trait_suggestion: has_static_predicate={:?}",
has_static_predicate);
let static_str = keywords::StaticLifetime.name();
// If there is a static predicate, then the only sensible suggestion is to replace
// fr with `'static`.
if has_static_predicate {
let span = self.get_span_of_named_region(infcx.tcx, f, &fr_name);
if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) {
diag.span_suggestion(
span,
&format!(
"you can add a constraint to the definition of `{}` to require it \
outlive `{}`",
fr_name, static_str,
),
format!("{}: {}", snippet, static_str),
);
}
diag.help(
&format!(
"consider replacing `{}` with `{}`",
fr_name, static_str,
),
);
} else {
// Otherwise, we should suggest adding a constraint on the return type.
let span = infcx.tcx.def_span(*did);
if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) {
let suggestable_fr_name = match fr_name {
RegionName::Named(name) => format!("{}", name),
RegionName::Synthesized(_) => "'_".to_string(),
};
diag.span_suggestion(
span,
&format!(
"you can add a constraint to the return type to make it last \
less than `{}` and match `{}`",
static_str, fr_name,
"to allow this impl Trait to capture borrowed data with lifetime \
`{}`, add `{}` as a constraint",
fr_name, suggestable_fr_name,
),
match fr_name {
RegionName::Named(name) => format!("{} + {}", snippet, name),
RegionName::Synthesized(_) => format!("{} + '_", snippet),
},
format!("{} + {}", snippet, suggestable_fr_name),
);
}
}
Expand Down
Expand Up @@ -11,7 +11,7 @@ error: unsatisfied lifetime constraints
|
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
help: you can add a constraint to the return type to make it last less than `'static` and match `'a`
help: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint
|
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ^^^^^^^^^^^^^^
Expand All @@ -21,10 +21,8 @@ error: unsatisfied lifetime constraints
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
help: you can add a constraint to the definition of `'a` to require it outlive `'static`
|
LL | fn with_bound<'a: 'static>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| ^^^^^^^^^^^
= help: consider replacing `'a` with `'static`

error: unsatisfied lifetime constraints
--> $DIR/must_outlive_least_region_or_bound.rs:29:5
Expand Down
Expand Up @@ -5,9 +5,9 @@ LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
| - let's call the lifetime of this reference `'1`
LL | self.x.iter().map(|a| a.0)
| ^^^^^^ cast requires that `'1` must outlive `'static`
help: you can add a constraint to the return type to make it last less than `'static` and match '1
help: to allow this impl Trait to capture borrowed data with lifetime `'1`, add `'_` as a constraint
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '1 {
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

0 comments on commit 37e18b1

Please sign in to comment.