@@ -42,7 +42,7 @@ use rustc_hir as hir;
42
42
use rustc_hir:: def_id:: DefId ;
43
43
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
44
44
use rustc_infer:: infer:: { Coercion , InferOk , InferResult } ;
45
- use rustc_infer:: traits:: Obligation ;
45
+ use rustc_infer:: traits:: { Obligation , TraitEngine , TraitEngineExt } ;
46
46
use rustc_middle:: lint:: in_external_macro;
47
47
use rustc_middle:: ty:: adjustment:: {
48
48
Adjust , Adjustment , AllowTwoPhase , AutoBorrow , AutoBorrowMutability , PointerCast ,
@@ -146,6 +146,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
146
146
. and_then ( |InferOk { value : ty, obligations } | success ( f ( ty) , ty, obligations) )
147
147
}
148
148
149
+ #[ instrument( skip( self ) ) ]
149
150
fn coerce ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
150
151
// First, remove any resolved type variables (at the top level, at least):
151
152
let a = self . shallow_resolve ( a) ;
@@ -933,14 +934,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
933
934
}
934
935
935
936
/// Same as `try_coerce()`, but without side-effects.
937
+ ///
938
+ /// Returns false if the coercion creates any obligations that result in
939
+ /// errors.
936
940
pub fn can_coerce ( & self , expr_ty : Ty < ' tcx > , target : Ty < ' tcx > ) -> bool {
937
941
let source = self . resolve_vars_with_obligations ( expr_ty) ;
938
- debug ! ( "coercion::can ({:?} -> {:?})" , source, target) ;
942
+ debug ! ( "coercion::can_with_predicates ({:?} -> {:?})" , source, target) ;
939
943
940
944
let cause = self . cause ( rustc_span:: DUMMY_SP , ObligationCauseCode :: ExprAssignable ) ;
941
945
// We don't ever need two-phase here since we throw out the result of the coercion
942
946
let coerce = Coerce :: new ( self , cause, AllowTwoPhase :: No ) ;
943
- self . probe ( |_| coerce. coerce ( source, target) ) . is_ok ( )
947
+ self . probe ( |_| {
948
+ let ok = match coerce. coerce ( source, target) {
949
+ Ok ( ok) => ok,
950
+ _ => return false ,
951
+ } ;
952
+ let mut fcx = traits:: FulfillmentContext :: new_in_snapshot ( ) ;
953
+ fcx. register_predicate_obligations ( self , ok. obligations ) ;
954
+ fcx. select_where_possible ( & self ) . is_ok ( )
955
+ } )
944
956
}
945
957
946
958
/// Given a type and a target type, this function will calculate and return
0 commit comments