Skip to content

Commit 772b1ce

Browse files
authored
Rollup merge of #108937 - lcnr:winnowing-enum, r=WaffleLapkin
improve readability of winnowing
2 parents 7699462 + 14818e2 commit 772b1ce

File tree

1 file changed

+67
-40
lines changed
  • compiler/rustc_trait_selection/src/traits/select

1 file changed

+67
-40
lines changed

compiler/rustc_trait_selection/src/traits/select/mod.rs

+67-40
Original file line numberDiff line numberDiff line change
@@ -465,14 +465,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
465465
if candidates.len() > 1 {
466466
let mut i = 0;
467467
while i < candidates.len() {
468-
let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
468+
let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| {
469469
self.candidate_should_be_dropped_in_favor_of(
470470
&candidates[i],
471471
&candidates[j],
472472
needs_infer,
473-
)
473+
) == DropVictim::Yes
474474
});
475-
if is_dup {
475+
if should_drop_i {
476476
debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
477477
candidates.swap_remove(i);
478478
} else {
@@ -1842,16 +1842,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18421842
ProjectionMatchesProjection::No
18431843
}
18441844
}
1845+
}
18451846

1846-
///////////////////////////////////////////////////////////////////////////
1847-
// WINNOW
1848-
//
1849-
// Winnowing is the process of attempting to resolve ambiguity by
1850-
// probing further. During the winnowing process, we unify all
1851-
// type variables and then we also attempt to evaluate recursive
1852-
// bounds to see if they are satisfied.
1847+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1848+
enum DropVictim {
1849+
Yes,
1850+
No,
1851+
}
18531852

1854-
/// Returns `true` if `victim` should be dropped in favor of
1853+
/// ## Winnowing
1854+
///
1855+
/// Winnowing is the process of attempting to resolve ambiguity by
1856+
/// probing further. During the winnowing process, we unify all
1857+
/// type variables and then we also attempt to evaluate recursive
1858+
/// bounds to see if they are satisfied.
1859+
impl<'tcx> SelectionContext<'_, 'tcx> {
1860+
/// Returns `DropVictim::Yes` if `victim` should be dropped in favor of
18551861
/// `other`. Generally speaking we will drop duplicate
18561862
/// candidates and prefer where-clause candidates.
18571863
///
@@ -1861,9 +1867,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18611867
victim: &EvaluatedCandidate<'tcx>,
18621868
other: &EvaluatedCandidate<'tcx>,
18631869
needs_infer: bool,
1864-
) -> bool {
1870+
) -> DropVictim {
18651871
if victim.candidate == other.candidate {
1866-
return true;
1872+
return DropVictim::Yes;
18671873
}
18681874

18691875
// Check if a bound would previously have been removed when normalizing
@@ -1887,11 +1893,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18871893
}
18881894

18891895
// FIXME(@jswrenn): this should probably be more sophisticated
1890-
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => false,
1896+
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
18911897

18921898
// (*)
1893-
(BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => true,
1894-
(_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => false,
1899+
(BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => {
1900+
DropVictim::Yes
1901+
}
1902+
(_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => {
1903+
DropVictim::No
1904+
}
18951905

18961906
(ParamCandidate(other), ParamCandidate(victim)) => {
18971907
let same_except_bound_vars = other.skip_binder().trait_ref
@@ -1905,28 +1915,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19051915
// or the current one if tied (they should both evaluate to the same answer). This is
19061916
// probably best characterized as a "hack", since we might prefer to just do our
19071917
// best to *not* create essentially duplicate candidates in the first place.
1908-
other.bound_vars().len() <= victim.bound_vars().len()
1918+
if other.bound_vars().len() <= victim.bound_vars().len() {
1919+
DropVictim::Yes
1920+
} else {
1921+
DropVictim::No
1922+
}
19091923
} else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
19101924
&& victim.skip_binder().constness == ty::BoundConstness::NotConst
19111925
&& other.skip_binder().polarity == victim.skip_binder().polarity
19121926
{
19131927
// Drop otherwise equivalent non-const candidates in favor of const candidates.
1914-
true
1928+
DropVictim::Yes
19151929
} else {
1916-
false
1930+
DropVictim::No
19171931
}
19181932
}
19191933

19201934
// Drop otherwise equivalent non-const fn pointer candidates
1921-
(FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true,
1935+
(FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => DropVictim::Yes,
19221936

1923-
// Global bounds from the where clause should be ignored
1924-
// here (see issue #50825). Otherwise, we have a where
1925-
// clause so don't go around looking for impls.
1926-
// Arbitrarily give param candidates priority
1927-
// over projection and object candidates.
19281937
(
1929-
ParamCandidate(ref cand),
1938+
ParamCandidate(ref other_cand),
19301939
ImplCandidate(..)
19311940
| ClosureCandidate { .. }
19321941
| GeneratorCandidate
@@ -1939,11 +1948,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19391948
| TraitAliasCandidate
19401949
| ObjectCandidate(_)
19411950
| ProjectionCandidate(..),
1942-
) => !is_global(cand),
1943-
(ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref cand)) => {
1951+
) => {
1952+
if is_global(other_cand) {
1953+
DropVictim::No
1954+
} else {
1955+
// We have a where clause so don't go around looking
1956+
// for impls. Arbitrarily give param candidates priority
1957+
// over projection and object candidates.
1958+
//
1959+
// Global bounds from the where clause should be ignored
1960+
// here (see issue #50825).
1961+
DropVictim::Yes
1962+
}
1963+
}
1964+
(ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref victim_cand)) => {
19441965
// Prefer these to a global where-clause bound
19451966
// (see issue #50825).
1946-
is_global(cand)
1967+
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
19471968
}
19481969
(
19491970
ImplCandidate(_)
@@ -1956,18 +1977,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19561977
| TraitUpcastingUnsizeCandidate(_)
19571978
| BuiltinCandidate { has_nested: true }
19581979
| TraitAliasCandidate,
1959-
ParamCandidate(ref cand),
1980+
ParamCandidate(ref victim_cand),
19601981
) => {
19611982
// Prefer these to a global where-clause bound
19621983
// (see issue #50825).
1963-
is_global(cand) && other.evaluation.must_apply_modulo_regions()
1984+
if is_global(victim_cand) && other.evaluation.must_apply_modulo_regions() {
1985+
DropVictim::Yes
1986+
} else {
1987+
DropVictim::No
1988+
}
19641989
}
19651990

19661991
(ProjectionCandidate(i, _), ProjectionCandidate(j, _))
19671992
| (ObjectCandidate(i), ObjectCandidate(j)) => {
19681993
// Arbitrarily pick the lower numbered candidate for backwards
19691994
// compatibility reasons. Don't let this affect inference.
1970-
i < j && !needs_infer
1995+
if i < j && !needs_infer { DropVictim::Yes } else { DropVictim::No }
19711996
}
19721997
(ObjectCandidate(_), ProjectionCandidate(..))
19731998
| (ProjectionCandidate(..), ObjectCandidate(_)) => {
@@ -1987,7 +2012,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19872012
| TraitUpcastingUnsizeCandidate(_)
19882013
| BuiltinCandidate { .. }
19892014
| TraitAliasCandidate,
1990-
) => true,
2015+
) => DropVictim::Yes,
19912016

19922017
(
19932018
ImplCandidate(..)
@@ -2001,7 +2026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20012026
| BuiltinCandidate { .. }
20022027
| TraitAliasCandidate,
20032028
ObjectCandidate(_) | ProjectionCandidate(..),
2004-
) => false,
2029+
) => DropVictim::No,
20052030

20062031
(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
20072032
// See if we can toss out `victim` based on specialization.
@@ -2014,7 +2039,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20142039
let tcx = self.tcx();
20152040
if other.evaluation.must_apply_modulo_regions() {
20162041
if tcx.specializes((other_def, victim_def)) {
2017-
return true;
2042+
return DropVictim::Yes;
20182043
}
20192044
}
20202045

@@ -2060,13 +2085,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20602085
// will then correctly report an inference error, since the
20612086
// existence of multiple marker trait impls tells us nothing
20622087
// about which one should actually apply.
2063-
!needs_infer
2088+
if needs_infer { DropVictim::No } else { DropVictim::Yes }
20642089
}
2065-
Some(_) => true,
2066-
None => false,
2090+
Some(_) => DropVictim::Yes,
2091+
None => DropVictim::No,
20672092
}
20682093
} else {
2069-
false
2094+
DropVictim::No
20702095
}
20712096
}
20722097

@@ -2092,10 +2117,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20922117
| TraitUpcastingUnsizeCandidate(_)
20932118
| BuiltinCandidate { has_nested: true }
20942119
| TraitAliasCandidate,
2095-
) => false,
2120+
) => DropVictim::No,
20962121
}
20972122
}
2123+
}
20982124

2125+
impl<'tcx> SelectionContext<'_, 'tcx> {
20992126
fn sized_conditions(
21002127
&mut self,
21012128
obligation: &TraitObligation<'tcx>,

0 commit comments

Comments
 (0)