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:
parent
5cfa7d1dfb
commit
2bd16f3c81
6 changed files with 41 additions and 31 deletions
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -595,11 +595,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
pub fn unexpected_hidden_region_diagnostic(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
region_scope_tree: Option<®ion::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,
|
||||
)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue