Skip to content

Commit f34ba77

Browse files
committed
Auto merge of #144732 - lcnr:ignore-shadowed-impls, r=compiler-errors
dont assemble shadowed impl candidates Fixes rust-lang/trait-system-refactor-initiative#109. I've originally intended to fix this by supporting lazy reevaluation when rerunning cycles. This ended up being really difficult, see https://github.com/lcnr/search_graph for my notes used while working on this. It is also insufficient for the `rayon-hang-2.rs` test as we end up with goals which we need to rerun for all combinations of provisional results. While landing such an optimization in the future may still be desirable, it is very difficult and insufficient to fix these hangs. Also see the relevant [zulip thread](https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/rustc-rayon.20hang/near/527850058). I was previously opposed to avoiding assembling shadowed impls as it may prevent future improvements in this area, cc #141226. Going to track this and the reasoning behind it in rust-lang/trait-system-refactor-initiative#226. r? `@BoxyUwU` `@compiler-errors`
2 parents 7cd9505 + a78f92b commit f34ba77

File tree

3 files changed

+105
-3
lines changed

3 files changed

+105
-3
lines changed

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::delegate::SolverDelegate;
2121
use crate::solve::inspect::ProbeKind;
2222
use crate::solve::{
2323
BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource,
24-
MaybeCause, NoSolution, ParamEnvSource, QueryResult,
24+
MaybeCause, NoSolution, ParamEnvSource, QueryResult, has_no_inference_or_external_constraints,
2525
};
2626

2727
enum AliasBoundKind {
@@ -395,9 +395,30 @@ where
395395

396396
match assemble_from {
397397
AssembleCandidatesFrom::All => {
398-
self.assemble_impl_candidates(goal, &mut candidates);
399398
self.assemble_builtin_impl_candidates(goal, &mut candidates);
400-
self.assemble_object_bound_candidates(goal, &mut candidates);
399+
// For performance we only assemble impls if there are no candidates
400+
// which would shadow them. This is necessary to avoid hangs in rayon,
401+
// see trait-system-refactor-initiative#109 for more details.
402+
//
403+
// We always assemble builtin impls as trivial builtin impls have a higher
404+
// priority than where-clauses.
405+
//
406+
// We only do this if any such candidate applies without any constraints
407+
// as we may want to weaken inference guidance in the future and don't want
408+
// to worry about causing major performance regressions when doing so.
409+
// See trait-system-refactor-initiative#226 for some ideas here.
410+
if TypingMode::Coherence == self.typing_mode()
411+
|| !candidates.iter().any(|c| {
412+
matches!(
413+
c.source,
414+
CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)
415+
| CandidateSource::AliasBound
416+
) && has_no_inference_or_external_constraints(c.result)
417+
})
418+
{
419+
self.assemble_impl_candidates(goal, &mut candidates);
420+
self.assemble_object_bound_candidates(goal, &mut candidates);
421+
}
401422
}
402423
AssembleCandidatesFrom::EnvAndBounds => {}
403424
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//@ compile-flags: -Znext-solver
2+
//@ check-pass
3+
4+
// A regression test for trait-system-refactor-initiative#109.
5+
6+
trait ParallelIterator: Sized {
7+
type Item;
8+
}
9+
trait IntoParallelIterator {
10+
type Iter: ParallelIterator<Item = Self::Item>;
11+
type Item;
12+
}
13+
impl<T: ParallelIterator> IntoParallelIterator for T {
14+
type Iter = T;
15+
type Item = T::Item;
16+
}
17+
18+
macro_rules! multizip_impls {
19+
($($T:ident),+) => {
20+
fn foo<$( $T, )+>() where
21+
$(
22+
$T: IntoParallelIterator,
23+
$T::Iter: ParallelIterator,
24+
)+
25+
($( $T, )+): IntoParallelIterator<Item = ($( $T::Item, )+)>,
26+
{}
27+
}
28+
}
29+
30+
multizip_impls! { A, B, C, D, E, F, G, H, I, J, K, L }
31+
32+
fn main() {}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//@ compile-flags: -Znext-solver
2+
//@ check-pass
3+
4+
// A regression test for trait-system-refactor-initiative#109.
5+
// Unlike `rayon-hang-1.rs` the cycles in this test are not
6+
// unproductive, which causes the `AliasRelate` goal when trying
7+
// to apply where-clauses to only error in the second iteration.
8+
//
9+
// This makes the exponential blowup to be significantly harder
10+
// to avoid.
11+
12+
trait ParallelIterator: Sized {
13+
type Item;
14+
}
15+
16+
trait IntoParallelIteratorIndir {
17+
type Iter: ParallelIterator<Item = Self::Item>;
18+
type Item;
19+
}
20+
impl<I> IntoParallelIteratorIndir for I
21+
where
22+
Box<I>: IntoParallelIterator,
23+
{
24+
type Iter = <Box<I> as IntoParallelIterator>::Iter;
25+
type Item = <Box<I> as IntoParallelIterator>::Item;
26+
}
27+
trait IntoParallelIterator {
28+
type Iter: ParallelIterator<Item = Self::Item>;
29+
type Item;
30+
}
31+
impl<T: ParallelIterator> IntoParallelIterator for T {
32+
type Iter = T;
33+
type Item = T::Item;
34+
}
35+
36+
macro_rules! multizip_impls {
37+
($($T:ident),+) => {
38+
fn foo<'a, $( $T, )+>() where
39+
$(
40+
$T: IntoParallelIteratorIndir,
41+
$T::Iter: ParallelIterator,
42+
)+
43+
{}
44+
}
45+
}
46+
47+
multizip_impls! { A, B, C, D, E, F, G, H, I, J, K, L }
48+
49+
fn main() {}

0 commit comments

Comments
 (0)