Skip to content

Commit 654f43f

Browse files
Move winnowing to assembly
1 parent 8987e68 commit 654f43f

File tree

3 files changed

+81
-140
lines changed

3 files changed

+81
-140
lines changed

compiler/rustc_trait_selection/src/solve/assembly.rs

+75-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use super::infcx_ext::InferCtxtExt;
44
#[cfg(doc)]
55
use super::trait_goals::structural_traits::*;
6-
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
6+
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
77
use rustc_hir::def_id::DefId;
88
use rustc_infer::traits::query::NoSolution;
99
use rustc_infer::traits::util::elaborate_predicates;
@@ -459,4 +459,78 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
459459
}
460460
}
461461
}
462+
463+
#[instrument(level = "debug", skip(self), ret)]
464+
pub(super) fn merge_candidates_and_discard_reservation_impls(
465+
&mut self,
466+
mut candidates: Vec<Candidate<'tcx>>,
467+
) -> QueryResult<'tcx> {
468+
match candidates.len() {
469+
0 => return Err(NoSolution),
470+
1 => return Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result),
471+
_ => {}
472+
}
473+
474+
if candidates.len() > 1 {
475+
let mut i = 0;
476+
'outer: while i < candidates.len() {
477+
for j in (0..candidates.len()).filter(|&j| i != j) {
478+
if self.trait_candidate_should_be_dropped_in_favor_of(
479+
&candidates[i],
480+
&candidates[j],
481+
) {
482+
debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
483+
candidates.swap_remove(i);
484+
continue 'outer;
485+
}
486+
}
487+
488+
debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
489+
i += 1;
490+
}
491+
492+
// If there are *STILL* multiple candidates, give up
493+
// and report ambiguity.
494+
if candidates.len() > 1 {
495+
let certainty = if candidates.iter().all(|x| {
496+
matches!(x.result.value.certainty, Certainty::Maybe(MaybeCause::Overflow))
497+
}) {
498+
Certainty::Maybe(MaybeCause::Overflow)
499+
} else {
500+
Certainty::AMBIGUOUS
501+
};
502+
return self.make_canonical_response(certainty);
503+
}
504+
}
505+
506+
Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result)
507+
}
508+
509+
fn trait_candidate_should_be_dropped_in_favor_of(
510+
&self,
511+
candidate: &Candidate<'tcx>,
512+
other: &Candidate<'tcx>,
513+
) -> bool {
514+
// FIXME: implement this
515+
match (candidate.source, other.source) {
516+
(CandidateSource::Impl(_), _)
517+
| (CandidateSource::ParamEnv(_), _)
518+
| (CandidateSource::AliasBound, _)
519+
| (CandidateSource::BuiltinImpl, _) => false,
520+
}
521+
}
522+
523+
fn discard_reservation_impl(&self, mut candidate: Candidate<'tcx>) -> Candidate<'tcx> {
524+
if let CandidateSource::Impl(def_id) = candidate.source {
525+
if let ty::ImplPolarity::Reservation = self.tcx().impl_polarity(def_id) {
526+
debug!("Selected reservation impl");
527+
// We assemble all candidates inside of a probe so by
528+
// making a new canonical response here our result will
529+
// have no constraints.
530+
candidate.result = self.make_canonical_response(Certainty::AMBIGUOUS).unwrap();
531+
}
532+
}
533+
534+
candidate
535+
}
462536
}

compiler/rustc_trait_selection/src/solve/project_goals.rs

+3-62
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::traits::{specialization_graph, translate_substs};
22

3-
use super::assembly::{self, Candidate, CandidateSource};
3+
use super::assembly;
44
use super::infcx_ext::InferCtxtExt;
55
use super::trait_goals::structural_traits;
6-
use super::{Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
6+
use super::{Certainty, EvalCtxt, Goal, QueryResult};
77
use rustc_errors::ErrorGuaranteed;
88
use rustc_hir::def::DefKind;
99
use rustc_hir::def_id::DefId;
@@ -34,7 +34,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
3434
// projection cache in the solver.
3535
if self.term_is_fully_unconstrained(goal) {
3636
let candidates = self.assemble_and_evaluate_candidates(goal);
37-
self.merge_project_candidates(candidates)
37+
self.merge_candidates_and_discard_reservation_impls(candidates)
3838
} else {
3939
let predicate = goal.predicate;
4040
let unconstrained_rhs = match predicate.term.unpack() {
@@ -153,65 +153,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
153153

154154
self.make_canonical_response(normalization_certainty.unify_and(rhs_certainty))
155155
}
156-
157-
fn merge_project_candidates(
158-
&mut self,
159-
mut candidates: Vec<Candidate<'tcx>>,
160-
) -> QueryResult<'tcx> {
161-
match candidates.len() {
162-
0 => return Err(NoSolution),
163-
1 => return Ok(candidates.pop().unwrap().result),
164-
_ => {}
165-
}
166-
167-
if candidates.len() > 1 {
168-
let mut i = 0;
169-
'outer: while i < candidates.len() {
170-
for j in (0..candidates.len()).filter(|&j| i != j) {
171-
if self.project_candidate_should_be_dropped_in_favor_of(
172-
&candidates[i],
173-
&candidates[j],
174-
) {
175-
debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
176-
candidates.swap_remove(i);
177-
continue 'outer;
178-
}
179-
}
180-
181-
debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
182-
// If there are *STILL* multiple candidates, give up
183-
// and report ambiguity.
184-
i += 1;
185-
}
186-
187-
if candidates.len() > 1 {
188-
let certainty = if candidates.iter().all(|x| {
189-
matches!(x.result.value.certainty, Certainty::Maybe(MaybeCause::Overflow))
190-
}) {
191-
Certainty::Maybe(MaybeCause::Overflow)
192-
} else {
193-
Certainty::AMBIGUOUS
194-
};
195-
return self.make_canonical_response(certainty);
196-
}
197-
}
198-
199-
Ok(candidates.pop().unwrap().result)
200-
}
201-
202-
fn project_candidate_should_be_dropped_in_favor_of(
203-
&self,
204-
candidate: &Candidate<'tcx>,
205-
other: &Candidate<'tcx>,
206-
) -> bool {
207-
// FIXME: implement this
208-
match (candidate.source, other.source) {
209-
(CandidateSource::Impl(_), _)
210-
| (CandidateSource::ParamEnv(_), _)
211-
| (CandidateSource::BuiltinImpl, _)
212-
| (CandidateSource::AliasBound, _) => false,
213-
}
214-
}
215156
}
216157

217158
impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+3-77
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
33
use std::iter;
44

5-
use super::assembly::{self, Candidate, CandidateSource};
5+
use super::assembly;
66
use super::infcx_ext::InferCtxtExt;
7-
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
7+
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
88
use rustc_hir::def_id::DefId;
99
use rustc_infer::infer::InferCtxt;
1010
use rustc_infer::traits::query::NoSolution;
@@ -479,80 +479,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
479479
goal: Goal<'tcx, TraitPredicate<'tcx>>,
480480
) -> QueryResult<'tcx> {
481481
let candidates = self.assemble_and_evaluate_candidates(goal);
482-
self.merge_trait_candidates_discard_reservation_impls(candidates)
483-
}
484-
485-
#[instrument(level = "debug", skip(self), ret)]
486-
pub(super) fn merge_trait_candidates_discard_reservation_impls(
487-
&mut self,
488-
mut candidates: Vec<Candidate<'tcx>>,
489-
) -> QueryResult<'tcx> {
490-
match candidates.len() {
491-
0 => return Err(NoSolution),
492-
1 => return Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result),
493-
_ => {}
494-
}
495-
496-
if candidates.len() > 1 {
497-
let mut i = 0;
498-
'outer: while i < candidates.len() {
499-
for j in (0..candidates.len()).filter(|&j| i != j) {
500-
if self.trait_candidate_should_be_dropped_in_favor_of(
501-
&candidates[i],
502-
&candidates[j],
503-
) {
504-
debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
505-
candidates.swap_remove(i);
506-
continue 'outer;
507-
}
508-
}
509-
510-
debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
511-
// If there are *STILL* multiple candidates, give up
512-
// and report ambiguity.
513-
i += 1;
514-
}
515-
516-
if candidates.len() > 1 {
517-
let certainty = if candidates.iter().all(|x| {
518-
matches!(x.result.value.certainty, Certainty::Maybe(MaybeCause::Overflow))
519-
}) {
520-
Certainty::Maybe(MaybeCause::Overflow)
521-
} else {
522-
Certainty::AMBIGUOUS
523-
};
524-
return self.make_canonical_response(certainty);
525-
}
526-
}
527-
528-
Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result)
529-
}
530-
531-
fn trait_candidate_should_be_dropped_in_favor_of(
532-
&self,
533-
candidate: &Candidate<'tcx>,
534-
other: &Candidate<'tcx>,
535-
) -> bool {
536-
// FIXME: implement this
537-
match (candidate.source, other.source) {
538-
(CandidateSource::Impl(_), _)
539-
| (CandidateSource::ParamEnv(_), _)
540-
| (CandidateSource::AliasBound, _)
541-
| (CandidateSource::BuiltinImpl, _) => false,
542-
}
543-
}
544-
545-
fn discard_reservation_impl(&self, mut candidate: Candidate<'tcx>) -> Candidate<'tcx> {
546-
if let CandidateSource::Impl(def_id) = candidate.source {
547-
if let ty::ImplPolarity::Reservation = self.tcx().impl_polarity(def_id) {
548-
debug!("Selected reservation impl");
549-
// We assemble all candidates inside of a probe so by
550-
// making a new canonical response here our result will
551-
// have no constraints.
552-
candidate.result = self.make_canonical_response(Certainty::AMBIGUOUS).unwrap();
553-
}
554-
}
555-
556-
candidate
482+
self.merge_candidates_and_discard_reservation_impls(candidates)
557483
}
558484
}

0 commit comments

Comments
 (0)