@@ -627,6 +627,7 @@ struct InferredPath<'tcx> {
627627 span : Span ,
628628 ty : Option < Ty < ' tcx > > ,
629629 args : Option < Cow < ' tcx , [ Ty < ' tcx > ] > > ,
630+ unresolved_vars : Vec < Vec < Ty < ' tcx > > > ,
630631}
631632
632633impl < ' a , ' tcx > Deref for FnCtxt < ' a , ' tcx > {
@@ -1069,28 +1070,72 @@ fn typeck_tables_of_with_fallback<'tcx>(
10691070 . borrow ( )
10701071 . iter ( )
10711072 . map ( |( id, path) | ( * id, path. clone ( ) ) )
1072- . filter ( |( hir_id, path) | {
1073+ . filter_map ( |( hir_id, mut path) | {
10731074 debug ! (
10741075 "typeck_tables_of_with_fallback: inspecting path ({:?}, {:?})" ,
10751076 hir_id, path
10761077 ) ;
1077- let debug_resolved = fcx. infcx . resolve_vars_if_possible ( & path. ty ) ;
1078- if fcx. infcx . unresolved_type_vars ( & path. ty ) . is_some ( ) {
1078+
1079+ let ty_resolved = fcx. infcx . resolve_vars_if_possible ( & path. ty ) ;
1080+
1081+ let fn_substs = match ty_resolved {
1082+ Some ( ty:: TyS { kind : ty:: FnDef ( _, substs) , .. } ) => substs,
1083+ _ => {
1084+ debug ! (
1085+ "typeck_tables_of_with_fallback: non-fn ty {:?}, skipping" ,
1086+ ty_resolved
1087+ ) ;
1088+ return None ;
1089+ }
1090+ } ;
1091+
1092+ if fcx. infcx . unresolved_type_vars ( fn_substs) . is_some ( ) {
1093+ struct TyVarFinder < ' a , ' tcx > {
1094+ infcx : & ' a InferCtxt < ' a , ' tcx > ,
1095+ vars : Vec < Ty < ' tcx > > ,
1096+ }
1097+ impl < ' a , ' tcx > TypeFolder < ' tcx > for TyVarFinder < ' a , ' tcx > {
1098+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
1099+ self . infcx . tcx
1100+ }
1101+
1102+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
1103+ if let ty:: Infer ( ty:: InferTy :: TyVar ( _) ) = t. kind {
1104+ self . vars . push ( t) ;
1105+ }
1106+ t. super_fold_with ( self )
1107+ }
1108+ }
1109+
1110+ for subst in fn_substs. types ( ) {
1111+ let mut finder = TyVarFinder { infcx : & fcx. infcx , vars : vec ! [ ] } ;
1112+ path. ty . fold_with ( & mut finder) ;
1113+ path. unresolved_vars . push ( finder. vars ) ;
1114+ }
1115+
10791116 debug ! (
1080- "typeck_tables_of_with_fallback: unresolved vars in ty: {:?}" ,
1081- debug_resolved
1117+ "typeck_tables_of_with_fallback: unresolved vars in ty {:?} : {:?}" ,
1118+ ty_resolved , path . unresolved_vars
10821119 ) ;
1083- true
1120+
1121+ Some ( ( hir_id, path) )
10841122 } else {
10851123 debug ! (
10861124 "typeck_tables_of_with_fallback: all vars resolved in ty: {:?}" ,
1087- debug_resolved
1125+ ty_resolved
10881126 ) ;
1089- false
1127+ None
10901128 }
10911129 } )
10921130 . collect ( ) ;
10931131
1132+ let unconstrained_diverging: Vec < _ > = fcx
1133+ . unsolved_variables ( )
1134+ . iter ( )
1135+ . cloned ( )
1136+ . filter ( |ty| fcx. infcx . type_var_diverges ( ty) )
1137+ . collect ( ) ;
1138+
10941139 // We do fallback in two passes, to try to generate
10951140 // better error messages.
10961141 // The first time, we do *not* replace opaque types.
@@ -1150,7 +1195,7 @@ fn typeck_tables_of_with_fallback<'tcx>(
11501195 if let ty:: FnDef ( _, substs) = ty. kind {
11511196 debug ! ( "Got substs: {:?}" , substs) ;
11521197 let mut args_inhabited = true ;
1153- let mut substs_inhabited = true ;
1198+ let mut uninhabited_subst = None ;
11541199
11551200 for arg in & * path. args . unwrap ( ) {
11561201 let resolved_arg = fcx. infcx . resolve_vars_if_possible ( arg) ;
@@ -1164,25 +1209,82 @@ fn typeck_tables_of_with_fallback<'tcx>(
11641209 }
11651210 }
11661211
1167- for subst_ty in substs. types ( ) {
1212+ for ( subst_ty, vars ) in substs. types ( ) . zip ( path . unresolved_vars . into_iter ( ) ) {
11681213 let resolved_subst = fcx. infcx . resolve_vars_if_possible ( & subst_ty) ;
11691214 if resolved_subst. conservative_is_privately_uninhabited ( tcx) {
11701215 debug ! ( "Subst is uninhabited: {:?}" , resolved_subst) ;
1171- substs_inhabited = false ;
1172- break ;
1216+ if !vars. is_empty ( ) {
1217+ debug ! ( "Found fallback vars: {:?}" , vars) ;
1218+ uninhabited_subst = Some ( ( resolved_subst, vars) ) ;
1219+ break ;
1220+ } else {
1221+ debug ! ( "No fallback vars" )
1222+ }
11731223 } else {
11741224 debug ! ( "Subst is inhabited: {:?}" , resolved_subst) ;
11751225 }
11761226 }
11771227
1178- if args_inhabited && !substs_inhabited {
1228+ if let ( true , Some ( ( subst , vars ) ) ) = ( args_inhabited , uninhabited_subst ) {
11791229 debug ! ( "All arguments are inhabited, at least one subst is not inhabited!" ) ;
1230+
1231+ let mut best_diverging_var = None ;
1232+ let mut best_var = None ;
1233+
1234+ for var in vars {
1235+ for diverging_var in & unconstrained_diverging {
1236+ match ( & var. kind , & diverging_var. kind ) {
1237+ (
1238+ ty:: Infer ( ty:: InferTy :: TyVar ( vid1) ) ,
1239+ ty:: Infer ( ty:: InferTy :: TyVar ( vid2) ) ,
1240+ ) => {
1241+ if fcx
1242+ . infcx
1243+ . type_variables
1244+ . borrow_mut ( )
1245+ . sub_unified ( * vid1, * vid2)
1246+ {
1247+ debug ! (
1248+ "Type variable {:?} is equal to diverging var {:?}" ,
1249+ var, diverging_var
1250+ ) ;
1251+ best_var = Some ( var) ;
1252+ best_diverging_var = Some ( diverging_var) ;
1253+ }
1254+ }
1255+ _ => bug ! (
1256+ "Unexpected types: var={:?} diverging_var={:?}" ,
1257+ var,
1258+ diverging_var
1259+ ) ,
1260+ }
1261+ }
1262+ }
1263+
1264+ let ( var_span, diverging_var_span) =
1265+ match ( & best_var. unwrap ( ) . kind , & best_diverging_var. unwrap ( ) . kind ) {
1266+ (
1267+ ty:: Infer ( ty:: InferTy :: TyVar ( var_vid) ) ,
1268+ ty:: Infer ( ty:: InferTy :: TyVar ( diverging_var_vid) ) ,
1269+ ) => (
1270+ fcx. infcx . type_variables . borrow ( ) . var_origin ( * var_vid) . span ,
1271+ fcx. infcx
1272+ . type_variables
1273+ . borrow ( )
1274+ . var_origin ( * diverging_var_vid)
1275+ . span ,
1276+ ) ,
1277+ _ => bug ! ( "Type is not a ty variable: {:?}" , best_var) ,
1278+ } ;
1279+
11801280 fcx. tcx ( )
11811281 . sess
11821282 . struct_span_warn (
11831283 path. span ,
11841284 "Fallback to `!` may introduce undefined behavior" ,
11851285 )
1286+ . span_note ( var_span, "the type here was inferred to `!`" )
1287+ . span_note ( diverging_var_span, "... due to this expression" )
11861288 . emit ( ) ;
11871289 }
11881290 }
@@ -3837,7 +3939,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38373939 match self . inferred_paths . borrow_mut ( ) . entry ( expr. hir_id ) {
38383940 Entry :: Vacant ( e) => {
38393941 debug ! ( "check_argument_types: making new entry for types {:?}" , fn_inputs) ;
3840- e. insert ( InferredPath { span : sp, ty : None , args : Some ( fn_inputs. clone ( ) ) } ) ;
3942+ e. insert ( InferredPath {
3943+ span : sp,
3944+ ty : None ,
3945+ args : Some ( fn_inputs. clone ( ) ) ,
3946+ unresolved_vars : vec ! [ ] ,
3947+ } ) ;
38413948 }
38423949 Entry :: Occupied ( mut e) => {
38433950 debug ! (
@@ -5552,6 +5659,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
55525659 span : * p_span,
55535660 ty : Some ( ty_substituted) ,
55545661 args : None ,
5662+ unresolved_vars : vec ! [ ] ,
55555663 } ) ;
55565664 }
55575665 Entry :: Occupied ( mut e) => {
0 commit comments