summary refs log tree commit diff
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
     }
 }