mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-14 16:03:17 +00:00
Auto merge of #90700 - fee1-dead:select-returns-vec, r=davidtwco
Make `select_*` methods return `Vec` for `TraitEngine` This reduces some complexity as an empty vec means no errors and non-empty vec means errors occurred.
This commit is contained in:
commit
eee8b9c7ba
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -46,30 +46,25 @@ pub trait TraitEngine<'tcx>: 'tcx {
|
||||
obligation: PredicateObligation<'tcx>,
|
||||
);
|
||||
|
||||
fn select_all_or_error(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
|
||||
fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
||||
|
||||
fn select_all_with_constness_or_error(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
_constness: hir::Constness,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
self.select_all_or_error(infcx)
|
||||
}
|
||||
|
||||
fn select_where_possible(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
|
||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>)
|
||||
-> Vec<FulfillmentError<'tcx>>;
|
||||
|
||||
// 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<FulfillmentError<'tcx>>> {
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
self.select_where_possible(infcx)
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -49,34 +49,32 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||
self.obligations.insert(obligation);
|
||||
}
|
||||
|
||||
fn select_all_or_error(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
self.select_where_possible(infcx)?;
|
||||
fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
||||
{
|
||||
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<FulfillmentError<'tcx>>> {
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
assert!(!infcx.is_in_snapshot());
|
||||
|
||||
let mut errors = Vec::new();
|
||||
@ -147,7 +145,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
if errors.is_empty() { Ok(()) } else { Err(errors) }
|
||||
errors
|
||||
}
|
||||
|
||||
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
|
||||
|
@ -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),
|
||||
|
@ -126,10 +126,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||
}
|
||||
|
||||
/// Attempts to select obligations using `selcx`.
|
||||
fn select(
|
||||
&mut self,
|
||||
selcx: &mut SelectionContext<'a, 'tcx>,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
||||
let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
|
||||
let _enter = span.enter();
|
||||
|
||||
@ -163,7 +160,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||
errors.len()
|
||||
);
|
||||
|
||||
if errors.is_empty() { Ok(()) } else { Err(errors) }
|
||||
errors
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,41 +220,36 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
|
||||
}
|
||||
|
||||
fn select_all_or_error(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
self.select_where_possible(infcx)?;
|
||||
fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
||||
{
|
||||
let errors = self.select_where_possible(infcx);
|
||||
if !errors.is_empty() {
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
let errors: Vec<_> = self
|
||||
.predicates
|
||||
.to_errors(CodeAmbiguity)
|
||||
.into_iter()
|
||||
.map(to_fulfillment_error)
|
||||
.collect();
|
||||
if errors.is_empty() { Ok(()) } else { Err(errors) }
|
||||
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
|
||||
}
|
||||
|
||||
fn select_all_with_constness_or_error(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
constness: rustc_hir::Constness,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
self.select_with_constness_where_possible(infcx, constness)?;
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
{
|
||||
let errors = self.select_with_constness_where_possible(infcx, constness);
|
||||
if !errors.is_empty() {
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
let errors: Vec<_> = self
|
||||
.predicates
|
||||
.to_errors(CodeAmbiguity)
|
||||
.into_iter()
|
||||
.map(to_fulfillment_error)
|
||||
.collect();
|
||||
if errors.is_empty() { Ok(()) } else { Err(errors) }
|
||||
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
|
||||
}
|
||||
|
||||
fn select_where_possible(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
let mut selcx = SelectionContext::new(infcx);
|
||||
self.select(&mut selcx)
|
||||
}
|
||||
@ -266,7 +258,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
constness: hir::Constness,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
let mut selcx = SelectionContext::with_constness(infcx, constness);
|
||||
self.select(&mut selcx)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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,10 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<traits::FulfillmentError<'tcx>>),
|
||||
) {
|
||||
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 = <dyn TraitEngine<'_>>::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(()),
|
||||
}
|
||||
|
@ -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 = <dyn TraitEngine<'_>>::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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
});
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user