summaryrefslogtreecommitdiff
path: root/src/librustc/traits/project.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc/traits/project.rs')
-rw-r--r--src/librustc/traits/project.rs31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index de336c29229..441089250a1 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -137,17 +137,30 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
use self::ProjectionTyCandidateSet::*;
use self::ProjectionTyCandidate::*;
+
+ // This wacky variable is just used to try and
+ // make code readable and avoid confusing paths.
+ // It is assigned a "value" of `()` only on those
+ // paths in which we wish to convert `*self` to
+ // ambiguous (and return false, because the candidate
+ // was not used). On other paths, it is not assigned,
+ // and hence if those paths *could* reach the code that
+ // comes after the match, this fn would not compile.
+ let convert_to_ambigious;
+
match self {
None => {
*self = Single(candidate);
- true
+ return true;
}
+
Single(current) => {
// Duplicates can happen inside ParamEnv. In the case, we
// perform a lazy deduplication.
if current == &candidate {
return false;
}
+
// Prefer where-clauses. As in select, if there are multiple
// candidates, we prefer where-clause candidates over impls. This
// may seem a bit surprising, since impls are the source of
@@ -156,17 +169,23 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
// clauses are the safer choice. See the comment on
// `select::SelectionCandidate` and #21974 for more details.
match (current, candidate) {
- (ParamEnv(..), ParamEnv(..)) => { *self = Ambiguous; }
- (ParamEnv(..), _) => {}
+ (ParamEnv(..), ParamEnv(..)) => convert_to_ambigious = (),
+ (ParamEnv(..), _) => return false,
(_, ParamEnv(..)) => { unreachable!(); }
- (_, _) => { *self = Ambiguous; }
+ (_, _) => convert_to_ambigious = (),
}
- false
}
+
Ambiguous | Error(..) => {
- false
+ return false;
}
}
+
+ // We only ever get here when we moved from a single candidate
+ // to ambiguous.
+ let () = convert_to_ambigious;
+ *self = Ambiguous;
+ false
}
}