Skip to content

Commit 5cc5121

Browse files
author
Ariel Ben-Yehuda
committed
attempt to refactor the *** thing
1 parent 7b48b58 commit 5cc5121

File tree

1 file changed

+53
-42
lines changed

1 file changed

+53
-42
lines changed

src/librustc/middle/traits/select.rs

+53-42
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
645645
}
646646

647647
let mut candidates = candidate_set.vec;
648+
let candidate;
648649

649650
debug!("assembled {} candidates for {}: {}",
650651
candidates.len(),
@@ -678,39 +679,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
678679
candidates.retain(|c| self.winnow_candidate(stack, c).may_apply())
679680
}
680681

681-
// If the predicate is fully known, there should be only one
682-
// matching candidate by coherence. However, there may also be
683-
// other candidates from impls (see the doc-comment for
684-
// Candidate). Pick one candidate to use. This is somewhat
685-
// wrong around regions.
686-
if candidates.len() > 1 && !stack.obligation.predicate.has_ty_infer() {
687-
let mut i = 0;
688-
while i < candidates.len() {
689-
let is_dup =
690-
(0..candidates.len())
691-
.filter(|&j| i != j)
692-
.any(|j| self.candidate_should_be_dropped_in_favor_of(&candidates[i],
693-
&candidates[j]));
694-
if is_dup {
695-
debug!("Dropping candidate #{}/{}: {}",
696-
i, candidates.len(), candidates[i].repr(self.tcx()));
697-
candidates.swap_remove(i);
698-
} else {
699-
debug!("Retaining candidate #{}/{}: {}",
700-
i, candidates.len(), candidates[i].repr(self.tcx()));
701-
i += 1;
702-
}
703-
}
704-
}
705-
706-
// If there are *STILL* multiple candidates, give up and
707-
// report ambiguity.
708-
if candidates.len() > 1 {
709-
debug!("multiple matches, ambig");
710-
return Ok(None);
711-
}
712-
713-
714682
// If there are *NO* candidates, that there are no impls --
715683
// that we know of, anyway. Note that in the case where there
716684
// are unbound type variables within the obligation, it might
@@ -724,22 +692,65 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
724692
return Err(Unimplemented);
725693
}
726694

727-
// Just one candidate left.
728-
let candidate = candidates.pop().unwrap();
729-
730-
match candidate {
731-
ImplCandidate(def_id) => {
732-
match ty::trait_impl_polarity(self.tcx(), def_id) {
733-
Some(ast::ImplPolarity::Negative) => return Err(Unimplemented),
734-
_ => {}
695+
let candidate;
696+
if let Some(c) = self.find_sure_clause(&stack.obligation, &candidates) {
697+
// If we have a projection/where-clause candidate that
698+
// surely matches, go ahead and pick it. There can be other
699+
// candidates that match, but the clause will transform into
700+
// the right one at monomorphization-time.
701+
candidate = candidates.swap_remove(c)
702+
} else {
703+
candidate = candidates.pop().unwrap();
704+
705+
// If there are *still* multiple distinct candidates,
706+
// report ambiguity.
707+
for c in candidates {
708+
if c != candidate {
709+
debug!("multiple matches, ambig");
710+
return Ok(None);
735711
}
736712
}
737-
_ => {}
713+
}
714+
715+
if let ImplCandidate(def_id) = candidate {
716+
let polarity = ty::trait_impl_polarity(self.tcx(), def_id);
717+
if polarity == Some(ast::ImplPolarity::Negative) {
718+
return Err(Unimplemented);
719+
}
738720
}
739721

740722
Ok(Some(candidate))
741723
}
742724

725+
/// Return the index of a where clause/projection that surely matches out
726+
/// of cs, if any exists.
727+
///
728+
/// This is somewhat wrong as it does not take regions into account.
729+
fn find_sure_candidate(&self,
730+
obligation: &TraitObligation<'tcx>,
731+
cs: &[SelectionCandidate<'tcx>])
732+
-> Option<usize>
733+
{
734+
let sure_projection = None;
735+
let sure_impl = None;
736+
for (i,candidate) in cs.iter().enumerate() {
737+
match candidate {
738+
&ErrorCandidate => return None,
739+
&ProjectionCandidate => {
740+
// if let Ok(_) = self.match_where_
741+
},
742+
&ImplCandidate(iid) => {
743+
if let Ok(..) = self.infcx.can_equate(
744+
&obligation.predicate.trait_ref.0,
745+
&
746+
},
747+
_ => {}
748+
}
749+
}
750+
751+
sure_projection.or(sure_impl)
752+
}
753+
743754
fn pick_candidate_cache(&self) -> &SelectionCache<'tcx> {
744755
// If there are any where-clauses in scope, then we always use
745756
// a cache local to this particular scope. Otherwise, we

0 commit comments

Comments
 (0)