From f1126f1272d21a5bee1694b5e9bb5f3cf19629d1 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 8 Nov 2021 23:35:23 +0800 Subject: [PATCH] Make select_* methods return Vec for TraitEngine --- .../src/diagnostics/bound_region_errors.rs | 2 +- .../src/transform/check_consts/check.rs | 5 ++- .../src/infer/canonical/query_response.rs | 4 +- compiler/rustc_infer/src/traits/engine.rs | 8 ++-- .../rustc_trait_selection/src/autoderef.rs | 5 ++- .../src/traits/auto_trait.rs | 8 ++-- .../src/traits/chalk_fulfill.rs | 40 ++++++++++--------- .../src/traits/codegen.rs | 3 +- .../src/traits/fulfill.rs | 36 ++++++++++------- .../rustc_trait_selection/src/traits/mod.rs | 23 ++++++----- .../src/traits/query/type_op/custom.rs | 5 ++- .../src/traits/specialize/mod.rs | 25 ++++++------ .../src/traits/structural_match.rs | 2 +- .../src/implied_outlives_bounds.rs | 6 +-- compiler/rustc_typeck/src/check/check.rs | 5 ++- compiler/rustc_typeck/src/check/coercion.rs | 2 +- .../rustc_typeck/src/check/compare_method.rs | 22 +++++----- compiler/rustc_typeck/src/check/dropck.rs | 5 ++- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 24 ++++++----- compiler/rustc_typeck/src/check/op.rs | 5 +-- .../rustc_typeck/src/coherence/builtin.rs | 6 ++- compiler/rustc_typeck/src/hir_wf_check.rs | 3 +- compiler/rustc_typeck/src/lib.rs | 13 +++--- .../src/outlives/outlives_bounds.rs | 3 +- .../clippy_lints/src/future_not_send.rs | 4 +- 25 files changed, 147 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 15309ccd8df..1bc9f8cf3cc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -339,7 +339,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( // We generally shouldn't have errors here because the query was // already run, but there's no point using `delay_span_bug` // when we're going to emit an error here anyway. - let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new); + let _errors = fulfill_cx.select_all_or_error(infcx); let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| { debug!("{:#?}", region_constraints); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 3785c170f6b..61fd828a430 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1054,8 +1054,9 @@ fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) let mut fulfillment_cx = traits::FulfillmentContext::new(); let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span)); fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause); - if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err, None, false); + let errors = fulfillment_cx.select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); } }); } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 2296cc6129a..5b4a9d9dfad 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -108,7 +108,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let tcx = self.tcx; // Select everything, returning errors. - let true_errors = fulfill_cx.select_where_possible(self).err().unwrap_or_else(Vec::new); + let true_errors = fulfill_cx.select_where_possible(self); debug!("true_errors = {:#?}", true_errors); if !true_errors.is_empty() { @@ -118,7 +118,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { } // Anything left unselected *now* must be an ambiguity. - let ambig_errors = fulfill_cx.select_all_or_error(self).err().unwrap_or_else(Vec::new); + let ambig_errors = fulfill_cx.select_all_or_error(self); debug!("ambig_errors = {:#?}", ambig_errors); let region_obligations = self.take_registered_region_obligations(); diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index dce4a87b041..06d38e79527 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -49,27 +49,27 @@ pub trait TraitEngine<'tcx>: 'tcx { fn select_all_or_error( &mut self, infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>>; + ) -> Vec>; fn select_all_with_constness_or_error( &mut self, infcx: &InferCtxt<'_, 'tcx>, _constness: hir::Constness, - ) -> Result<(), Vec>> { + ) -> Vec> { self.select_all_or_error(infcx) } fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>>; + ) -> Vec>; // FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated fn select_with_constness_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, _constness: hir::Constness, - ) -> Result<(), Vec>> { + ) -> Vec> { self.select_where_possible(infcx) } diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 53afe4ca068..4c80483fc1f 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -152,11 +152,12 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { }, cause, ); - if let Err(e) = fulfillcx.select_where_possible(&self.infcx) { + let errors = fulfillcx.select_where_possible(&self.infcx); + if !errors.is_empty() { // This shouldn't happen, except for evaluate/fulfill mismatches, // but that's not a reason for an ICE (`predicate_may_hold` is conservative // by design). - debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e); + debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors); return None; } let obligations = fulfillcx.pending_obligations(); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 6452b520452..4469b2e6055 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -187,9 +187,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { // an additional sanity check. let mut fulfill = FulfillmentContext::new(); fulfill.register_bound(&infcx, full_env, ty, trait_did, ObligationCause::dummy()); - fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| { - panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e) - }); + let errors = fulfill.select_all_or_error(&infcx); + + if !errors.is_empty() { + panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors); + } let body_id_map: FxHashMap<_, _> = infcx .inner diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index ec62ee40068..eed7280ceaf 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -52,31 +52,33 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { fn select_all_or_error( &mut self, infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { - self.select_where_possible(infcx)?; + ) -> Vec> { + { + let errors = self.select_where_possible(infcx); - if self.obligations.is_empty() { - Ok(()) - } else { - let errors = self - .obligations - .iter() - .map(|obligation| FulfillmentError { - obligation: obligation.clone(), - code: FulfillmentErrorCode::CodeAmbiguity, - // FIXME - does Chalk have a notation of 'root obligation'? - // This is just for diagnostics, so it's okay if this is wrong - root_obligation: obligation.clone(), - }) - .collect(); - Err(errors) + if !errors.is_empty() { + return errors; + } } + + // any remaining obligations are errors + self + .obligations + .iter() + .map(|obligation| FulfillmentError { + obligation: obligation.clone(), + code: FulfillmentErrorCode::CodeAmbiguity, + // FIXME - does Chalk have a notation of 'root obligation'? + // This is just for diagnostics, so it's okay if this is wrong + root_obligation: obligation.clone(), + }) + .collect() } fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { + ) -> Vec> { assert!(!infcx.is_in_snapshot()); let mut errors = Vec::new(); @@ -147,7 +149,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { } } - if errors.is_empty() { Ok(()) } else { Err(errors) } + errors } fn pending_obligations(&self) -> Vec> { diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index f06f0e32f41..bdd4fdd4043 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -120,7 +120,8 @@ where // In principle, we only need to do this so long as `result` // contains unbound type parameters. It could be a slight // optimization to stop iterating early. - if let Err(errors) = fulfill_cx.select_all_or_error(infcx) { + let errors = fulfill_cx.select_all_or_error(infcx); + if !errors.is_empty() { infcx.tcx.sess.delay_span_bug( rustc_span::DUMMY_SP, &format!("Encountered errors `{:?}` resolving bounds after type-checking", errors), diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 465d1465d5d..ebac19b923d 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -129,7 +129,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { fn select( &mut self, selcx: &mut SelectionContext<'a, 'tcx>, - ) -> Result<(), Vec>> { + ) -> Vec> { let span = debug_span!("select", obligation_forest_size = ?self.predicates.len()); let _enter = span.enter(); @@ -163,7 +163,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { errors.len() ); - if errors.is_empty() { Ok(()) } else { Err(errors) } + errors } } @@ -226,38 +226,46 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { fn select_all_or_error( &mut self, infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { - self.select_where_possible(infcx)?; + ) -> Vec> { + { + let errors = self.select_where_possible(infcx); + if !errors.is_empty() { + return errors; + } + } - let errors: Vec<_> = self + self .predicates .to_errors(CodeAmbiguity) .into_iter() .map(to_fulfillment_error) - .collect(); - if errors.is_empty() { Ok(()) } else { Err(errors) } + .collect() } fn select_all_with_constness_or_error( &mut self, infcx: &InferCtxt<'_, 'tcx>, constness: rustc_hir::Constness, - ) -> Result<(), Vec>> { - self.select_with_constness_where_possible(infcx, constness)?; + ) -> Vec> { + { + let errors = self.select_with_constness_where_possible(infcx, constness); + if !errors.is_empty() { + return errors; + } + } - let errors: Vec<_> = self + self .predicates .to_errors(CodeAmbiguity) .into_iter() .map(to_fulfillment_error) - .collect(); - if errors.is_empty() { Ok(()) } else { Err(errors) } + .collect() } fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { + ) -> Vec> { let mut selcx = SelectionContext::new(infcx); self.select(&mut selcx) } @@ -266,7 +274,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { &mut self, infcx: &InferCtxt<'_, 'tcx>, constness: hir::Constness, - ) -> Result<(), Vec>> { + ) -> Vec> { let mut selcx = SelectionContext::with_constness(infcx, constness); self.select(&mut selcx) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 8f247184e88..d4a586b0124 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -180,8 +180,8 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( // Note: we only assume something is `Copy` if we can // *definitively* show that it implements `Copy`. Otherwise, // assume it is move; linear is always ok. - match fulfill_cx.select_all_or_error(infcx) { - Ok(()) => { + match fulfill_cx.select_all_or_error(infcx).as_slice() { + [] => { debug!( "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", ty, @@ -189,12 +189,12 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( ); true } - Err(e) => { + errors => { debug!( - "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}", - ty, - infcx.tcx.def_path_str(def_id), - e + ?ty, + bound = %infcx.tcx.def_path_str(def_id), + ?errors, + "type_known_to_meet_bound_modulo_regions" ); false } @@ -410,7 +410,10 @@ where } debug!("fully_normalize: select_all_or_error start"); - fulfill_cx.select_all_or_error(infcx)?; + let errors = fulfill_cx.select_all_or_error(infcx); + if !errors.is_empty() { + return Err(errors); + } debug!("fully_normalize: select_all_or_error complete"); let resolved_value = infcx.resolve_vars_if_possible(normalized_value); debug!("fully_normalize: resolved_value={:?}", resolved_value); @@ -441,7 +444,9 @@ pub fn impossible_predicates<'tcx>( fulfill_cx.register_predicate_obligation(&infcx, obligation); } - fulfill_cx.select_all_or_error(&infcx).is_err() + let errors = fulfill_cx.select_all_or_error(&infcx); + + !errors.is_empty() }); debug!("impossible_predicates = {:?}", result); result diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index b5398f8a435..da891b35571 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -77,10 +77,11 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?; debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id)); fulfill_cx.register_predicate_obligations(infcx, obligations); - if let Err(e) = fulfill_cx.select_all_or_error(infcx) { + let errors = fulfill_cx.select_all_or_error(infcx); + if !errors.is_empty() { infcx.tcx.sess.diagnostic().delay_span_bug( DUMMY_SP, - &format!("errors selecting obligation during MIR typeck: {:?}", e), + &format!("errors selecting obligation during MIR typeck: {:?}", errors), ); } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index f9867f0671e..f81a74a67dc 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -225,8 +225,18 @@ fn fulfill_implication<'a, 'tcx>( for oblig in obligations.chain(more_obligations) { fulfill_cx.register_predicate_obligation(&infcx, oblig); } - match fulfill_cx.select_all_or_error(infcx) { - Err(errors) => { + match fulfill_cx.select_all_or_error(infcx).as_slice() { + [] => { + debug!( + "fulfill_implication: an impl for {:?} specializes {:?}", + source_trait_ref, target_trait_ref + ); + + // Now resolve the *substitution* we built for the target earlier, replacing + // the inference variables inside with whatever we got from fulfillment. + Ok(infcx.resolve_vars_if_possible(target_substs)) + } + errors => { // no dice! debug!( "fulfill_implication: for impls on {:?} and {:?}, \ @@ -238,17 +248,6 @@ fn fulfill_implication<'a, 'tcx>( ); Err(()) } - - Ok(()) => { - debug!( - "fulfill_implication: an impl for {:?} specializes {:?}", - source_trait_ref, target_trait_ref - ); - - // Now resolve the *substitution* we built for the target earlier, replacing - // the inference variables inside with whatever we got from fulfillment. - Ok(infcx.resolve_vars_if_possible(target_substs)) - } } }) } diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index a398e847b93..3d713822278 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -103,7 +103,7 @@ fn type_marked_structural( // // 2. We are sometimes doing future-incompatibility lints for // now, so we do not want unconditional errors here. - fulfillment_cx.select_all_or_error(infcx).is_ok() + fulfillment_cx.select_all_or_error(infcx).is_empty() } /// This implements the traversal over the structure of a given type to try to diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 37e00733737..92f2760e62c 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -128,9 +128,9 @@ fn compute_implied_outlives_bounds<'tcx>( // Ensure that those obligations that we had to solve // get solved *here*. - match fulfill_cx.select_all_or_error(infcx) { - Ok(()) => Ok(implied_bounds), - Err(_) => Err(NoSolution), + match fulfill_cx.select_all_or_error(infcx).as_slice() { + [] => Ok(implied_bounds), + _ => Err(NoSolution), } } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 5040c4db951..909fdf63f3e 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -663,8 +663,9 @@ fn check_opaque_meets_bounds<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); } // Finally, resolve all regions. This catches wily misuses of diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index ad65a0ba62a..28712e06582 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -950,7 +950,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut fcx = traits::FulfillmentContext::new_in_snapshot(); fcx.register_predicate_obligations(self, ok.obligations); - fcx.select_where_possible(&self).is_ok() + fcx.select_where_possible(&self).is_empty() }) } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 7c262dcf723..b965b3cb56d 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -391,8 +391,9 @@ fn compare_predicate_entailment<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); } @@ -1094,8 +1095,9 @@ crate fn compare_const_impl<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); return; } @@ -1210,8 +1212,9 @@ fn compare_type_predicate_entailment<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); } @@ -1427,10 +1430,9 @@ pub fn check_type_bounds<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - if let Err(ref errors) = - inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness) - { - infcx.report_fulfillment_errors(errors, None, false); + let errors = inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); } diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index fd150978f00..bfa0d92ab47 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -113,9 +113,10 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( } } - if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) { + let errors = fulfillment_cx.select_all_or_error(&infcx); + if !errors.is_empty() { // this could be reached when we get lazy normalization - infcx.report_fulfillment_errors(errors, None, false); + infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 5308126f252..a86c16ef6df 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -642,11 +642,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub(in super::super) fn select_all_obligations_or_error(&self) { - if let Err(errors) = self + let errors =self .fulfillment_cx .borrow_mut() - .select_all_with_constness_or_error(&self, self.inh.constness) - { + .select_all_with_constness_or_error(&self, self.inh.constness); + + if !errors.is_empty() { self.report_fulfillment_errors(&errors, self.inh.body_id, false); } } @@ -657,13 +658,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fallback_has_occurred: bool, mutate_fulfillment_errors: impl Fn(&mut Vec>), ) { - let result = self + let mut result = self .fulfillment_cx .borrow_mut() .select_with_constness_where_possible(self, self.inh.constness); - if let Err(mut errors) = result { - mutate_fulfillment_errors(&mut errors); - self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred); + if !result.is_empty() { + mutate_fulfillment_errors(&mut result); + self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred); } } @@ -793,14 +794,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we can. We don't care if some things turn // out unconstrained or ambiguous, as we're // just trying to get hints here. - self.save_and_restore_in_snapshot_flag(|_| { + let errors = self.save_and_restore_in_snapshot_flag(|_| { let mut fulfill = >::new(self.tcx); for obligation in ok.obligations { fulfill.register_predicate_obligation(self, obligation); } fulfill.select_where_possible(self) - }) - .map_err(|_| ())?; + }); + + if !errors.is_empty() { + return Err(()); + } } Err(_) => return Err(()), } diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index dd094745331..9c53a1d4eb6 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -826,10 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.obligation_for_method(span, trait_did, lhs_ty, Some(other_tys)); let mut fulfill = >::new(self.tcx); fulfill.register_predicate_obligation(self, obligation); - Err(match fulfill.select_where_possible(&self.infcx) { - Err(errors) => errors, - _ => vec![], - }) + Err(fulfill.select_where_possible(&self.infcx)) } } } diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 8cae61e8c22..289985a4717 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -263,7 +263,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } // Check that all transitive obligations are satisfied. - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { + let errors = fulfill_cx.select_all_or_error(&infcx); + if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); } @@ -522,7 +523,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI fulfill_cx.register_predicate_obligation(&infcx, predicate); // Check that all transitive obligations are satisfied. - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { + let errors = fulfill_cx.select_all_or_error(&infcx); + if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); } diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs index 39bcf899932..a49eda6572d 100644 --- a/compiler/rustc_typeck/src/hir_wf_check.rs +++ b/compiler/rustc_typeck/src/hir_wf_check.rs @@ -88,7 +88,8 @@ fn diagnostic_hir_wf_check<'tcx>( ), ); - if let Err(errors) = fulfill.select_all_or_error(&infcx) { + let errors = fulfill.select_all_or_error(&infcx); + if !errors.is_empty() { tracing::debug!("Wf-check got errors for {:?}: {:?}", ty, errors); for error in errors { if error.obligation.predicate == self.predicate { diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index f90cfb88491..ba0fd12a275 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -157,10 +157,10 @@ fn require_same_types<'tcx>( } } - match fulfill_cx.select_all_or_error(infcx) { - Ok(()) => true, - Err(errors) => { - infcx.report_fulfillment_errors(&errors, None, false); + match fulfill_cx.select_all_or_error(infcx).as_slice() { + [] => true, + errors => { + infcx.report_fulfillment_errors(errors, None, false); false } } @@ -352,8 +352,9 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { term_id, cause, ); - if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err, None, false); + let errors = fulfillment_cx.select_all_or_error(&infcx); + if !errors.is_empty() { + infcx.report_fulfillment_errors(&errors, None, false); error = true; } }); diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs index 4ab5fe26abe..91727d57ddf 100644 --- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs +++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs @@ -83,7 +83,8 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { // variables. Process these constraints. let mut fulfill_cx = FulfillmentContext::new(); fulfill_cx.register_predicate_obligations(self, result.obligations); - if fulfill_cx.select_all_or_error(self).is_err() { + let errors = fulfill_cx.select_all_or_error(self); + if !errors.is_empty() { self.tcx.sess.delay_span_bug( span, "implied_outlives_bounds failed to solve obligations from instantiation", diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index e18442515b8..6b2ac985555 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -77,13 +77,13 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { if is_future { let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap(); let span = decl.output.span(); - let send_result = cx.tcx.infer_ctxt().enter(|infcx| { + let send_errors = cx.tcx.infer_ctxt().enter(|infcx| { let cause = traits::ObligationCause::misc(span, hir_id); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_bound(&infcx, cx.param_env, ret_ty, send_trait, cause); fulfillment_cx.select_all_or_error(&infcx) }); - if let Err(send_errors) = send_result { + if !send_errors.is_empty() { span_lint_and_then( cx, FUTURE_NOT_SEND,