Skip to content

Commit 5253bb6

Browse files
committed
Factor out code into its own module
1 parent ebf1918 commit 5253bb6

File tree

2 files changed

+218
-195
lines changed

2 files changed

+218
-195
lines changed

src/librustc_typeck/check/mod.rs

+3-195
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ mod expr;
8080
mod generator_interior;
8181
pub mod intrinsic;
8282
pub mod method;
83+
mod never_compat;
8384
mod op;
8485
mod pat;
8586
mod 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

Comments
 (0)