1
Fork 0

Improve opaque type lifetime errors

* Use better span for member constraint errors
* Avoid a bad suggestion
* Don't report member constraint errors if we have other universal
  region errors.
This commit is contained in:
Matthew Jasper 2020-01-11 14:12:39 +00:00
parent 5cfa7d1dfb
commit 2bd16f3c81
6 changed files with 41 additions and 31 deletions

View file

@ -405,17 +405,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
RegionResolutionError::MemberConstraintFailure {
opaque_type_def_id,
hidden_ty,
member_region,
span: _,
choice_regions: _,
span,
} => {
let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
opaque_types::unexpected_hidden_region_diagnostic(
self.tcx,
Some(region_scope_tree),
opaque_type_def_id,
span,
hidden_ty,
member_region,
)

View file

@ -18,7 +18,6 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::implementation::{
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
};
use rustc_hir::def_id::DefId;
use rustc_index::vec::{Idx, IndexVec};
use rustc_span::Span;
use std::fmt;
@ -95,13 +94,7 @@ pub enum RegionResolutionError<'tcx> {
/// Indicates a failure of a `MemberConstraint`. These arise during
/// impl trait processing explicitly -- basically, the impl trait's hidden type
/// included some region that it was not supposed to.
MemberConstraintFailure {
span: Span,
opaque_type_def_id: DefId,
hidden_ty: Ty<'tcx>,
member_region: Region<'tcx>,
choice_regions: Vec<Region<'tcx>>,
},
MemberConstraintFailure { span: Span, hidden_ty: Ty<'tcx>, member_region: Region<'tcx> },
}
struct RegionAndOrigin<'tcx> {
@ -656,10 +649,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
let span = self.tcx().def_span(member_constraint.opaque_type_def_id);
errors.push(RegionResolutionError::MemberConstraintFailure {
span,
opaque_type_def_id: member_constraint.opaque_type_def_id,
hidden_ty: member_constraint.hidden_ty,
member_region,
choice_regions: choice_regions.collect(),
});
}
}

View file

@ -595,11 +595,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn unexpected_hidden_region_diagnostic(
tcx: TyCtxt<'tcx>,
region_scope_tree: Option<&region::ScopeTree>,
opaque_type_def_id: DefId,
span: Span,
hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>,
) -> DiagnosticBuilder<'tcx> {
let span = tcx.def_span(opaque_type_def_id);
let mut err = struct_span_err!(
tcx.sess,
span,
@ -851,7 +850,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
unexpected_hidden_region_diagnostic(
self.tcx,
None,
self.opaque_type_def_id,
self.tcx.def_span(self.opaque_type_def_id),
hidden_ty,
r,
)

View file

@ -6,7 +6,6 @@ use rustc::infer::{
use rustc::mir::ConstraintCategory;
use rustc::ty::{self, RegionVid, Ty};
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir::def_id::DefId;
use rustc_span::symbol::kw;
use rustc_span::Span;
@ -58,8 +57,8 @@ crate enum RegionErrorKind<'tcx> {
/// An unexpected hidden region for an opaque type.
UnexpectedHiddenRegion {
/// The def id of the opaque type.
opaque_type_def_id: DefId,
/// The span for the member constraint.
span: Span,
/// The hidden type.
hidden_ty: Ty<'tcx>,
/// The unexpected region.
@ -194,18 +193,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
RegionErrorKind::UnexpectedHiddenRegion {
opaque_type_def_id,
hidden_ty,
member_region,
} => {
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
opaque_types::unexpected_hidden_region_diagnostic(
self.infcx.tcx,
Some(region_scope_tree),
opaque_type_def_id,
hidden_ty,
member_region,
span,
named_ty,
named_region,
)
.buffer(&mut self.errors_buffer);
}
@ -588,6 +585,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
{
found = true;
break;
} else {
// If there's already a lifetime bound, don't
// suggest anything.
return;
}
}
}

View file

@ -511,7 +511,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer);
}
self.check_member_constraints(infcx, &mut errors_buffer);
if errors_buffer.is_empty() {
self.check_member_constraints(infcx, &mut errors_buffer);
}
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
@ -1604,7 +1606,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// If not, report an error.
let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
opaque_type_def_id: m_c.opaque_type_def_id,
span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
member_region,
});

View file

@ -1,5 +1,5 @@
use rustc::infer::InferCtxt;
use rustc::ty;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_span::Span;
@ -119,4 +119,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
})
.collect()
}
/// Map the regions in the type to named regions. This is similar to what
/// `infer_opaque_types` does, but can infer any universal region, not only
/// ones from the substs for the opaque type. It also doesn't double check
/// that the regions produced are in fact equal to the named region they are
/// replaced with. This is fine because this function is only to improve the
/// region names in error messages.
pub(in crate::borrow_check) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
where
T: TypeFoldable<'tcx>,
{
tcx.fold_regions(&ty, &mut false, |region, _| match *region {
ty::ReVar(vid) => {
let upper_bound = self.universal_upper_bound(vid);
self.definitions[upper_bound].external_name.unwrap_or(region)
}
_ => region,
})
}
}