Remove unnecessary call to select_from_obligation

The only regression is one ambiguity in the new trait solver, having to
do with two param-env candidates that may apply. I think this is fine,
since the error message already kinda sucks.
This commit is contained in:
Michael Goulet 2023-06-20 20:00:39 +00:00
parent 46514218f6
commit db235a07f7
2 changed files with 35 additions and 49 deletions

View File

@ -5,7 +5,7 @@ pub mod suggestions;
use super::{
FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, ObligationCause,
ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
PredicateObligation, SelectionError, TraitNotObjectSafe,
};
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@ -2269,55 +2269,40 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
)
};
let obligation = obligation.with(self.tcx, trait_ref);
let mut selcx = SelectionContext::new(&self);
match selcx.select_from_obligation(&obligation) {
Ok(None) => {
let ambiguities =
ambiguity::recompute_applicable_impls(self.infcx, &obligation);
let has_non_region_infer = trait_ref
.skip_binder()
.substs
.types()
.any(|t| !t.is_ty_or_numeric_infer());
// It doesn't make sense to talk about applicable impls if there are more
// than a handful of them.
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
if self.tainted_by_errors().is_some() && subst.is_none() {
// If `subst.is_none()`, then this is probably two param-env
// candidates or impl candidates that are equal modulo lifetimes.
// Therefore, if we've already emitted an error, just skip this
// one, since it's not particularly actionable.
err.cancel();
return;
}
self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
} else {
if self.tainted_by_errors().is_some() {
err.cancel();
return;
}
err.note(format!("cannot satisfy `{}`", predicate));
let impl_candidates = self.find_similar_impl_candidates(
predicate.to_opt_poly_trait_pred().unwrap(),
);
if impl_candidates.len() < 10 {
self.report_similar_impl_candidates(
impl_candidates.as_slice(),
trait_ref,
obligation.cause.body_id,
&mut err,
false,
);
}
}
let ambiguities = ambiguity::recompute_applicable_impls(
self.infcx,
&obligation.with(self.tcx, trait_ref),
);
let has_non_region_infer =
trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_or_numeric_infer());
// It doesn't make sense to talk about applicable impls if there are more
// than a handful of them.
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
if self.tainted_by_errors().is_some() && subst.is_none() {
// If `subst.is_none()`, then this is probably two param-env
// candidates or impl candidates that are equal modulo lifetimes.
// Therefore, if we've already emitted an error, just skip this
// one, since it's not particularly actionable.
err.cancel();
return;
}
_ => {
if self.tainted_by_errors().is_some() {
err.cancel();
return;
}
err.note(format!("cannot satisfy `{}`", predicate));
self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
} else {
if self.tainted_by_errors().is_some() {
err.cancel();
return;
}
err.note(format!("cannot satisfy `{}`", predicate));
let impl_candidates = self
.find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap());
if impl_candidates.len() < 10 {
self.report_similar_impl_candidates(
impl_candidates.as_slice(),
trait_ref,
obligation.cause.body_id,
&mut err,
false,
);
}
}

View File

@ -5,6 +5,7 @@ LL | needs_bar::<T>();
| ^^^^^^^^^^^^^^
|
= note: cannot satisfy `T: Bar`
= help: the trait `Bar` is implemented for `T`
note: required by a bound in `needs_bar`
--> $DIR/two-projection-param-candidates-are-ambiguous.rs:23:17
|