@@ -5,7 +5,8 @@ use rustc_data_structures::{
5
5
graph:: { iterate:: DepthFirstSearch , vec_graph:: VecGraph } ,
6
6
stable_set:: FxHashSet ,
7
7
} ;
8
- use rustc_middle:: ty:: { self , Ty } ;
8
+ use rustc_infer:: traits:: ObligationCauseCode ;
9
+ use rustc_middle:: ty:: { self , adjustment:: AllowTwoPhase , Ty , TypeFoldable } ;
9
10
10
11
impl < ' tcx > FnCtxt < ' _ , ' tcx > {
11
12
/// Performs type inference fallback, returning true if any fallback
@@ -16,6 +17,48 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
16
17
self . fulfillment_cx. borrow_mut( ) . pending_obligations( )
17
18
) ;
18
19
20
+ let mut cast_vars = Vec :: new ( ) ;
21
+
22
+ // FIXME: This seems to cause extra object safety errors. Not clear why; one would expect the probe and such to eat them.
23
+ for cast in self . deferred_cast_checks . borrow ( ) . iter ( ) {
24
+ let source = cast. expr_ty ;
25
+ let target = cast. cast_ty ;
26
+ debug ! ( "attempting coerce {:?} -> {:?}" , source, target, ) ;
27
+ let source = self . resolve_vars_with_obligations ( source) ;
28
+
29
+ let cause = self . cause ( rustc_span:: DUMMY_SP , ObligationCauseCode :: ExprAssignable ) ;
30
+ // We don't ever need two-phase here since we throw out the result of the coercion
31
+ let coerce = crate :: check:: coercion:: Coerce :: new ( self , cause, AllowTwoPhase :: No ) ;
32
+ if let Ok ( infok) = self . probe ( |_| coerce. coerce_silent ( source, target) ) {
33
+ for obligation in infok. obligations {
34
+ if let ty:: PredicateKind :: Projection ( predicate) =
35
+ obligation. predicate . kind ( ) . skip_binder ( )
36
+ {
37
+ if !predicate. projection_ty . has_escaping_bound_vars ( ) {
38
+ // FIXME: We really *should* do this even with escaping bound
39
+ // vars, but there's not much we can do here. In the worst case
40
+ // (if this ends up being important) we just don't register a relationship and then end up falling back to !,
41
+ // which is not terrible.
42
+
43
+ if let Some ( vid) = self
44
+ . fulfillment_cx
45
+ . borrow_mut ( )
46
+ . normalize_projection_type (
47
+ & self . infcx ,
48
+ obligation. param_env ,
49
+ predicate. projection_ty ,
50
+ obligation. cause . clone ( ) ,
51
+ )
52
+ . ty_vid ( )
53
+ {
54
+ cast_vars. push ( vid) ;
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+
19
62
// All type checking constraints were added, try to fallback unsolved variables.
20
63
self . select_obligations_where_possible ( false , |_| { } ) ;
21
64
@@ -36,7 +79,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
36
79
}
37
80
38
81
let diverging_fallback =
39
- self . calculate_diverging_fallback ( & unsolved_variables, & relationships) ;
82
+ self . calculate_diverging_fallback ( & unsolved_variables, & relationships, & cast_vars ) ;
40
83
41
84
// We do fallback in two passes, to try to generate
42
85
// better error messages.
@@ -263,6 +306,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
263
306
& self ,
264
307
unsolved_variables : & [ Ty < ' tcx > ] ,
265
308
relationships : & FxHashMap < ty:: TyVid , ty:: FoundRelationships > ,
309
+ cast_vars : & [ ty:: TyVid ] ,
266
310
) -> FxHashMap < Ty < ' tcx > , Ty < ' tcx > > {
267
311
debug ! ( "calculate_diverging_fallback({:?})" , unsolved_variables) ;
268
312
@@ -368,16 +412,26 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
368
412
let mut relationship = ty:: FoundRelationships { self_in_trait : false , output : false } ;
369
413
370
414
for ( vid, rel) in relationships. iter ( ) {
371
- //if self.infcx.shallow_resolve(*ty).ty_vid().map(|t| self.infcx.root_var(t))
372
415
if self . infcx . root_var ( * vid) == root_vid {
373
416
relationship. self_in_trait |= rel. self_in_trait ;
374
417
relationship. output |= rel. output ;
375
418
}
376
419
}
377
420
421
+ let mut is_cast = false ;
422
+ for vid in cast_vars. iter ( ) {
423
+ if self . infcx . root_var ( * vid) == root_vid {
424
+ is_cast = true ;
425
+ break ;
426
+ }
427
+ }
428
+
378
429
if relationship. self_in_trait && relationship. output {
379
430
debug ! ( "fallback to () - found trait and projection: {:?}" , diverging_vid) ;
380
431
diverging_fallback. insert ( diverging_ty, self . tcx . types . unit ) ;
432
+ } else if is_cast {
433
+ debug ! ( "fallback to () - interacted with cast: {:?}" , diverging_vid) ;
434
+ diverging_fallback. insert ( diverging_ty, self . tcx . types . unit ) ;
381
435
} else if can_reach_non_diverging {
382
436
debug ! ( "fallback to () - reached non-diverging: {:?}" , diverging_vid) ;
383
437
diverging_fallback. insert ( diverging_ty, self . tcx . types . unit ) ;
0 commit comments