Move opaque_types::unexpected_hidden_region_diagnostic to error_reporting.
This commit is contained in:
parent
3e5259d3eb
commit
98444ca53e
3 changed files with 85 additions and 87 deletions
|
@ -49,7 +49,6 @@ use super::lexical_region_resolve::RegionResolutionError;
|
||||||
use super::region_constraints::GenericKind;
|
use super::region_constraints::GenericKind;
|
||||||
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
|
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
|
||||||
|
|
||||||
use crate::infer::opaque_types;
|
|
||||||
use crate::infer::{self, SuppressRegionErrors};
|
use crate::infer::{self, SuppressRegionErrors};
|
||||||
use crate::traits::error_reporting::report_object_safety_error;
|
use crate::traits::error_reporting::report_object_safety_error;
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
|
@ -288,6 +287,86 @@ fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option
|
||||||
(format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
|
(format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unexpected_hidden_region_diagnostic(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
region_scope_tree: Option<®ion::ScopeTree>,
|
||||||
|
span: Span,
|
||||||
|
hidden_ty: Ty<'tcx>,
|
||||||
|
hidden_region: ty::Region<'tcx>,
|
||||||
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
|
let mut err = struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
span,
|
||||||
|
E0700,
|
||||||
|
"hidden type for `impl Trait` captures lifetime that does not appear in bounds",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Explain the region we are capturing.
|
||||||
|
if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region {
|
||||||
|
// Assuming regionck succeeded (*), we ought to always be
|
||||||
|
// capturing *some* region from the fn header, and hence it
|
||||||
|
// ought to be free. So under normal circumstances, we will go
|
||||||
|
// down this path which gives a decent human readable
|
||||||
|
// explanation.
|
||||||
|
//
|
||||||
|
// (*) if not, the `tainted_by_errors` flag would be set to
|
||||||
|
// true in any case, so we wouldn't be here at all.
|
||||||
|
note_and_explain_free_region(
|
||||||
|
tcx,
|
||||||
|
&mut err,
|
||||||
|
&format!("hidden type `{}` captures ", hidden_ty),
|
||||||
|
hidden_region,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Ugh. This is a painful case: the hidden region is not one
|
||||||
|
// that we can easily summarize or explain. This can happen
|
||||||
|
// in a case like
|
||||||
|
// `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
|
||||||
|
// if condition() { a } else { b }
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Here the captured lifetime is the intersection of `'a` and
|
||||||
|
// `'b`, which we can't quite express.
|
||||||
|
|
||||||
|
if let Some(region_scope_tree) = region_scope_tree {
|
||||||
|
// If the `region_scope_tree` is available, this is being
|
||||||
|
// invoked from the "region inferencer error". We can at
|
||||||
|
// least report a really cryptic error for now.
|
||||||
|
note_and_explain_region(
|
||||||
|
tcx,
|
||||||
|
region_scope_tree,
|
||||||
|
&mut err,
|
||||||
|
&format!("hidden type `{}` captures ", hidden_ty),
|
||||||
|
hidden_region,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// If the `region_scope_tree` is *unavailable*, this is
|
||||||
|
// being invoked by the code that comes *after* region
|
||||||
|
// inferencing. This is a bug, as the region inferencer
|
||||||
|
// ought to have noticed the failed constraint and invoked
|
||||||
|
// error reporting, which in turn should have prevented us
|
||||||
|
// from getting trying to infer the hidden type
|
||||||
|
// completely.
|
||||||
|
tcx.sess.delay_span_bug(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"hidden type captures unexpected lifetime `{:?}` \
|
||||||
|
but no region inference failure",
|
||||||
|
hidden_region,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
pub fn report_region_errors(
|
pub fn report_region_errors(
|
||||||
&self,
|
&self,
|
||||||
|
@ -410,7 +489,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
span,
|
span,
|
||||||
} => {
|
} => {
|
||||||
let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
|
let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
|
||||||
opaque_types::unexpected_hidden_region_diagnostic(
|
unexpected_hidden_region_diagnostic(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
Some(region_scope_tree),
|
Some(region_scope_tree),
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region};
|
use crate::infer::error_reporting::unexpected_hidden_region_diagnostic;
|
||||||
use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
|
use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use crate::traits::{self, PredicateObligation};
|
use crate::traits::{self, PredicateObligation};
|
||||||
use rustc::middle::region;
|
|
||||||
use rustc::session::config::nightly_options;
|
use rustc::session::config::nightly_options;
|
||||||
use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
|
use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
|
||||||
use rustc::ty::free_region_map::FreeRegionRelations;
|
use rustc::ty::free_region_map::FreeRegionRelations;
|
||||||
|
@ -9,7 +8,6 @@ use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
|
||||||
use rustc::ty::{self, GenericParamDefKind, Ty, TyCtxt};
|
use rustc::ty::{self, GenericParamDefKind, Ty, TyCtxt};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::{struct_span_err, DiagnosticBuilder};
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{DefId, DefIdMap};
|
use rustc_hir::def_id::{DefId, DefIdMap};
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
|
@ -618,86 +616,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unexpected_hidden_region_diagnostic(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
region_scope_tree: Option<®ion::ScopeTree>,
|
|
||||||
span: Span,
|
|
||||||
hidden_ty: Ty<'tcx>,
|
|
||||||
hidden_region: ty::Region<'tcx>,
|
|
||||||
) -> DiagnosticBuilder<'tcx> {
|
|
||||||
let mut err = struct_span_err!(
|
|
||||||
tcx.sess,
|
|
||||||
span,
|
|
||||||
E0700,
|
|
||||||
"hidden type for `impl Trait` captures lifetime that does not appear in bounds",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Explain the region we are capturing.
|
|
||||||
if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region {
|
|
||||||
// Assuming regionck succeeded (*), we ought to always be
|
|
||||||
// capturing *some* region from the fn header, and hence it
|
|
||||||
// ought to be free. So under normal circumstances, we will go
|
|
||||||
// down this path which gives a decent human readable
|
|
||||||
// explanation.
|
|
||||||
//
|
|
||||||
// (*) if not, the `tainted_by_errors` flag would be set to
|
|
||||||
// true in any case, so we wouldn't be here at all.
|
|
||||||
note_and_explain_free_region(
|
|
||||||
tcx,
|
|
||||||
&mut err,
|
|
||||||
&format!("hidden type `{}` captures ", hidden_ty),
|
|
||||||
hidden_region,
|
|
||||||
"",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Ugh. This is a painful case: the hidden region is not one
|
|
||||||
// that we can easily summarize or explain. This can happen
|
|
||||||
// in a case like
|
|
||||||
// `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
|
|
||||||
//
|
|
||||||
// ```
|
|
||||||
// fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
|
|
||||||
// if condition() { a } else { b }
|
|
||||||
// }
|
|
||||||
// ```
|
|
||||||
//
|
|
||||||
// Here the captured lifetime is the intersection of `'a` and
|
|
||||||
// `'b`, which we can't quite express.
|
|
||||||
|
|
||||||
if let Some(region_scope_tree) = region_scope_tree {
|
|
||||||
// If the `region_scope_tree` is available, this is being
|
|
||||||
// invoked from the "region inferencer error". We can at
|
|
||||||
// least report a really cryptic error for now.
|
|
||||||
note_and_explain_region(
|
|
||||||
tcx,
|
|
||||||
region_scope_tree,
|
|
||||||
&mut err,
|
|
||||||
&format!("hidden type `{}` captures ", hidden_ty),
|
|
||||||
hidden_region,
|
|
||||||
"",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// If the `region_scope_tree` is *unavailable*, this is
|
|
||||||
// being invoked by the code that comes *after* region
|
|
||||||
// inferencing. This is a bug, as the region inferencer
|
|
||||||
// ought to have noticed the failed constraint and invoked
|
|
||||||
// error reporting, which in turn should have prevented us
|
|
||||||
// from getting trying to infer the hidden type
|
|
||||||
// completely.
|
|
||||||
tcx.sess.delay_span_bug(
|
|
||||||
span,
|
|
||||||
&format!(
|
|
||||||
"hidden type captures unexpected lifetime `{:?}` \
|
|
||||||
but no region inference failure",
|
|
||||||
hidden_region,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visitor that requires that (almost) all regions in the type visited outlive
|
// Visitor that requires that (almost) all regions in the type visited outlive
|
||||||
// `least_region`. We cannot use `push_outlives_components` because regions in
|
// `least_region`. We cannot use `push_outlives_components` because regions in
|
||||||
// closure signatures are not included in their outlives components. We need to
|
// closure signatures are not included in their outlives components. We need to
|
||||||
|
|
|
@ -4,7 +4,8 @@ use rustc::mir::ConstraintCategory;
|
||||||
use rustc::ty::{self, RegionVid, Ty};
|
use rustc::ty::{self, RegionVid, Ty};
|
||||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||||
use rustc_infer::infer::{
|
use rustc_infer::infer::{
|
||||||
error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin,
|
error_reporting::nice_region_error::NiceRegionError,
|
||||||
|
error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin,
|
||||||
};
|
};
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -197,7 +198,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
|
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_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
|
||||||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||||
opaque_types::unexpected_hidden_region_diagnostic(
|
unexpected_hidden_region_diagnostic(
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
Some(region_scope_tree),
|
Some(region_scope_tree),
|
||||||
span,
|
span,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue