2
2
3
3
#[ cfg( doc) ]
4
4
use super :: trait_goals:: structural_traits:: * ;
5
- use super :: EvalCtxt ;
5
+ use super :: { EvalCtxt , SolverMode } ;
6
+ use crate :: traits:: coherence;
6
7
use itertools:: Itertools ;
7
8
use rustc_hir:: def_id:: DefId ;
8
9
use rustc_infer:: traits:: query:: NoSolution ;
@@ -87,6 +88,8 @@ pub(super) enum CandidateSource {
87
88
pub ( super ) trait GoalKind < ' tcx > : TypeFoldable < TyCtxt < ' tcx > > + Copy + Eq {
88
89
fn self_ty ( self ) -> Ty < ' tcx > ;
89
90
91
+ fn trait_ref ( self , tcx : TyCtxt < ' tcx > ) -> ty:: TraitRef < ' tcx > ;
92
+
90
93
fn with_self_ty ( self , tcx : TyCtxt < ' tcx > , self_ty : Ty < ' tcx > ) -> Self ;
91
94
92
95
fn trait_def_id ( self , tcx : TyCtxt < ' tcx > ) -> DefId ;
@@ -244,15 +247,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
244
247
245
248
self . assemble_object_bound_candidates ( goal, & mut candidates) ;
246
249
250
+ self . assemble_coherence_unknowable_candidates ( goal, & mut candidates) ;
251
+
247
252
candidates
248
253
}
249
254
250
255
/// If the self type of a goal is a projection, computing the relevant candidates is difficult.
251
256
///
252
257
/// To deal with this, we first try to normalize the self type and add the candidates for the normalized
253
- /// self type to the list of candidates in case that succeeds. Note that we can't just eagerly return in
254
- /// this case as projections as self types add
255
- // FIXME complete the unfinished sentence above
258
+ /// self type to the list of candidates in case that succeeds. We also have to consider candidates with the
259
+ /// projection as a self type as well
256
260
fn assemble_candidates_after_normalizing_self_ty < G : GoalKind < ' tcx > > (
257
261
& mut self ,
258
262
goal : Goal < ' tcx , G > ,
@@ -468,25 +472,49 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
468
472
}
469
473
}
470
474
475
+ fn assemble_coherence_unknowable_candidates < G : GoalKind < ' tcx > > (
476
+ & mut self ,
477
+ goal : Goal < ' tcx , G > ,
478
+ candidates : & mut Vec < Candidate < ' tcx > > ,
479
+ ) {
480
+ match self . solver_mode ( ) {
481
+ SolverMode :: Normal => return ,
482
+ SolverMode :: Coherence => {
483
+ let trait_ref = goal. predicate . trait_ref ( self . tcx ( ) ) ;
484
+ match coherence:: trait_ref_is_knowable ( self . tcx ( ) , trait_ref) {
485
+ Ok ( ( ) ) => { }
486
+ Err ( _) => match self
487
+ . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
488
+ {
489
+ Ok ( result) => candidates
490
+ . push ( Candidate { source : CandidateSource :: BuiltinImpl , result } ) ,
491
+ // FIXME: This will be reachable at some point if we're in
492
+ // `assemble_candidates_after_normalizing_self_ty` and we get a
493
+ // universe error. We'll deal with it at this point.
494
+ Err ( NoSolution ) => bug ! ( "coherence candidate resulted in NoSolution" ) ,
495
+ } ,
496
+ }
497
+ }
498
+ }
499
+ }
500
+
471
501
#[ instrument( level = "debug" , skip( self ) , ret) ]
472
- pub ( super ) fn merge_candidates_and_discard_reservation_impls (
502
+ pub ( super ) fn merge_candidates (
473
503
& mut self ,
474
504
mut candidates : Vec < Candidate < ' tcx > > ,
475
505
) -> QueryResult < ' tcx > {
476
506
match candidates. len ( ) {
477
507
0 => return Err ( NoSolution ) ,
478
- 1 => return Ok ( self . discard_reservation_impl ( candidates. pop ( ) . unwrap ( ) ) . result ) ,
508
+ 1 => return Ok ( candidates. pop ( ) . unwrap ( ) . result ) ,
479
509
_ => { }
480
510
}
481
511
482
512
if candidates. len ( ) > 1 {
483
513
let mut i = 0 ;
484
514
' outer: while i < candidates. len ( ) {
485
515
for j in ( 0 ..candidates. len ( ) ) . filter ( |& j| i != j) {
486
- if self . trait_candidate_should_be_dropped_in_favor_of (
487
- & candidates[ i] ,
488
- & candidates[ j] ,
489
- ) {
516
+ if self . candidate_should_be_dropped_in_favor_of ( & candidates[ i] , & candidates[ j] )
517
+ {
490
518
debug ! ( candidate = ?candidates[ i] , "Dropping candidate #{}/{}" , i, candidates. len( ) ) ;
491
519
candidates. swap_remove ( i) ;
492
520
continue ' outer;
@@ -511,11 +539,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
511
539
}
512
540
}
513
541
514
- // FIXME: What if there are >1 candidates left with the same response, and one is a reservation impl?
515
- Ok ( self . discard_reservation_impl ( candidates. pop ( ) . unwrap ( ) ) . result )
542
+ Ok ( candidates. pop ( ) . unwrap ( ) . result )
516
543
}
517
544
518
- fn trait_candidate_should_be_dropped_in_favor_of (
545
+ fn candidate_should_be_dropped_in_favor_of (
519
546
& self ,
520
547
candidate : & Candidate < ' tcx > ,
521
548
other : & Candidate < ' tcx > ,
@@ -528,20 +555,4 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
528
555
| ( CandidateSource :: BuiltinImpl , _) => false ,
529
556
}
530
557
}
531
-
532
- fn discard_reservation_impl ( & mut self , mut candidate : Candidate < ' tcx > ) -> Candidate < ' tcx > {
533
- if let CandidateSource :: Impl ( def_id) = candidate. source {
534
- if let ty:: ImplPolarity :: Reservation = self . tcx ( ) . impl_polarity ( def_id) {
535
- debug ! ( "Selected reservation impl" ) ;
536
- // We assemble all candidates inside of a probe so by
537
- // making a new canonical response here our result will
538
- // have no constraints.
539
- candidate. result = self
540
- . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
541
- . unwrap ( ) ;
542
- }
543
- }
544
-
545
- candidate
546
- }
547
558
}
0 commit comments