Move fallback_has_occurred to FnCtxt

This commit is contained in:
Michael Goulet 2022-11-02 01:34:17 +00:00
parent e6fead46dc
commit bc345d7bd0
21 changed files with 52 additions and 64 deletions

View file

@ -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()
} }
} }

View file

@ -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,
); );
} }

View file

@ -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.

View file

@ -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);
} }

View file

@ -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;
} }

View file

@ -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.

View file

@ -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;
} }

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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,
);
} }
} }

View file

@ -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

View file

@ -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 {

View file

@ -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.

View file

@ -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![]),

View file

@ -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<'_, '_> {

View file

@ -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

View file

@ -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) => {

View file

@ -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);
} }
}; };
} }

View file

@ -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);
} }
}; };