Auto merge of #95333 - GuillaumeGomez:auto-trait-perf-issue, r=oli-obk
Fix perf issue for auto trait selection Follow-up of https://github.com/rust-lang/rust/pull/95069 which fixes the perf issue introduced by it. r? `@oli-obk`
This commit is contained in:
commit
3badf5c51c
3 changed files with 31 additions and 28 deletions
|
@ -999,6 +999,15 @@ impl<'tcx> PolyTraitRef<'tcx> {
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::ImplPolarity::Positive,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Same as [`PolyTraitRef::to_poly_trait_predicate`] but sets a negative polarity instead.
|
||||||
|
pub fn to_poly_trait_predicate_negative_polarity(&self) -> ty::PolyTraitPredicate<'tcx> {
|
||||||
|
self.map_bound(|trait_ref| ty::TraitPredicate {
|
||||||
|
trait_ref,
|
||||||
|
constness: ty::BoundConstness::NotConst,
|
||||||
|
polarity: ty::ImplPolarity::Negative,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An existential reference to a trait, where `Self` is erased.
|
/// An existential reference to a trait, where `Self` is erased.
|
||||||
|
|
|
@ -87,13 +87,31 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
let trait_pred = ty::Binder::dummy(trait_ref);
|
let trait_pred = ty::Binder::dummy(trait_ref);
|
||||||
|
|
||||||
let bail_out = tcx.infer_ctxt().enter(|infcx| {
|
let bail_out = tcx.infer_ctxt().enter(|infcx| {
|
||||||
let mut selcx = SelectionContext::with_negative(&infcx, true);
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
let result = selcx.select(&Obligation::new(
|
let result = selcx.select(&Obligation::new(
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
orig_env,
|
orig_env,
|
||||||
trait_pred.to_poly_trait_predicate(),
|
trait_pred.to_poly_trait_predicate(),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(Some(ImplSource::UserDefined(_))) => {
|
||||||
|
debug!(
|
||||||
|
"find_auto_trait_generics({:?}): \
|
||||||
|
manual impl found, bailing out",
|
||||||
|
trait_ref
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = selcx.select(&Obligation::new(
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
orig_env,
|
||||||
|
trait_pred.to_poly_trait_predicate_negative_polarity(),
|
||||||
|
));
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(Some(ImplSource::UserDefined(_))) => {
|
Ok(Some(ImplSource::UserDefined(_))) => {
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -277,7 +295,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
fresh_preds.insert(self.clean_pred(infcx, predicate));
|
fresh_preds.insert(self.clean_pred(infcx, predicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut select = SelectionContext::with_negative(&infcx, true);
|
let mut select = SelectionContext::new(&infcx);
|
||||||
|
|
||||||
let mut already_visited = FxHashSet::default();
|
let mut already_visited = FxHashSet::default();
|
||||||
let mut predicates = VecDeque::new();
|
let mut predicates = VecDeque::new();
|
||||||
|
|
|
@ -119,11 +119,6 @@ pub struct SelectionContext<'cx, 'tcx> {
|
||||||
|
|
||||||
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
|
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
|
||||||
|
|
||||||
/// Controls whether or not to filter out negative impls when selecting.
|
|
||||||
/// This is used in librustdoc to distinguish between the lack of an impl
|
|
||||||
/// and a negative impl
|
|
||||||
allow_negative_impls: bool,
|
|
||||||
|
|
||||||
/// The mode that trait queries run in, which informs our error handling
|
/// The mode that trait queries run in, which informs our error handling
|
||||||
/// policy. In essence, canonicalized queries need their errors propagated
|
/// policy. In essence, canonicalized queries need their errors propagated
|
||||||
/// rather than immediately reported because we do not have accurate spans.
|
/// rather than immediately reported because we do not have accurate spans.
|
||||||
|
@ -215,7 +210,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
freshener: infcx.freshener_keep_static(),
|
freshener: infcx.freshener_keep_static(),
|
||||||
intercrate: false,
|
intercrate: false,
|
||||||
intercrate_ambiguity_causes: None,
|
intercrate_ambiguity_causes: None,
|
||||||
allow_negative_impls: false,
|
|
||||||
query_mode: TraitQueryMode::Standard,
|
query_mode: TraitQueryMode::Standard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,22 +220,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
freshener: infcx.freshener_keep_static(),
|
freshener: infcx.freshener_keep_static(),
|
||||||
intercrate: true,
|
intercrate: true,
|
||||||
intercrate_ambiguity_causes: None,
|
intercrate_ambiguity_causes: None,
|
||||||
allow_negative_impls: false,
|
|
||||||
query_mode: TraitQueryMode::Standard,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_negative(
|
|
||||||
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
|
||||||
allow_negative_impls: bool,
|
|
||||||
) -> SelectionContext<'cx, 'tcx> {
|
|
||||||
debug!(?allow_negative_impls, "with_negative");
|
|
||||||
SelectionContext {
|
|
||||||
infcx,
|
|
||||||
freshener: infcx.freshener_keep_static(),
|
|
||||||
intercrate: false,
|
|
||||||
intercrate_ambiguity_causes: None,
|
|
||||||
allow_negative_impls,
|
|
||||||
query_mode: TraitQueryMode::Standard,
|
query_mode: TraitQueryMode::Standard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,7 +234,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
freshener: infcx.freshener_keep_static(),
|
freshener: infcx.freshener_keep_static(),
|
||||||
intercrate: false,
|
intercrate: false,
|
||||||
intercrate_ambiguity_causes: None,
|
intercrate_ambiguity_causes: None,
|
||||||
allow_negative_impls: false,
|
|
||||||
query_mode,
|
query_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1192,7 +1169,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
if let ImplCandidate(def_id) = candidate {
|
if let ImplCandidate(def_id) = candidate {
|
||||||
if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id)
|
if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id)
|
||||||
|| obligation.polarity() == tcx.impl_polarity(def_id)
|
|| obligation.polarity() == tcx.impl_polarity(def_id)
|
||||||
|| self.allow_negative_impls
|
|
||||||
{
|
{
|
||||||
result.push(candidate);
|
result.push(candidate);
|
||||||
}
|
}
|
||||||
|
@ -1272,7 +1248,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// the master cache. Since coherence executes pretty quickly,
|
// the master cache. Since coherence executes pretty quickly,
|
||||||
// it's not worth going to more trouble to increase the
|
// it's not worth going to more trouble to increase the
|
||||||
// hit-rate, I don't think.
|
// hit-rate, I don't think.
|
||||||
if self.intercrate || self.allow_negative_impls {
|
if self.intercrate {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,7 +1265,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// mode, so don't do any caching. In particular, we might
|
// mode, so don't do any caching. In particular, we might
|
||||||
// re-use the same `InferCtxt` with both an intercrate
|
// re-use the same `InferCtxt` with both an intercrate
|
||||||
// and non-intercrate `SelectionContext`
|
// and non-intercrate `SelectionContext`
|
||||||
if self.intercrate || self.allow_negative_impls {
|
if self.intercrate {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue