2017-06-29 21:40:04 +02:00
|
|
|
//! Error Reporting for Anonymous Region Lifetime Errors
|
|
|
|
//! where one region is named and the other is anonymous.
|
2019-12-22 23:42:04 +01:00
|
|
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
2019-02-05 18:20:45 +01:00
|
|
|
use crate::ty;
|
2019-12-31 21:25:16 +01:00
|
|
|
use errors::{struct_span_err, Applicability, DiagnosticBuilder};
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::{FunctionRetTy, TyKind};
|
2017-06-12 20:45:19 +02:00
|
|
|
|
2019-11-11 22:46:56 +01:00
|
|
|
use rustc_error_codes::*;
|
|
|
|
|
2019-06-13 23:48:52 +02:00
|
|
|
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
2019-08-27 13:24:32 +02:00
|
|
|
/// When given a `ConcreteFailure` for a function with parameters containing a named region and
|
2017-11-07 06:02:31 +01:00
|
|
|
/// an anonymous region, emit an descriptive diagnostic error.
|
2019-02-06 14:11:09 +01:00
|
|
|
pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'a>> {
|
2019-10-23 19:28:27 +02:00
|
|
|
let (span, sub, sup) = self.regions();
|
2017-06-12 20:45:19 +02:00
|
|
|
|
2017-12-12 14:31:38 +01:00
|
|
|
debug!(
|
2019-03-31 18:07:56 +02:00
|
|
|
"try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
|
2019-12-22 23:42:04 +01:00
|
|
|
sub, sup, self.error,
|
2017-12-12 14:31:38 +01:00
|
|
|
);
|
2017-08-25 08:21:22 +02:00
|
|
|
|
2017-06-18 01:27:07 +02:00
|
|
|
// Determine whether the sub and sup consist of one named region ('a)
|
|
|
|
// and one anonymous (elided) region. If so, find the parameter arg
|
|
|
|
// where the anonymous region appears (there must always be one; we
|
|
|
|
// only introduced anonymous regions in parameters) as well as a
|
|
|
|
// version new_ty of its type where the anonymous region is replaced
|
2017-08-17 20:45:30 +02:00
|
|
|
// with the named one.//scope_def_id
|
2019-08-27 13:24:32 +02:00
|
|
|
let (named, anon, anon_param_info, region_info) = if self.is_named_region(sub)
|
2019-01-25 18:22:44 +01:00
|
|
|
&& self.tcx().is_suitable_region(sup).is_some()
|
2019-08-27 13:24:32 +02:00
|
|
|
&& self.find_param_with_region(sup, sub).is_some()
|
2017-12-12 14:31:38 +01:00
|
|
|
{
|
|
|
|
(
|
|
|
|
sub,
|
|
|
|
sup,
|
2019-08-27 13:24:32 +02:00
|
|
|
self.find_param_with_region(sup, sub).unwrap(),
|
2019-01-25 18:22:44 +01:00
|
|
|
self.tcx().is_suitable_region(sup).unwrap(),
|
2017-12-12 14:31:38 +01:00
|
|
|
)
|
2019-12-22 23:42:04 +01:00
|
|
|
} else if self.is_named_region(sup)
|
|
|
|
&& self.tcx().is_suitable_region(sub).is_some()
|
2019-08-27 13:24:32 +02:00
|
|
|
&& self.find_param_with_region(sub, sup).is_some()
|
2017-12-12 14:31:38 +01:00
|
|
|
{
|
|
|
|
(
|
|
|
|
sup,
|
|
|
|
sub,
|
2019-08-27 13:24:32 +02:00
|
|
|
self.find_param_with_region(sub, sup).unwrap(),
|
2019-01-25 18:22:44 +01:00
|
|
|
self.tcx().is_suitable_region(sub).unwrap(),
|
2017-12-12 14:31:38 +01:00
|
|
|
)
|
|
|
|
} else {
|
2017-12-12 14:39:20 +01:00
|
|
|
return None; // inapplicable
|
2017-12-12 14:31:38 +01:00
|
|
|
};
|
2017-06-20 15:42:11 +02:00
|
|
|
|
2017-08-25 08:21:22 +02:00
|
|
|
debug!("try_report_named_anon_conflict: named = {:?}", named);
|
2019-12-22 23:42:04 +01:00
|
|
|
debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info);
|
|
|
|
debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);
|
2017-08-25 08:21:22 +02:00
|
|
|
|
2019-08-27 13:24:32 +02:00
|
|
|
let (param, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = (
|
|
|
|
anon_param_info.param,
|
|
|
|
anon_param_info.param_ty,
|
|
|
|
anon_param_info.param_ty_span,
|
|
|
|
anon_param_info.bound_region,
|
|
|
|
anon_param_info.is_first,
|
2017-12-12 14:31:38 +01:00
|
|
|
region_info.def_id,
|
|
|
|
region_info.is_impl_item,
|
|
|
|
);
|
2017-08-25 08:21:22 +02:00
|
|
|
match br {
|
|
|
|
ty::BrAnon(_) => {}
|
|
|
|
_ => {
|
|
|
|
/* not an anonymous region */
|
|
|
|
debug!("try_report_named_anon_conflict: not an anonymous region");
|
2017-12-12 14:39:20 +01:00
|
|
|
return None;
|
2017-08-25 08:21:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-23 15:10:28 +02:00
|
|
|
if is_impl_item {
|
2017-08-25 08:21:22 +02:00
|
|
|
debug!("try_report_named_anon_conflict: impl item, bail out");
|
2017-12-12 14:39:20 +01:00
|
|
|
return None;
|
2017-08-23 15:10:28 +02:00
|
|
|
}
|
|
|
|
|
2017-09-24 16:16:29 +02:00
|
|
|
if let Some((_, fndecl)) = self.find_anon_type(anon, &br) {
|
2017-12-12 14:31:38 +01:00
|
|
|
if self.is_return_type_anon(scope_def_id, br, fndecl).is_some()
|
|
|
|
|| self.is_self_anon(is_first, scope_def_id)
|
|
|
|
{
|
2017-12-12 14:39:20 +01:00
|
|
|
return None;
|
2017-09-11 16:29:57 +02:00
|
|
|
}
|
2019-03-31 18:07:56 +02:00
|
|
|
if let FunctionRetTy::Return(ty) = &fndecl.output {
|
2019-09-26 18:25:31 +02:00
|
|
|
if let (TyKind::Def(_, _), ty::ReStatic) = (&ty.kind, sub) {
|
2019-03-31 18:07:56 +02:00
|
|
|
// This is an impl Trait return that evaluates de need of 'static.
|
|
|
|
// We handle this case better in `static_impl_trait`.
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
2017-09-11 16:29:57 +02:00
|
|
|
}
|
|
|
|
|
2019-08-27 13:24:32 +02:00
|
|
|
let (error_var, span_label_var) = match param.pat.simple_ident() {
|
2019-03-13 17:10:27 +01:00
|
|
|
Some(simple_ident) => (
|
2018-06-10 18:33:30 +02:00
|
|
|
format!("the type of `{}`", simple_ident),
|
|
|
|
format!("the type of `{}`", simple_ident),
|
2019-03-13 17:10:27 +01:00
|
|
|
),
|
|
|
|
None => ("parameter type".to_owned(), "type".to_owned()),
|
2017-09-11 16:29:57 +02:00
|
|
|
};
|
|
|
|
|
2019-02-06 14:11:09 +01:00
|
|
|
let mut diag = struct_span_err!(
|
2019-01-25 18:22:44 +01:00
|
|
|
self.tcx().sess,
|
2017-12-12 14:31:38 +01:00
|
|
|
span,
|
|
|
|
E0621,
|
|
|
|
"explicit lifetime required in {}",
|
|
|
|
error_var
|
2019-02-06 14:11:09 +01:00
|
|
|
);
|
|
|
|
|
2019-03-31 18:07:56 +02:00
|
|
|
diag.span_label(span, format!("lifetime `{}` required", named));
|
2019-02-06 14:11:09 +01:00
|
|
|
diag.span_suggestion(
|
2019-03-04 20:52:03 +01:00
|
|
|
new_ty_span,
|
2019-03-31 18:07:56 +02:00
|
|
|
&format!("add explicit lifetime `{}` to {}", named, span_label_var),
|
2019-03-04 20:52:03 +01:00
|
|
|
new_ty.to_string(),
|
|
|
|
Applicability::Unspecified,
|
|
|
|
);
|
2019-02-06 14:11:09 +01:00
|
|
|
|
|
|
|
Some(diag)
|
2017-06-12 20:45:19 +02:00
|
|
|
}
|
2018-01-10 18:13:07 +01:00
|
|
|
|
|
|
|
// This method returns whether the given Region is Named
|
|
|
|
pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
|
|
|
|
match *region {
|
|
|
|
ty::ReStatic => true,
|
|
|
|
ty::ReFree(ref free_region) => match free_region.bound_region {
|
|
|
|
ty::BrNamed(..) => true,
|
|
|
|
_ => false,
|
|
|
|
},
|
2018-08-06 21:15:15 +02:00
|
|
|
ty::ReEarlyBound(ebr) => ebr.has_name(),
|
2018-01-10 18:13:07 +01:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2017-06-12 20:45:19 +02:00
|
|
|
}
|