Skip to content

Commit 1260cee

Browse files
committed
Auto merge of #155765 - chenyukang:yukang-fix-155759-rustdoc-blanket-impl, r=<try>
Avoid recursive blanket impl checks
2 parents f964de4 + 5c6d93c commit 1260cee

5 files changed

Lines changed: 321 additions & 5 deletions

File tree

src/librustdoc/clean/auto_trait.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ fn synthesize_auto_trait_impl<'tcx>(
112112
}
113113
auto_trait::AutoTraitResult::ExplicitImpl => return None,
114114
};
115+
cx.generated_auto_trait_impls.insert((ty, trait_def_id), polarity);
115116

116117
Some(clean::Item {
117118
inner: Box::new(clean::ItemInner {

src/librustdoc/clean/blanket_impl.rs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_data_structures::thin_vec::ThinVec;
22
use rustc_hir as hir;
33
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt};
44
use rustc_infer::traits;
5-
use rustc_middle::ty::{self, TypingMode, Unnormalized, Upcast};
5+
use rustc_middle::ty::{self, Ty, TypingMode, Unnormalized};
66
use rustc_span::DUMMY_SP;
77
use rustc_span::def_id::DefId;
88
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -21,11 +21,12 @@ pub(crate) fn synthesize_blanket_impls(
2121
) -> Vec<clean::Item> {
2222
let tcx = cx.tcx;
2323
let ty = tcx.type_of(item_def_id);
24+
let item_ty = ty.instantiate_identity().skip_norm_wip();
2425

2526
let mut blanket_impls = Vec::new();
2627
for trait_def_id in tcx.visible_traits() {
2728
if !cx.cache.effective_visibilities.is_reachable(tcx, trait_def_id)
28-
|| cx.generated_synthetics.contains(&(ty.skip_binder(), trait_def_id))
29+
|| cx.generated_synthetics.contains(&(item_ty, trait_def_id))
2930
{
3031
continue;
3132
}
@@ -59,14 +60,26 @@ pub(crate) fn synthesize_blanket_impls(
5960
// FIXME(eddyb) ignoring `obligations` might cause false positives.
6061
drop(obligations);
6162

63+
// Only the impl's where-predicates need to be checked here. The trait ref itself is
64+
// the blanket impl candidate we're considering; proving it would select recursively.
6265
let predicates = tcx
6366
.predicates_of(impl_def_id)
6467
.instantiate(tcx, impl_args)
6568
.predicates
6669
.into_iter()
67-
.map(Unnormalized::skip_norm_wip)
68-
.chain(Some(impl_trait_ref.upcast(tcx)));
70+
.map(Unnormalized::skip_norm_wip);
6971
for predicate in predicates {
72+
let predicate = infcx.resolve_vars_if_possible(predicate);
73+
if let Some(may_apply) =
74+
cached_auto_trait_predicate_result(cx, predicate, impl_ty, item_ty)
75+
{
76+
if may_apply {
77+
continue;
78+
} else {
79+
continue 'blanket_impls;
80+
}
81+
}
82+
7083
let obligation = traits::Obligation::new(
7184
tcx,
7285
traits::ObligationCause::dummy(),
@@ -81,7 +94,7 @@ pub(crate) fn synthesize_blanket_impls(
8194
}
8295
debug!("found applicable impl for trait ref {trait_ref:?}");
8396

84-
cx.generated_synthetics.insert((ty.skip_binder(), trait_def_id));
97+
cx.generated_synthetics.insert((item_ty, trait_def_id));
8598

8699
blanket_impls.push(clean::Item {
87100
inner: Box::new(clean::ItemInner {
@@ -133,3 +146,31 @@ pub(crate) fn synthesize_blanket_impls(
133146

134147
blanket_impls
135148
}
149+
150+
fn cached_auto_trait_predicate_result<'tcx>(
151+
cx: &DocContext<'tcx>,
152+
predicate: ty::Clause<'tcx>,
153+
impl_ty: Ty<'tcx>,
154+
item_ty: Ty<'tcx>,
155+
) -> Option<bool> {
156+
let trait_pred = predicate.as_trait_clause()?;
157+
if trait_pred.polarity() != ty::PredicatePolarity::Positive {
158+
return None;
159+
}
160+
161+
let trait_def_id = trait_pred.def_id();
162+
if !cx.tcx.trait_is_auto(trait_def_id) {
163+
return None;
164+
}
165+
166+
let self_ty = trait_pred.self_ty().no_bound_vars()?;
167+
if self_ty != impl_ty {
168+
return None;
169+
}
170+
171+
match cx.generated_auto_trait_impls.get(&(item_ty, trait_def_id)) {
172+
Some(ty::ImplPolarity::Positive) => Some(true),
173+
Some(ty::ImplPolarity::Negative) => Some(false),
174+
_ => None,
175+
}
176+
}

src/librustdoc/core.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ pub(crate) struct DocContext<'tcx> {
5959
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
6060
// FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
6161
pub(crate) generated_synthetics: FxHashSet<(Ty<'tcx>, DefId)>,
62+
/// Polarity of synthesized auto-trait impls processed so far.
63+
pub(crate) generated_auto_trait_impls: FxHashMap<(Ty<'tcx>, DefId), ty::ImplPolarity>,
6264
pub(crate) auto_traits: Vec<DefId>,
6365
/// This same cache is used throughout rustdoc, including in [`crate::html::render`].
6466
pub(crate) cache: Cache,
@@ -370,6 +372,7 @@ pub(crate) fn run_global_ctxt(
370372
current_type_aliases: Default::default(),
371373
impl_trait_bounds: Default::default(),
372374
generated_synthetics: Default::default(),
375+
generated_auto_trait_impls: Default::default(),
373376
auto_traits,
374377
cache: Cache::new(render_options.document_private, render_options.document_hidden),
375378
inlined: FxHashSet::default(),
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
#![crate_name = "foo"]
2+
3+
//@ has 'foo/struct.Class.html'
4+
//@ has - '//*[@id="impl-ThreadSafe-for-T"]' 'impl<T> ThreadSafe for T'
5+
pub struct Class<Span> {
6+
pub body: std::sync::Arc<[stmt::Statement<Span>]>,
7+
pub decorators: std::sync::Arc<[expr::Expression<Span>]>,
8+
pub span: Span,
9+
}
10+
11+
pub trait ThreadSafe: Send + Sync {}
12+
13+
// With this line commented out, the slow behavior does not occur.
14+
impl<T: Send + Sync> ThreadSafe for T {}
15+
16+
mod stmt {
17+
pub struct S00<Span>(pub Statement<Span>);
18+
pub struct S01<Span>(pub Statement<Span>);
19+
pub struct S02<Span>(pub Statement<Span>);
20+
pub struct S03<Span>(pub Statement<Span>);
21+
pub struct S04<Span>(pub Statement<Span>);
22+
pub struct S05<Span>(pub Statement<Span>);
23+
pub struct S06<Span>(pub Statement<Span>);
24+
pub struct S07<Span>(pub Statement<Span>);
25+
pub struct S08<Span>(pub Statement<Span>);
26+
pub struct S09<Span>(pub Statement<Span>);
27+
pub struct S10<Span>(pub Statement<Span>);
28+
pub struct S11<Span>(pub Statement<Span>);
29+
pub struct S12<Span>(pub Statement<Span>);
30+
pub struct S13<Span>(pub Statement<Span>);
31+
pub struct S14<Span>(pub Statement<Span>);
32+
pub struct S15<Span>(pub Statement<Span>);
33+
pub struct S16<Span>(pub Statement<Span>);
34+
pub struct S17<Span>(pub Statement<Span>);
35+
pub struct S18<Span>(pub Statement<Span>);
36+
pub struct S19<Span>(pub Statement<Span>);
37+
pub struct S20<Span>(pub Statement<Span>);
38+
pub struct S21<Span>(pub Statement<Span>);
39+
pub struct S22<Span>(pub Statement<Span>);
40+
pub struct S23<Span>(pub Statement<Span>);
41+
pub struct S24<Span>(pub Statement<Span>);
42+
pub struct S25<Span>(pub Statement<Span>);
43+
pub struct S26<Span>(pub Statement<Span>);
44+
pub struct S27<Span>(pub Statement<Span>);
45+
pub struct S28<Span>(pub Statement<Span>);
46+
pub struct S29<Span>(pub Statement<Span>);
47+
pub struct S30<Span>(pub Statement<Span>);
48+
pub struct S31<Span>(pub Statement<Span>);
49+
pub struct S32<Span>(pub Statement<Span>);
50+
pub struct S33<Span>(pub Statement<Span>);
51+
pub struct S34<Span>(pub Statement<Span>);
52+
pub struct S35<Span>(pub Statement<Span>);
53+
pub struct S36<Span>(pub Statement<Span>);
54+
pub struct S37<Span>(pub Statement<Span>);
55+
pub struct S38<Span>(pub Statement<Span>);
56+
pub struct S39<Span>(pub Statement<Span>);
57+
pub struct S40<Span>(pub Statement<Span>);
58+
pub struct S41<Span>(pub Statement<Span>);
59+
pub struct S42<Span>(pub Statement<Span>);
60+
pub struct S43<Span>(pub Statement<Span>);
61+
pub struct S44<Span>(pub Statement<Span>);
62+
pub struct S45<Span>(pub Statement<Span>);
63+
pub struct S46<Span>(pub Statement<Span>);
64+
pub struct S47<Span>(pub Statement<Span>);
65+
pub struct S48<Span>(pub Statement<Span>);
66+
pub struct S49<Span>(pub Statement<Span>);
67+
pub struct S50<Span>(pub Statement<Span>);
68+
pub struct S51<Span>(pub Statement<Span>);
69+
pub struct S52<Span>(pub Statement<Span>);
70+
pub struct S53<Span>(pub Statement<Span>);
71+
pub struct S54<Span>(pub Statement<Span>);
72+
pub struct S55<Span>(pub Statement<Span>);
73+
pub struct S56<Span>(pub Statement<Span>);
74+
pub struct S57<Span>(pub Statement<Span>);
75+
pub struct S58<Span>(pub Statement<Span>);
76+
pub struct S59<Span>(pub Statement<Span>);
77+
78+
pub enum Statement<Span> {
79+
Class(std::sync::Arc<crate::Class<Span>>),
80+
S00(std::sync::Arc<S00<Span>>),
81+
S01(std::sync::Arc<S01<Span>>),
82+
S02(std::sync::Arc<S02<Span>>),
83+
S03(std::sync::Arc<S03<Span>>),
84+
S04(std::sync::Arc<S04<Span>>),
85+
S05(std::sync::Arc<S05<Span>>),
86+
S06(std::sync::Arc<S06<Span>>),
87+
S07(std::sync::Arc<S07<Span>>),
88+
S08(std::sync::Arc<S08<Span>>),
89+
S09(std::sync::Arc<S09<Span>>),
90+
S10(std::sync::Arc<S10<Span>>),
91+
S11(std::sync::Arc<S11<Span>>),
92+
S12(std::sync::Arc<S12<Span>>),
93+
S13(std::sync::Arc<S13<Span>>),
94+
S14(std::sync::Arc<S14<Span>>),
95+
S15(std::sync::Arc<S15<Span>>),
96+
S16(std::sync::Arc<S16<Span>>),
97+
S17(std::sync::Arc<S17<Span>>),
98+
S18(std::sync::Arc<S18<Span>>),
99+
S19(std::sync::Arc<S19<Span>>),
100+
S20(std::sync::Arc<S20<Span>>),
101+
S21(std::sync::Arc<S21<Span>>),
102+
S22(std::sync::Arc<S22<Span>>),
103+
S23(std::sync::Arc<S23<Span>>),
104+
S24(std::sync::Arc<S24<Span>>),
105+
S25(std::sync::Arc<S25<Span>>),
106+
S26(std::sync::Arc<S26<Span>>),
107+
S27(std::sync::Arc<S27<Span>>),
108+
S28(std::sync::Arc<S28<Span>>),
109+
S29(std::sync::Arc<S29<Span>>),
110+
S30(std::sync::Arc<S30<Span>>),
111+
S31(std::sync::Arc<S31<Span>>),
112+
S32(std::sync::Arc<S32<Span>>),
113+
S33(std::sync::Arc<S33<Span>>),
114+
S34(std::sync::Arc<S34<Span>>),
115+
S35(std::sync::Arc<S35<Span>>),
116+
S36(std::sync::Arc<S36<Span>>),
117+
S37(std::sync::Arc<S37<Span>>),
118+
S38(std::sync::Arc<S38<Span>>),
119+
S39(std::sync::Arc<S39<Span>>),
120+
S40(std::sync::Arc<S40<Span>>),
121+
S41(std::sync::Arc<S41<Span>>),
122+
S42(std::sync::Arc<S42<Span>>),
123+
S43(std::sync::Arc<S43<Span>>),
124+
S44(std::sync::Arc<S44<Span>>),
125+
S45(std::sync::Arc<S45<Span>>),
126+
S46(std::sync::Arc<S46<Span>>),
127+
S47(std::sync::Arc<S47<Span>>),
128+
S48(std::sync::Arc<S48<Span>>),
129+
S49(std::sync::Arc<S49<Span>>),
130+
S50(std::sync::Arc<S50<Span>>),
131+
S51(std::sync::Arc<S51<Span>>),
132+
S52(std::sync::Arc<S52<Span>>),
133+
S53(std::sync::Arc<S53<Span>>),
134+
S54(std::sync::Arc<S54<Span>>),
135+
S55(std::sync::Arc<S55<Span>>),
136+
S56(std::sync::Arc<S56<Span>>),
137+
S57(std::sync::Arc<S57<Span>>),
138+
S58(std::sync::Arc<S58<Span>>),
139+
S59(std::sync::Arc<S59<Span>>),
140+
}
141+
}
142+
143+
mod expr {
144+
pub struct E00<Span>(pub Expression<Span>);
145+
pub struct E01<Span>(pub Expression<Span>);
146+
pub struct E02<Span>(pub Expression<Span>);
147+
pub struct E03<Span>(pub Expression<Span>);
148+
pub struct E04<Span>(pub Expression<Span>);
149+
pub struct E05<Span>(pub Expression<Span>);
150+
pub struct E06<Span>(pub Expression<Span>);
151+
pub struct E07<Span>(pub Expression<Span>);
152+
pub struct E08<Span>(pub Expression<Span>);
153+
pub struct E09<Span>(pub Expression<Span>);
154+
pub struct E10<Span>(pub Expression<Span>);
155+
pub struct E11<Span>(pub Expression<Span>);
156+
pub struct E12<Span>(pub Expression<Span>);
157+
pub struct E13<Span>(pub Expression<Span>);
158+
pub struct E14<Span>(pub Expression<Span>);
159+
pub struct E15<Span>(pub Expression<Span>);
160+
pub struct E16<Span>(pub Expression<Span>);
161+
pub struct E17<Span>(pub Expression<Span>);
162+
pub struct E18<Span>(pub Expression<Span>);
163+
pub struct E19<Span>(pub Expression<Span>);
164+
pub struct E20<Span>(pub Expression<Span>);
165+
pub struct E21<Span>(pub Expression<Span>);
166+
pub struct E22<Span>(pub Expression<Span>);
167+
pub struct E23<Span>(pub Expression<Span>);
168+
pub struct E24<Span>(pub Expression<Span>);
169+
pub struct E25<Span>(pub Expression<Span>);
170+
pub struct E26<Span>(pub Expression<Span>);
171+
pub struct E27<Span>(pub Expression<Span>);
172+
pub struct E28<Span>(pub Expression<Span>);
173+
pub struct E29<Span>(pub Expression<Span>);
174+
pub struct E30<Span>(pub Expression<Span>);
175+
pub struct E31<Span>(pub Expression<Span>);
176+
pub struct E32<Span>(pub Expression<Span>);
177+
pub struct E33<Span>(pub Expression<Span>);
178+
pub struct E34<Span>(pub Expression<Span>);
179+
pub struct E35<Span>(pub Expression<Span>);
180+
pub struct E36<Span>(pub Expression<Span>);
181+
pub struct E37<Span>(pub Expression<Span>);
182+
pub struct E38<Span>(pub Expression<Span>);
183+
pub struct E39<Span>(pub Expression<Span>);
184+
pub struct E40<Span>(pub Expression<Span>);
185+
pub struct E41<Span>(pub Expression<Span>);
186+
pub struct E42<Span>(pub Expression<Span>);
187+
pub struct E43<Span>(pub Expression<Span>);
188+
pub struct E44<Span>(pub Expression<Span>);
189+
pub struct E45<Span>(pub Expression<Span>);
190+
pub struct E46<Span>(pub Expression<Span>);
191+
pub struct E47<Span>(pub Expression<Span>);
192+
pub struct E48<Span>(pub Expression<Span>);
193+
pub struct E49<Span>(pub Expression<Span>);
194+
pub struct E50<Span>(pub Expression<Span>);
195+
pub struct E51<Span>(pub Expression<Span>);
196+
pub struct E52<Span>(pub Expression<Span>);
197+
pub struct E53<Span>(pub Expression<Span>);
198+
pub struct E54<Span>(pub Expression<Span>);
199+
pub struct E55<Span>(pub Expression<Span>);
200+
pub struct E56<Span>(pub Expression<Span>);
201+
pub struct E57<Span>(pub Expression<Span>);
202+
pub struct E58<Span>(pub Expression<Span>);
203+
pub struct E59<Span>(pub Expression<Span>);
204+
205+
pub enum Expression<Span> {
206+
Class(std::sync::Arc<crate::Class<Span>>),
207+
E00(std::sync::Arc<E00<Span>>),
208+
E01(std::sync::Arc<E01<Span>>),
209+
E02(std::sync::Arc<E02<Span>>),
210+
E03(std::sync::Arc<E03<Span>>),
211+
E04(std::sync::Arc<E04<Span>>),
212+
E05(std::sync::Arc<E05<Span>>),
213+
E06(std::sync::Arc<E06<Span>>),
214+
E07(std::sync::Arc<E07<Span>>),
215+
E08(std::sync::Arc<E08<Span>>),
216+
E09(std::sync::Arc<E09<Span>>),
217+
E10(std::sync::Arc<E10<Span>>),
218+
E11(std::sync::Arc<E11<Span>>),
219+
E12(std::sync::Arc<E12<Span>>),
220+
E13(std::sync::Arc<E13<Span>>),
221+
E14(std::sync::Arc<E14<Span>>),
222+
E15(std::sync::Arc<E15<Span>>),
223+
E16(std::sync::Arc<E16<Span>>),
224+
E17(std::sync::Arc<E17<Span>>),
225+
E18(std::sync::Arc<E18<Span>>),
226+
E19(std::sync::Arc<E19<Span>>),
227+
E20(std::sync::Arc<E20<Span>>),
228+
E21(std::sync::Arc<E21<Span>>),
229+
E22(std::sync::Arc<E22<Span>>),
230+
E23(std::sync::Arc<E23<Span>>),
231+
E24(std::sync::Arc<E24<Span>>),
232+
E25(std::sync::Arc<E25<Span>>),
233+
E26(std::sync::Arc<E26<Span>>),
234+
E27(std::sync::Arc<E27<Span>>),
235+
E28(std::sync::Arc<E28<Span>>),
236+
E29(std::sync::Arc<E29<Span>>),
237+
E30(std::sync::Arc<E30<Span>>),
238+
E31(std::sync::Arc<E31<Span>>),
239+
E32(std::sync::Arc<E32<Span>>),
240+
E33(std::sync::Arc<E33<Span>>),
241+
E34(std::sync::Arc<E34<Span>>),
242+
E35(std::sync::Arc<E35<Span>>),
243+
E36(std::sync::Arc<E36<Span>>),
244+
E37(std::sync::Arc<E37<Span>>),
245+
E38(std::sync::Arc<E38<Span>>),
246+
E39(std::sync::Arc<E39<Span>>),
247+
E40(std::sync::Arc<E40<Span>>),
248+
E41(std::sync::Arc<E41<Span>>),
249+
E42(std::sync::Arc<E42<Span>>),
250+
E43(std::sync::Arc<E43<Span>>),
251+
E44(std::sync::Arc<E44<Span>>),
252+
E45(std::sync::Arc<E45<Span>>),
253+
E46(std::sync::Arc<E46<Span>>),
254+
E47(std::sync::Arc<E47<Span>>),
255+
E48(std::sync::Arc<E48<Span>>),
256+
E49(std::sync::Arc<E49<Span>>),
257+
E50(std::sync::Arc<E50<Span>>),
258+
E51(std::sync::Arc<E51<Span>>),
259+
E52(std::sync::Arc<E52<Span>>),
260+
E53(std::sync::Arc<E53<Span>>),
261+
E54(std::sync::Arc<E54<Span>>),
262+
E55(std::sync::Arc<E55<Span>>),
263+
E56(std::sync::Arc<E56<Span>>),
264+
E57(std::sync::Arc<E57<Span>>),
265+
E58(std::sync::Arc<E58<Span>>),
266+
E59(std::sync::Arc<E59<Span>>),
267+
}
268+
}

0 commit comments

Comments
 (0)