Skip to content

Commit 3badf5c

Browse files
committed
Auto merge of #95333 - GuillaumeGomez:auto-trait-perf-issue, r=oli-obk
Fix perf issue for auto trait selection Follow-up of #95069 which fixes the perf issue introduced by it. r? `@oli-obk`
2 parents 6252304 + bd51f17 commit 3badf5c

File tree

3 files changed

+31
-28
lines changed

3 files changed

+31
-28
lines changed

Diff for: compiler/rustc_middle/src/ty/sty.rs

+9
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,15 @@ impl<'tcx> PolyTraitRef<'tcx> {
999999
polarity: ty::ImplPolarity::Positive,
10001000
})
10011001
}
1002+
1003+
/// Same as [`PolyTraitRef::to_poly_trait_predicate`] but sets a negative polarity instead.
1004+
pub fn to_poly_trait_predicate_negative_polarity(&self) -> ty::PolyTraitPredicate<'tcx> {
1005+
self.map_bound(|trait_ref| ty::TraitPredicate {
1006+
trait_ref,
1007+
constness: ty::BoundConstness::NotConst,
1008+
polarity: ty::ImplPolarity::Negative,
1009+
})
1010+
}
10021011
}
10031012

10041013
/// An existential reference to a trait, where `Self` is erased.

Diff for: compiler/rustc_trait_selection/src/traits/auto_trait.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,31 @@ impl<'tcx> AutoTraitFinder<'tcx> {
8787
let trait_pred = ty::Binder::dummy(trait_ref);
8888

8989
let bail_out = tcx.infer_ctxt().enter(|infcx| {
90-
let mut selcx = SelectionContext::with_negative(&infcx, true);
90+
let mut selcx = SelectionContext::new(&infcx);
9191
let result = selcx.select(&Obligation::new(
9292
ObligationCause::dummy(),
9393
orig_env,
9494
trait_pred.to_poly_trait_predicate(),
9595
));
9696

97+
match result {
98+
Ok(Some(ImplSource::UserDefined(_))) => {
99+
debug!(
100+
"find_auto_trait_generics({:?}): \
101+
manual impl found, bailing out",
102+
trait_ref
103+
);
104+
return true;
105+
}
106+
_ => {}
107+
}
108+
109+
let result = selcx.select(&Obligation::new(
110+
ObligationCause::dummy(),
111+
orig_env,
112+
trait_pred.to_poly_trait_predicate_negative_polarity(),
113+
));
114+
97115
match result {
98116
Ok(Some(ImplSource::UserDefined(_))) => {
99117
debug!(
@@ -277,7 +295,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
277295
fresh_preds.insert(self.clean_pred(infcx, predicate));
278296
}
279297

280-
let mut select = SelectionContext::with_negative(&infcx, true);
298+
let mut select = SelectionContext::new(&infcx);
281299

282300
let mut already_visited = FxHashSet::default();
283301
let mut predicates = VecDeque::new();

Diff for: compiler/rustc_trait_selection/src/traits/select/mod.rs

+2-26
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,6 @@ pub struct SelectionContext<'cx, 'tcx> {
119119

120120
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
121121

122-
/// Controls whether or not to filter out negative impls when selecting.
123-
/// This is used in librustdoc to distinguish between the lack of an impl
124-
/// and a negative impl
125-
allow_negative_impls: bool,
126-
127122
/// The mode that trait queries run in, which informs our error handling
128123
/// policy. In essence, canonicalized queries need their errors propagated
129124
/// rather than immediately reported because we do not have accurate spans.
@@ -215,7 +210,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
215210
freshener: infcx.freshener_keep_static(),
216211
intercrate: false,
217212
intercrate_ambiguity_causes: None,
218-
allow_negative_impls: false,
219213
query_mode: TraitQueryMode::Standard,
220214
}
221215
}
@@ -226,22 +220,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
226220
freshener: infcx.freshener_keep_static(),
227221
intercrate: true,
228222
intercrate_ambiguity_causes: None,
229-
allow_negative_impls: false,
230-
query_mode: TraitQueryMode::Standard,
231-
}
232-
}
233-
234-
pub fn with_negative(
235-
infcx: &'cx InferCtxt<'cx, 'tcx>,
236-
allow_negative_impls: bool,
237-
) -> SelectionContext<'cx, 'tcx> {
238-
debug!(?allow_negative_impls, "with_negative");
239-
SelectionContext {
240-
infcx,
241-
freshener: infcx.freshener_keep_static(),
242-
intercrate: false,
243-
intercrate_ambiguity_causes: None,
244-
allow_negative_impls,
245223
query_mode: TraitQueryMode::Standard,
246224
}
247225
}
@@ -256,7 +234,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
256234
freshener: infcx.freshener_keep_static(),
257235
intercrate: false,
258236
intercrate_ambiguity_causes: None,
259-
allow_negative_impls: false,
260237
query_mode,
261238
}
262239
}
@@ -1192,7 +1169,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11921169
if let ImplCandidate(def_id) = candidate {
11931170
if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id)
11941171
|| obligation.polarity() == tcx.impl_polarity(def_id)
1195-
|| self.allow_negative_impls
11961172
{
11971173
result.push(candidate);
11981174
}
@@ -1272,7 +1248,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12721248
// the master cache. Since coherence executes pretty quickly,
12731249
// it's not worth going to more trouble to increase the
12741250
// hit-rate, I don't think.
1275-
if self.intercrate || self.allow_negative_impls {
1251+
if self.intercrate {
12761252
return false;
12771253
}
12781254

@@ -1289,7 +1265,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12891265
// mode, so don't do any caching. In particular, we might
12901266
// re-use the same `InferCtxt` with both an intercrate
12911267
// and non-intercrate `SelectionContext`
1292-
if self.intercrate || self.allow_negative_impls {
1268+
if self.intercrate {
12931269
return None;
12941270
}
12951271
let tcx = self.tcx();

0 commit comments

Comments
 (0)