Skip to content

Commit 10cd2e3

Browse files
committed
Work on splitting up post_fallback
1 parent 932d7c2 commit 10cd2e3

File tree

1 file changed

+104
-109
lines changed

1 file changed

+104
-109
lines changed

src/librustc_typeck/check/never_compat.rs

+104-109
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,58 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TyVarFinder<'a, 'tcx> {
3434
}
3535
}
3636

37+
fn find_questionable_call(
38+
path: InferredPath<'tcx>,
39+
fcx: &FnCtxt<'a, 'tcx>,
40+
) -> Option<Vec<Ty<'tcx>>> {
41+
let tcx = fcx.tcx;
42+
let ty = fcx.infcx.resolve_vars_if_possible(&path.ty);
43+
debug!("post_fallback: Fully resolved ty: {:?}", ty);
44+
45+
let ty = ty.unwrap_or_else(|| bug!("Missing ty in path: {:?}", path));
46+
47+
if let ty::FnDef(_, substs) = ty.kind {
48+
debug!("Got substs: {:?}", substs);
49+
let mut args_inhabited = true;
50+
51+
for arg in &*path.args.unwrap() {
52+
let resolved_arg = fcx.infcx.resolve_vars_if_possible(arg);
53+
54+
if resolved_arg.conservative_is_privately_uninhabited(tcx) {
55+
debug!("post_fallback: Arg is uninhabited: {:?}", resolved_arg);
56+
args_inhabited = false;
57+
break;
58+
} else {
59+
debug!("post_fallback: Arg is inhabited: {:?}", resolved_arg);
60+
}
61+
}
62+
63+
if !args_inhabited {
64+
debug!("post_fallback: Not all arguments are inhabited");
65+
return None;
66+
}
67+
68+
for (subst_ty, vars) in substs.types().zip(path.unresolved_vars.into_iter()) {
69+
let resolved_subst = fcx.infcx.resolve_vars_if_possible(&subst_ty);
70+
if resolved_subst.conservative_is_privately_uninhabited(tcx) {
71+
debug!("post_fallback: Subst is uninhabited: {:?}", resolved_subst);
72+
if !vars.is_empty() {
73+
debug!("Found fallback vars: {:?}", vars);
74+
debug!(
75+
"post_fallback: All arguments are inhabited, at least one subst is not inhabited!"
76+
);
77+
return Some(vars);
78+
} else {
79+
debug!("No fallback vars")
80+
}
81+
} else {
82+
debug!("post_fallback: Subst is inhabited: {:?}", resolved_subst);
83+
}
84+
}
85+
}
86+
return None;
87+
}
88+
3789
impl<'tcx> NeverCompatHandler<'tcx> {
3890
pub fn pre_fallback(fcx: &FnCtxt<'a, 'tcx>) -> NeverCompatHandler<'tcx> {
3991
let unresolved_paths: FxHashMap<HirId, InferredPath<'tcx>> = fcx
@@ -88,132 +140,75 @@ impl<'tcx> NeverCompatHandler<'tcx> {
88140
let tcx = fcx.tcx;
89141
for (call_id, path) in self.unresolved_paths {
90142
debug!(
91-
"Resolved ty: {:?} at span {:?} : expr={:?} parent={:?} path={:?}",
143+
"post_fallback: resolved ty: {:?} at span {:?} : expr={:?} parent={:?} path={:?}",
92144
path.span,
93145
path.ty,
94146
tcx.hir().get(call_id),
95147
tcx.hir().get(tcx.hir().get_parent_node(call_id)),
96148
path
97149
);
98150

99-
let ty = fcx.infcx.resolve_vars_if_possible(&path.ty);
100-
debug!("Fully resolved ty: {:?}", ty);
101-
102-
let ty = ty.unwrap_or_else(|| bug!("Missing ty in path: {:?}", path));
103-
104-
if let ty::FnDef(_, substs) = ty.kind {
105-
debug!("Got substs: {:?}", substs);
106-
let mut args_inhabited = true;
107-
let mut uninhabited_subst = None;
108-
109-
for arg in &*path.args.unwrap() {
110-
let resolved_arg = fcx.infcx.resolve_vars_if_possible(arg);
111-
112-
if resolved_arg.conservative_is_privately_uninhabited(tcx) {
113-
debug!("Arg is uninhabited: {:?}", resolved_arg);
114-
args_inhabited = false;
115-
break;
116-
} else {
117-
debug!("Arg is inhabited: {:?}", resolved_arg);
118-
}
119-
}
120-
121-
for (subst_ty, vars) in substs.types().zip(path.unresolved_vars.into_iter()) {
122-
let resolved_subst = fcx.infcx.resolve_vars_if_possible(&subst_ty);
123-
if resolved_subst.conservative_is_privately_uninhabited(tcx) {
124-
debug!("Subst is uninhabited: {:?}", resolved_subst);
125-
if !vars.is_empty() {
126-
debug!("Found fallback vars: {:?}", vars);
127-
uninhabited_subst = Some(vars);
128-
break;
129-
} else {
130-
debug!("No fallback vars")
131-
}
132-
} else {
133-
debug!("Subst is inhabited: {:?}", resolved_subst);
134-
}
135-
}
136-
137-
if let (true, Some(vars)) = (args_inhabited, uninhabited_subst) {
138-
debug!("All arguments are inhabited, at least one subst is not inhabited!");
139-
140-
let mut best_diverging_var = None;
141-
let mut best_var = None;
142-
143-
for var in vars {
144-
for diverging_var in &self.unconstrained_diverging {
145-
match (&var.kind, &diverging_var.kind) {
146-
(
147-
ty::Infer(ty::InferTy::TyVar(vid1)),
148-
ty::Infer(ty::InferTy::TyVar(vid2)),
149-
) => {
150-
if fcx
151-
.infcx
152-
.type_variables
153-
.borrow_mut()
154-
.sub_unified(*vid1, *vid2)
155-
{
156-
debug!(
157-
"Type variable {:?} is equal to diverging var {:?}",
158-
var, diverging_var
159-
);
160-
161-
debug!(
162-
"Var origin: {:?}",
163-
fcx.infcx.type_variables.borrow().var_origin(*vid1)
164-
);
165-
best_var = Some(vid1);
166-
best_diverging_var = Some(vid2);
167-
}
151+
let span = path.span;
152+
if let Some(vars) = find_questionable_call(path, fcx) {
153+
let mut best_diverging_var = None;
154+
let mut best_var = None;
155+
156+
for var in vars {
157+
for diverging_var in &self.unconstrained_diverging {
158+
match (&var.kind, &diverging_var.kind) {
159+
(
160+
ty::Infer(ty::InferTy::TyVar(vid1)),
161+
ty::Infer(ty::InferTy::TyVar(vid2)),
162+
) => {
163+
if fcx.infcx.type_variables.borrow_mut().sub_unified(*vid1, *vid2) {
164+
debug!(
165+
"Type variable {:?} is equal to diverging var {:?}",
166+
var, diverging_var
167+
);
168+
169+
debug!(
170+
"Var origin: {:?}",
171+
fcx.infcx.type_variables.borrow().var_origin(*vid1)
172+
);
173+
best_var = Some(vid1);
174+
best_diverging_var = Some(vid2);
168175
}
169-
_ => bug!(
170-
"Unexpected types: var={:?} diverging_var={:?}",
171-
var,
172-
diverging_var
173-
),
174176
}
177+
_ => bug!(
178+
"Unexpected types: var={:?} diverging_var={:?}",
179+
var,
180+
diverging_var
181+
),
175182
}
176183
}
184+
}
177185

178-
let var_origin =
179-
*fcx.infcx.type_variables.borrow().var_origin(*best_var.unwrap());
180-
let diverging_var_span = fcx
181-
.infcx
182-
.type_variables
183-
.borrow()
184-
.var_origin(*best_diverging_var.unwrap())
185-
.span;
186-
187-
let mut err = tcx.sess.struct_span_warn(
188-
path.span,
189-
"Fallback to `!` may introduce undefined behavior",
190-
);
191-
192-
match var_origin.kind {
193-
TypeVariableOriginKind::TypeParameterDefinition(name, did) => {
194-
err.span_note(
195-
var_origin.span,
196-
&format!("the type parameter {} here was inferred to `!`", name),
197-
);
198-
if let Some(did) = did {
199-
err.span_note(
200-
fcx.tcx.def_span(did),
201-
"(type parameter defined here)",
202-
);
203-
}
204-
}
205-
_ => {
206-
err.span_note(var_origin.span, "the type here was inferred to `!`");
186+
let var_origin = *fcx.infcx.type_variables.borrow().var_origin(*best_var.unwrap());
187+
let diverging_var_span =
188+
fcx.infcx.type_variables.borrow().var_origin(*best_diverging_var.unwrap()).span;
189+
190+
let mut err = tcx
191+
.sess
192+
.struct_span_warn(span, "Fallback to `!` may introduce undefined behavior");
193+
194+
match var_origin.kind {
195+
TypeVariableOriginKind::TypeParameterDefinition(name, did) => {
196+
err.span_note(
197+
var_origin.span,
198+
&format!("the type parameter {} here was inferred to `!`", name),
199+
);
200+
if let Some(did) = did {
201+
err.span_note(fcx.tcx.def_span(did), "(type parameter defined here)");
207202
}
208203
}
204+
_ => {
205+
err.span_note(var_origin.span, "the type here was inferred to `!`");
206+
}
207+
}
209208

210-
err.span_note(
211-
diverging_var_span,
212-
"... due to this expression evaluating to `!`",
213-
)
209+
err.span_note(diverging_var_span, "... due to this expression evaluating to `!`")
214210
.note("If you want the `!` type to be used here, add explicit type annotations")
215211
.emit();
216-
}
217212
}
218213
}
219214
}

0 commit comments

Comments
 (0)