Move fallback_has_occurred to FnCtxt
This commit is contained in:
parent
e6fead46dc
commit
bc345d7bd0
21 changed files with 52 additions and 64 deletions
|
@ -299,7 +299,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
definition_ty
|
definition_ty
|
||||||
} else {
|
} else {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
self.tcx.ty_error()
|
self.tcx.ty_error()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -765,7 +765,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
|
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,7 +831,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
obligation.clone(),
|
obligation.clone(),
|
||||||
&obligation,
|
&obligation,
|
||||||
&e,
|
&e,
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -471,7 +471,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
}
|
}
|
||||||
match origin {
|
match origin {
|
||||||
// Checked when type checking the function containing them.
|
// Checked when type checking the function containing them.
|
||||||
|
|
|
@ -405,7 +405,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,7 +538,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
|
||||||
// RPITs.
|
// RPITs.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1431,7 +1431,7 @@ pub(crate) fn raw_compare_const_impl<'tcx>(
|
||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None, false));
|
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME return `ErrorReported` if region obligations error?
|
// FIXME return `ErrorReported` if region obligations error?
|
||||||
|
@ -1549,7 +1549,7 @@ fn compare_type_predicate_entailment<'tcx>(
|
||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1769,7 +1769,7 @@ pub fn check_type_bounds<'tcx>(
|
||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
||||||
f(&mut wfcx);
|
f(&mut wfcx);
|
||||||
let errors = wfcx.select_all_or_error();
|
let errors = wfcx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -321,7 +321,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, resolve all regions.
|
// Finally, resolve all regions.
|
||||||
|
@ -561,7 +561,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
|
||||||
predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]);
|
predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]);
|
||||||
let errors = traits::fully_solve_obligation(&infcx, predicate);
|
let errors = traits::fully_solve_obligation(&infcx, predicate);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, resolve all regions.
|
// Finally, resolve all regions.
|
||||||
|
|
|
@ -155,7 +155,7 @@ fn get_impl_substs<'tcx>(
|
||||||
|
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ fn require_same_types<'tcx>(
|
||||||
match &errors[..] {
|
match &errors[..] {
|
||||||
[] => true,
|
[] => true,
|
||||||
errors => {
|
errors => {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(errors, None);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,7 +336,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||||
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
|
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
// now we can take the return type of the given main function
|
// now we can take the return type of the given main function
|
||||||
|
|
|
@ -705,12 +705,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
|
|
||||||
// Object safety violations or miscellaneous.
|
// Object safety violations or miscellaneous.
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.err_ctxt().report_selection_error(
|
self.err_ctxt().report_selection_error(obligation.clone(), &obligation, &err);
|
||||||
obligation.clone(),
|
|
||||||
&obligation,
|
|
||||||
&err,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
// Treat this like an obligation and follow through
|
// Treat this like an obligation and follow through
|
||||||
// with the unsizing - the lack of a coercion should
|
// with the unsizing - the lack of a coercion should
|
||||||
// be silent, as it causes a type mismatch later.
|
// be silent, as it causes a type mismatch later.
|
||||||
|
|
|
@ -843,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
// Point any obligations that were registered due to opaque type
|
// Point any obligations that were registered due to opaque type
|
||||||
// inference at the return expression.
|
// inference at the return expression.
|
||||||
self.select_obligations_where_possible(false, |errors| {
|
self.select_obligations_where_possible(|errors| {
|
||||||
self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty);
|
self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2738,7 +2738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
Some((index_ty, element_ty)) => {
|
Some((index_ty, element_ty)) => {
|
||||||
// two-phase not needed because index_ty is never mutable
|
// two-phase not needed because index_ty is never mutable
|
||||||
self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
|
self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
|
||||||
self.select_obligations_where_possible(false, |errors| {
|
self.select_obligations_where_possible(|errors| {
|
||||||
self.point_at_index_if_possible(errors, idx.span)
|
self.point_at_index_if_possible(errors, idx.span)
|
||||||
});
|
});
|
||||||
element_ty
|
element_ty
|
||||||
|
|
|
@ -7,16 +7,16 @@ use rustc_data_structures::{
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
|
|
||||||
impl<'tcx> FnCtxt<'_, 'tcx> {
|
impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
/// Performs type inference fallback, returning true if any fallback
|
/// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred`
|
||||||
/// occurs.
|
/// if fallback has occurred.
|
||||||
pub(super) fn type_inference_fallback(&self) -> bool {
|
pub(super) fn type_inference_fallback(&self) {
|
||||||
debug!(
|
debug!(
|
||||||
"type-inference-fallback start obligations: {:#?}",
|
"type-inference-fallback start obligations: {:#?}",
|
||||||
self.fulfillment_cx.borrow_mut().pending_obligations()
|
self.fulfillment_cx.borrow_mut().pending_obligations()
|
||||||
);
|
);
|
||||||
|
|
||||||
// All type checking constraints were added, try to fallback unsolved variables.
|
// All type checking constraints were added, try to fallback unsolved variables.
|
||||||
self.select_obligations_where_possible(false, |_| {});
|
self.select_obligations_where_possible(|_| {});
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"type-inference-fallback post selection obligations: {:#?}",
|
"type-inference-fallback post selection obligations: {:#?}",
|
||||||
|
@ -26,18 +26,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
// Check if we have any unsolved variables. If not, no need for fallback.
|
// Check if we have any unsolved variables. If not, no need for fallback.
|
||||||
let unsolved_variables = self.unsolved_variables();
|
let unsolved_variables = self.unsolved_variables();
|
||||||
if unsolved_variables.is_empty() {
|
if unsolved_variables.is_empty() {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
|
let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
|
||||||
|
|
||||||
let mut fallback_has_occurred = false;
|
|
||||||
// We do fallback in two passes, to try to generate
|
// We do fallback in two passes, to try to generate
|
||||||
// better error messages.
|
// better error messages.
|
||||||
// The first time, we do *not* replace opaque types.
|
// The first time, we do *not* replace opaque types.
|
||||||
for ty in unsolved_variables {
|
for ty in unsolved_variables {
|
||||||
debug!("unsolved_variable = {:?}", ty);
|
debug!("unsolved_variable = {:?}", ty);
|
||||||
fallback_has_occurred |= self.fallback_if_possible(ty, &diverging_fallback);
|
self.fallback_if_possible(ty, &diverging_fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We now see if we can make progress. This might cause us to
|
// We now see if we can make progress. This might cause us to
|
||||||
|
@ -63,9 +62,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
// If we had tried to fallback the opaque inference variable to `MyType`,
|
// If we had tried to fallback the opaque inference variable to `MyType`,
|
||||||
// we will generate a confusing type-check error that does not explicitly
|
// we will generate a confusing type-check error that does not explicitly
|
||||||
// refer to opaque types.
|
// refer to opaque types.
|
||||||
self.select_obligations_where_possible(fallback_has_occurred, |_| {});
|
self.select_obligations_where_possible(|_| {});
|
||||||
|
|
||||||
fallback_has_occurred
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tries to apply a fallback to `ty` if it is an unsolved variable.
|
// Tries to apply a fallback to `ty` if it is an unsolved variable.
|
||||||
|
@ -81,12 +78,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
// Fallback becomes very dubious if we have encountered
|
// Fallback becomes very dubious if we have encountered
|
||||||
// type-checking errors. In that case, fallback to Error.
|
// type-checking errors. In that case, fallback to Error.
|
||||||
//
|
//
|
||||||
// The return value indicates whether fallback has occurred.
|
// Sets `FnCtxt::fallback_has_occurred` if fallback is performed
|
||||||
|
// during this call.
|
||||||
fn fallback_if_possible(
|
fn fallback_if_possible(
|
||||||
&self,
|
&self,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
|
diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||||
) -> bool {
|
) {
|
||||||
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
|
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
|
||||||
// is an unsolved variable, and we determine its fallback
|
// is an unsolved variable, and we determine its fallback
|
||||||
// based solely on how it was created, not what other type
|
// based solely on how it was created, not what other type
|
||||||
|
@ -111,7 +109,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
|
ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
|
||||||
_ => match diverging_fallback.get(&ty) {
|
_ => match diverging_fallback.get(&ty) {
|
||||||
Some(&fallback_ty) => fallback_ty,
|
Some(&fallback_ty) => fallback_ty,
|
||||||
None => return false,
|
None => return,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
|
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
|
||||||
|
@ -122,7 +120,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
.map(|origin| origin.span)
|
.map(|origin| origin.span)
|
||||||
.unwrap_or(rustc_span::DUMMY_SP);
|
.unwrap_or(rustc_span::DUMMY_SP);
|
||||||
self.demand_eqtype(span, ty, fallback);
|
self.demand_eqtype(span, ty, fallback);
|
||||||
true
|
self.fallback_has_occurred.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The "diverging fallback" system is rather complicated. This is
|
/// The "diverging fallback" system is rather complicated. This is
|
||||||
|
|
|
@ -106,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// possible. This can help substantially when there are
|
// possible. This can help substantially when there are
|
||||||
// indirect dependencies that don't seem worth tracking
|
// indirect dependencies that don't seem worth tracking
|
||||||
// precisely.
|
// precisely.
|
||||||
self.select_obligations_where_possible(false, mutate_fulfillment_errors);
|
self.select_obligations_where_possible(mutate_fulfillment_errors);
|
||||||
self.resolve_vars_if_possible(ty)
|
self.resolve_vars_if_possible(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
|
pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
|
||||||
let mut generators = self.deferred_generator_interiors.borrow_mut();
|
let mut generators = self.deferred_generator_interiors.borrow_mut();
|
||||||
for (body_id, interior, kind) in generators.drain(..) {
|
for (body_id, interior, kind) in generators.drain(..) {
|
||||||
self.select_obligations_where_possible(false, |_| {});
|
self.select_obligations_where_possible(|_| {});
|
||||||
crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind);
|
crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,25 +611,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
|
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
|
||||||
self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id, false);
|
self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Select as many obligations as we can at present.
|
/// Select as many obligations as we can at present.
|
||||||
pub(in super::super) fn select_obligations_where_possible(
|
pub(in super::super) fn select_obligations_where_possible(
|
||||||
&self,
|
&self,
|
||||||
fallback_has_occurred: bool,
|
|
||||||
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
|
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
|
||||||
) {
|
) {
|
||||||
let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
|
let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
mutate_fulfillment_errors(&mut result);
|
mutate_fulfillment_errors(&mut result);
|
||||||
self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
|
self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
|
||||||
self.err_ctxt().report_fulfillment_errors(
|
self.err_ctxt().report_fulfillment_errors(&result, self.inh.body_id);
|
||||||
&result,
|
|
||||||
self.inh.body_id,
|
|
||||||
fallback_has_occurred,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -344,7 +344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// an "opportunistic" trait resolution of any trait bounds on
|
// an "opportunistic" trait resolution of any trait bounds on
|
||||||
// the call. This helps coercions.
|
// the call. This helps coercions.
|
||||||
if check_closures {
|
if check_closures {
|
||||||
self.select_obligations_where_possible(false, |_| {})
|
self.select_obligations_where_possible(|_| {})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check each argument, to satisfy the input it was provided for
|
// Check each argument, to satisfy the input it was provided for
|
||||||
|
|
|
@ -115,6 +115,8 @@ pub struct FnCtxt<'a, 'tcx> {
|
||||||
pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
|
pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
|
||||||
|
|
||||||
pub(super) inh: &'a Inherited<'tcx>,
|
pub(super) inh: &'a Inherited<'tcx>,
|
||||||
|
|
||||||
|
pub(super) fallback_has_occurred: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
@ -138,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
by_id: Default::default(),
|
by_id: Default::default(),
|
||||||
}),
|
}),
|
||||||
inh,
|
inh,
|
||||||
|
fallback_has_occurred: Cell::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +162,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
///
|
///
|
||||||
/// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt
|
/// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt
|
||||||
pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
|
pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
|
||||||
TypeErrCtxt { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()) }
|
TypeErrCtxt {
|
||||||
|
infcx: &self.infcx,
|
||||||
|
typeck_results: Some(self.typeck_results.borrow()),
|
||||||
|
fallback_has_occurred: self.fallback_has_occurred.get(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn errors_reported_since_creation(&self) -> bool {
|
pub fn errors_reported_since_creation(&self) -> bool {
|
||||||
|
|
|
@ -316,12 +316,12 @@ fn typeck_with_fallback<'tcx>(
|
||||||
fcx
|
fcx
|
||||||
};
|
};
|
||||||
|
|
||||||
let fallback_has_occurred = fcx.type_inference_fallback();
|
fcx.type_inference_fallback();
|
||||||
|
|
||||||
// Even though coercion casts provide type hints, we check casts after fallback for
|
// Even though coercion casts provide type hints, we check casts after fallback for
|
||||||
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
|
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
|
||||||
fcx.check_casts();
|
fcx.check_casts();
|
||||||
fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
|
fcx.select_obligations_where_possible(|_| {});
|
||||||
|
|
||||||
// Closure and generator analysis may run after fallback
|
// Closure and generator analysis may run after fallback
|
||||||
// because they don't constrain other type variables.
|
// because they don't constrain other type variables.
|
||||||
|
|
|
@ -772,7 +772,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
match (method, trait_did) {
|
match (method, trait_did) {
|
||||||
(Some(ok), _) => {
|
(Some(ok), _) => {
|
||||||
let method = self.register_infer_ok_obligations(ok);
|
let method = self.register_infer_ok_obligations(ok);
|
||||||
self.select_obligations_where_possible(false, |_| {});
|
self.select_obligations_where_possible(|_| {});
|
||||||
Ok(method)
|
Ok(method)
|
||||||
}
|
}
|
||||||
(None, None) => Err(vec![]),
|
(None, None) => Err(vec![]),
|
||||||
|
|
|
@ -91,6 +91,7 @@ pub mod nice_region_error;
|
||||||
pub struct TypeErrCtxt<'a, 'tcx> {
|
pub struct TypeErrCtxt<'a, 'tcx> {
|
||||||
pub infcx: &'a InferCtxt<'tcx>,
|
pub infcx: &'a InferCtxt<'tcx>,
|
||||||
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
|
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
|
||||||
|
pub fallback_has_occurred: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeErrCtxt<'_, '_> {
|
impl TypeErrCtxt<'_, '_> {
|
||||||
|
|
|
@ -677,9 +677,9 @@ pub struct CombinedSnapshot<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> InferCtxt<'tcx> {
|
impl<'tcx> InferCtxt<'tcx> {
|
||||||
/// Creates a `TypeErrCtxt` for emitting various inference errors.
|
/// Creates a `TypeErrCtxt` for emitting various inference errors.
|
||||||
/// During typeck, use `FnCtxt::infer_err` instead.
|
/// During typeck, use `FnCtxt::err_ctxt` instead.
|
||||||
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
|
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
|
||||||
TypeErrCtxt { infcx: self, typeck_results: None }
|
TypeErrCtxt { infcx: self, typeck_results: None, fallback_has_occurred: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// calls `tcx.try_unify_abstract_consts` after
|
/// calls `tcx.try_unify_abstract_consts` after
|
||||||
|
|
|
@ -101,7 +101,6 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
errors: &[FulfillmentError<'tcx>],
|
errors: &[FulfillmentError<'tcx>],
|
||||||
body_id: Option<hir::BodyId>,
|
body_id: Option<hir::BodyId>,
|
||||||
fallback_has_occurred: bool,
|
|
||||||
) -> ErrorGuaranteed;
|
) -> ErrorGuaranteed;
|
||||||
|
|
||||||
fn report_overflow_error<T>(
|
fn report_overflow_error<T>(
|
||||||
|
@ -124,7 +123,6 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||||
obligation: PredicateObligation<'tcx>,
|
obligation: PredicateObligation<'tcx>,
|
||||||
root_obligation: &PredicateObligation<'tcx>,
|
root_obligation: &PredicateObligation<'tcx>,
|
||||||
error: &SelectionError<'tcx>,
|
error: &SelectionError<'tcx>,
|
||||||
fallback_has_occurred: bool,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +373,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
errors: &[FulfillmentError<'tcx>],
|
errors: &[FulfillmentError<'tcx>],
|
||||||
body_id: Option<hir::BodyId>,
|
body_id: Option<hir::BodyId>,
|
||||||
fallback_has_occurred: bool,
|
|
||||||
) -> ErrorGuaranteed {
|
) -> ErrorGuaranteed {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ErrorDescriptor<'tcx> {
|
struct ErrorDescriptor<'tcx> {
|
||||||
|
@ -452,7 +449,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
|
|
||||||
for (error, suppressed) in iter::zip(errors, is_suppressed) {
|
for (error, suppressed) in iter::zip(errors, is_suppressed) {
|
||||||
if !suppressed {
|
if !suppressed {
|
||||||
self.report_fulfillment_error(error, body_id, fallback_has_occurred);
|
self.report_fulfillment_error(error, body_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +531,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
mut obligation: PredicateObligation<'tcx>,
|
mut obligation: PredicateObligation<'tcx>,
|
||||||
root_obligation: &PredicateObligation<'tcx>,
|
root_obligation: &PredicateObligation<'tcx>,
|
||||||
error: &SelectionError<'tcx>,
|
error: &SelectionError<'tcx>,
|
||||||
fallback_has_occurred: bool,
|
|
||||||
) {
|
) {
|
||||||
self.set_tainted_by_errors();
|
self.set_tainted_by_errors();
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
@ -1000,7 +996,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
// variable that used to fallback to `()` now falling back to `!`. Issue a
|
// variable that used to fallback to `()` now falling back to `!`. Issue a
|
||||||
// note informing about the change in behaviour.
|
// note informing about the change in behaviour.
|
||||||
if trait_predicate.skip_binder().self_ty().is_never()
|
if trait_predicate.skip_binder().self_ty().is_never()
|
||||||
&& fallback_has_occurred
|
&& self.fallback_has_occurred
|
||||||
{
|
{
|
||||||
let predicate = trait_predicate.map_bound(|mut trait_pred| {
|
let predicate = trait_predicate.map_bound(|mut trait_pred| {
|
||||||
trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
|
trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
|
||||||
|
@ -1366,7 +1362,6 @@ trait InferCtxtPrivExt<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
error: &FulfillmentError<'tcx>,
|
error: &FulfillmentError<'tcx>,
|
||||||
body_id: Option<hir::BodyId>,
|
body_id: Option<hir::BodyId>,
|
||||||
fallback_has_occurred: bool,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
fn report_projection_error(
|
fn report_projection_error(
|
||||||
|
@ -1516,7 +1511,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
error: &FulfillmentError<'tcx>,
|
error: &FulfillmentError<'tcx>,
|
||||||
body_id: Option<hir::BodyId>,
|
body_id: Option<hir::BodyId>,
|
||||||
fallback_has_occurred: bool,
|
|
||||||
) {
|
) {
|
||||||
match error.code {
|
match error.code {
|
||||||
FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
|
FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
|
||||||
|
@ -1524,7 +1518,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
error.obligation.clone(),
|
error.obligation.clone(),
|
||||||
&error.root_obligation,
|
&error.root_obligation,
|
||||||
selection_error,
|
selection_error,
|
||||||
fallback_has_occurred,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
FulfillmentErrorCode::CodeProjectionError(ref e) => {
|
FulfillmentErrorCode::CodeProjectionError(ref e) => {
|
||||||
|
|
|
@ -70,7 +70,7 @@ pub fn can_type_implement_copy<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(errors) => {
|
Err(errors) => {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,7 @@ fn do_normalize_predicates<'tcx>(
|
||||||
let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
|
let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
|
||||||
Ok(predicates) => predicates,
|
Ok(predicates) => predicates,
|
||||||
Err(errors) => {
|
Err(errors) => {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue