Skip to content

Commit fceb523

Browse files
committed
remove reliance on "diverging" type variables
Instead, we now record those type variables that are the target of a `NeverToAny` adjustment and consider those to be the "diverging" type variables. This allows us to remove the special case logic that creates a type variable for `!` in coercion.
1 parent 8eda90e commit fceb523

File tree

4 files changed

+53
-40
lines changed

4 files changed

+53
-40
lines changed

compiler/rustc_typeck/src/check/coercion.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -163,24 +163,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
163163

164164
// Coercing from `!` to any type is allowed:
165165
if a.is_never() {
166-
// Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
167-
// type variable, we want `?T` to fallback to `!` if not
168-
// otherwise constrained. An example where this arises:
169-
//
170-
// let _: Option<?T> = Some({ return; });
171-
//
172-
// here, we would coerce from `!` to `?T`.
173-
return if b.is_ty_var() {
174-
// Micro-optimization: no need for this if `b` is
175-
// already resolved in some way.
176-
let diverging_ty = self.next_diverging_ty_var(TypeVariableOrigin {
177-
kind: TypeVariableOriginKind::AdjustmentType,
178-
span: self.cause.span,
179-
});
180-
self.coerce_from_inference_variable(diverging_ty, b, simple(Adjust::NeverToAny))
181-
} else {
182-
success(simple(Adjust::NeverToAny)(b), b, vec![])
183-
};
166+
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
184167
}
185168

186169
// Coercing *from* an unresolved inference variable means that

compiler/rustc_typeck/src/check/fallback.rs

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use crate::check::FnCtxt;
22
use rustc_data_structures::{
33
fx::FxHashMap, graph::vec_graph::VecGraph, graph::WithSuccessors, stable_set::FxHashSet,
44
};
5-
use rustc_infer::infer::type_variable::Diverging;
65
use rustc_middle::ty::{self, Ty};
76

87
impl<'tcx> FnCtxt<'_, 'tcx> {
@@ -250,8 +249,27 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
250249

251250
// Extract the unsolved type inference variable vids; note that some
252251
// unsolved variables are integer/float variables and are excluded.
253-
let unsolved_vids: Vec<_> =
254-
unsolved_variables.iter().filter_map(|ty| ty.ty_vid()).collect();
252+
let unsolved_vids = unsolved_variables.iter().filter_map(|ty| ty.ty_vid());
253+
254+
// Compute the diverging root vids D -- that is, the root vid of
255+
// those type variables that (a) are the target of a coercion from
256+
// a `!` type and (b) have not yet been solved.
257+
//
258+
// These variables are the ones that are targets for fallback to
259+
// either `!` or `()`.
260+
let diverging_roots: FxHashSet<ty::TyVid> = self
261+
.diverging_type_vars
262+
.borrow()
263+
.iter()
264+
.map(|&ty| self.infcx.shallow_resolve(ty))
265+
.filter_map(|ty| ty.ty_vid())
266+
.map(|vid| self.infcx.root_var(vid))
267+
.collect();
268+
debug!(
269+
"calculate_diverging_fallback: diverging_type_vars={:?}",
270+
self.diverging_type_vars.borrow()
271+
);
272+
debug!("calculate_diverging_fallback: diverging_roots={:?}", diverging_roots);
255273

256274
// Find all type variables that are reachable from a diverging
257275
// type variable. These will typically default to `!`, unless
@@ -260,27 +278,24 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
260278
let mut roots_reachable_from_diverging = FxHashSet::default();
261279
let mut diverging_vids = vec![];
262280
let mut non_diverging_vids = vec![];
263-
for &unsolved_vid in &unsolved_vids {
281+
for unsolved_vid in unsolved_vids {
282+
let root_vid = self.infcx.root_var(unsolved_vid);
264283
debug!(
265-
"calculate_diverging_fallback: unsolved_vid={:?} diverges={:?}",
284+
"calculate_diverging_fallback: unsolved_vid={:?} root_vid={:?} diverges={:?}",
266285
unsolved_vid,
267-
self.infcx.ty_vid_diverges(unsolved_vid)
286+
root_vid,
287+
diverging_roots.contains(&root_vid),
268288
);
269-
match self.infcx.ty_vid_diverges(unsolved_vid) {
270-
Diverging::Diverges => {
271-
diverging_vids.push(unsolved_vid);
272-
let root_vid = self.infcx.root_var(unsolved_vid);
273-
debug!(
274-
"calculate_diverging_fallback: root_vid={:?} reaches {:?}",
275-
root_vid,
276-
coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
277-
);
278-
roots_reachable_from_diverging
279-
.extend(coercion_graph.depth_first_search(root_vid));
280-
}
281-
Diverging::NotDiverging => {
282-
non_diverging_vids.push(unsolved_vid);
283-
}
289+
if diverging_roots.contains(&root_vid) {
290+
diverging_vids.push(unsolved_vid);
291+
debug!(
292+
"calculate_diverging_fallback: root_vid={:?} reaches {:?}",
293+
root_vid,
294+
coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
295+
);
296+
roots_reachable_from_diverging.extend(coercion_graph.depth_first_search(root_vid));
297+
} else {
298+
non_diverging_vids.push(unsolved_vid);
284299
}
285300
}
286301
debug!(

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
273273
return;
274274
}
275275

276+
for a in &adj {
277+
if let Adjust::NeverToAny = a.kind {
278+
if a.target.is_ty_var() {
279+
self.diverging_type_vars.borrow_mut().insert(a.target);
280+
debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
281+
}
282+
}
283+
}
284+
276285
let autoborrow_mut = adj.iter().any(|adj| {
277286
matches!(adj, &Adjustment {
278287
kind: Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. })),

compiler/rustc_typeck/src/check/inherited.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::callee::DeferredCallResolution;
22
use super::MaybeInProgressTables;
33

4-
use rustc_data_structures::fx::FxHashMap;
4+
use rustc_data_structures::{fx::FxHashMap, stable_set::FxHashSet};
55
use rustc_hir as hir;
66
use rustc_hir::def_id::{DefIdMap, LocalDefId};
77
use rustc_hir::HirIdMap;
@@ -68,6 +68,11 @@ pub struct Inherited<'a, 'tcx> {
6868
pub(super) opaque_types_vars: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
6969

7070
pub(super) body_id: Option<hir::BodyId>,
71+
72+
/// Whenever we introduce an adjustment from `!` into a type variable,
73+
/// we record that type variable here. This is later used to inform
74+
/// fallback. See the `fallback` module for details.
75+
pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
7176
}
7277

7378
impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> {
@@ -125,6 +130,7 @@ impl Inherited<'a, 'tcx> {
125130
deferred_generator_interiors: RefCell::new(Vec::new()),
126131
opaque_types: RefCell::new(Default::default()),
127132
opaque_types_vars: RefCell::new(Default::default()),
133+
diverging_type_vars: RefCell::new(Default::default()),
128134
body_id,
129135
}
130136
}

0 commit comments

Comments
 (0)