@@ -80,6 +80,7 @@ mod expr;
8080mod generator_interior;
8181pub mod intrinsic;
8282pub mod method;
83+ mod never_compat;
8384mod op;
8485mod pat;
8586mod regionck;
@@ -1065,76 +1066,7 @@ fn typeck_tables_of_with_fallback<'tcx>(
10651066 // All type checking constraints were added, try to fallback unsolved variables.
10661067 fcx. select_obligations_where_possible ( false , |_| { } ) ;
10671068 let mut fallback_has_occurred = false ;
1068- let unresolved_paths: FxHashMap < hir:: HirId , InferredPath < ' tcx > > = fcx
1069- . inferred_paths
1070- . borrow ( )
1071- . iter ( )
1072- . map ( |( id, path) | ( * id, path. clone ( ) ) )
1073- . filter_map ( |( hir_id, mut path) | {
1074- debug ! (
1075- "typeck_tables_of_with_fallback: inspecting path ({:?}, {:?})" ,
1076- hir_id, path
1077- ) ;
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-
1116- debug ! (
1117- "typeck_tables_of_with_fallback: unresolved vars in ty {:?} : {:?}" ,
1118- ty_resolved, path. unresolved_vars
1119- ) ;
1120-
1121- Some ( ( hir_id, path) )
1122- } else {
1123- debug ! (
1124- "typeck_tables_of_with_fallback: all vars resolved in ty: {:?}" ,
1125- ty_resolved
1126- ) ;
1127- None
1128- }
1129- } )
1130- . collect ( ) ;
1131-
1132- let unconstrained_diverging: Vec < _ > = fcx
1133- . unsolved_variables ( )
1134- . iter ( )
1135- . cloned ( )
1136- . filter ( |ty| fcx. infcx . type_var_diverges ( ty) )
1137- . collect ( ) ;
1069+ let never_compat = never_compat:: NeverCompatHandler :: pre_fallback ( & fcx) ;
11381070
11391071 // We do fallback in two passes, to try to generate
11401072 // better error messages.
@@ -1177,131 +1109,7 @@ fn typeck_tables_of_with_fallback<'tcx>(
11771109 // See if we can make any more progress.
11781110 fcx. select_obligations_where_possible ( fallback_has_occurred, |_| { } ) ;
11791111
1180- for ( call_id, path) in unresolved_paths {
1181- debug ! (
1182- "Resolved ty: {:?} at span {:?} : expr={:?} parent={:?} path={:?}" ,
1183- path. span,
1184- path. ty,
1185- tcx. hir( ) . get( call_id) ,
1186- tcx. hir( ) . get( tcx. hir( ) . get_parent_node( call_id) ) ,
1187- path
1188- ) ;
1189-
1190- let ty = fcx. infcx . resolve_vars_if_possible ( & path. ty ) ;
1191- debug ! ( "Fully resolved ty: {:?}" , ty) ;
1192-
1193- let ty = ty. unwrap_or_else ( || bug ! ( "Missing ty in path: {:?}" , path) ) ;
1194-
1195- if let ty:: FnDef ( _, substs) = ty. kind {
1196- debug ! ( "Got substs: {:?}" , substs) ;
1197- let mut args_inhabited = true ;
1198- let mut uninhabited_subst = None ;
1199-
1200- for arg in & * path. args . unwrap ( ) {
1201- let resolved_arg = fcx. infcx . resolve_vars_if_possible ( arg) ;
1202-
1203- if resolved_arg. conservative_is_privately_uninhabited ( tcx) {
1204- debug ! ( "Arg is uninhabited: {:?}" , resolved_arg) ;
1205- args_inhabited = false ;
1206- break ;
1207- } else {
1208- debug ! ( "Arg is inhabited: {:?}" , resolved_arg) ;
1209- }
1210- }
1211-
1212- for ( subst_ty, vars) in substs. types ( ) . zip ( path. unresolved_vars . into_iter ( ) ) {
1213- let resolved_subst = fcx. infcx . resolve_vars_if_possible ( & subst_ty) ;
1214- if resolved_subst. conservative_is_privately_uninhabited ( tcx) {
1215- debug ! ( "Subst is uninhabited: {:?}" , resolved_subst) ;
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- }
1223- } else {
1224- debug ! ( "Subst is inhabited: {:?}" , resolved_subst) ;
1225- }
1226- }
1227-
1228- if let ( true , Some ( ( subst, vars) ) ) = ( args_inhabited, uninhabited_subst) {
1229- 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-
1252- debug ! (
1253- "Var origin: {:?}" ,
1254- fcx. infcx. type_variables. borrow( ) . var_origin( * vid1)
1255- ) ;
1256- best_var = Some ( vid1) ;
1257- best_diverging_var = Some ( vid2) ;
1258- }
1259- }
1260- _ => bug ! (
1261- "Unexpected types: var={:?} diverging_var={:?}" ,
1262- var,
1263- diverging_var
1264- ) ,
1265- }
1266- }
1267- }
1268-
1269- let var_origin =
1270- * fcx. infcx . type_variables . borrow ( ) . var_origin ( * best_var. unwrap ( ) ) ;
1271- let diverging_var_span = fcx
1272- . infcx
1273- . type_variables
1274- . borrow ( )
1275- . var_origin ( * best_diverging_var. unwrap ( ) )
1276- . span ;
1277-
1278- let mut err = fcx. tcx ( ) . sess . struct_span_warn (
1279- path. span ,
1280- "Fallback to `!` may introduce undefined behavior" ,
1281- ) ;
1282-
1283- match var_origin. kind {
1284- TypeVariableOriginKind :: TypeParameterDefinition ( name, did) => {
1285- err. span_note (
1286- var_origin. span ,
1287- & format ! ( "the type parameter {} here was inferred to `!`" , name) ,
1288- ) ;
1289- if let Some ( did) = did {
1290- err. span_note (
1291- fcx. tcx . def_span ( did) ,
1292- "(type parameter defined here)" ,
1293- ) ;
1294- }
1295- }
1296- _ => {
1297- err. span_note ( var_origin. span , "the type here was inferred to `!`" ) ;
1298- }
1299- }
1300-
1301- err. span_note ( diverging_var_span, "... due to this expression" ) . emit ( ) ;
1302- }
1303- }
1304- }
1112+ never_compat. post_fallback ( & fcx) ;
13051113
13061114 // Even though coercion casts provide type hints, we check casts after fallback for
13071115 // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
0 commit comments