Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 1c004f2

Browse files
nikomatsakisMark-Simulacrum
authored andcommitted
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 ebb8ff9 commit 1c004f2

File tree

4 files changed

+53
-39
lines changed

4 files changed

+53
-39
lines changed

compiler/rustc_typeck/src/check/coercion.rs

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

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

182165
// 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> {
@@ -255,8 +254,27 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
255254

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

261279
// Find all type variables that are reachable from a diverging
262280
// type variable. These will typically default to `!`, unless
@@ -265,27 +283,24 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
265283
let mut roots_reachable_from_diverging = FxHashSet::default();
266284
let mut diverging_vids = vec![];
267285
let mut non_diverging_vids = vec![];
268-
for &unsolved_vid in &unsolved_vids {
286+
for unsolved_vid in unsolved_vids {
287+
let root_vid = self.infcx.root_var(unsolved_vid);
269288
debug!(
270-
"calculate_diverging_fallback: unsolved_vid={:?} diverges={:?}",
289+
"calculate_diverging_fallback: unsolved_vid={:?} root_vid={:?} diverges={:?}",
271290
unsolved_vid,
272-
self.infcx.ty_vid_diverges(unsolved_vid)
291+
root_vid,
292+
diverging_roots.contains(&root_vid),
273293
);
274-
match self.infcx.ty_vid_diverges(unsolved_vid) {
275-
Diverging::Diverges => {
276-
diverging_vids.push(unsolved_vid);
277-
let root_vid = self.infcx.root_var(unsolved_vid);
278-
debug!(
279-
"calculate_diverging_fallback: root_vid={:?} reaches {:?}",
280-
root_vid,
281-
coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
282-
);
283-
roots_reachable_from_diverging
284-
.extend(coercion_graph.depth_first_search(root_vid));
285-
}
286-
Diverging::NotDiverging => {
287-
non_diverging_vids.push(unsolved_vid);
288-
}
294+
if diverging_roots.contains(&root_vid) {
295+
diverging_vids.push(unsolved_vid);
296+
debug!(
297+
"calculate_diverging_fallback: root_vid={:?} reaches {:?}",
298+
root_vid,
299+
coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
300+
);
301+
roots_reachable_from_diverging.extend(coercion_graph.depth_first_search(root_vid));
302+
} else {
303+
non_diverging_vids.push(unsolved_vid);
289304
}
290305
}
291306
debug!(

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
286286
return;
287287
}
288288

289+
for a in &adj {
290+
if let Adjust::NeverToAny = a.kind {
291+
if a.target.is_ty_var() {
292+
self.diverging_type_vars.borrow_mut().insert(a.target);
293+
debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
294+
}
295+
}
296+
}
297+
289298
let autoborrow_mut = adj.iter().any(|adj| {
290299
matches!(
291300
adj,

compiler/rustc_typeck/src/check/inherited.rs

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

4+
use rustc_data_structures::fx::FxHashSet;
45
use rustc_hir as hir;
56
use rustc_hir::def_id::{DefIdMap, LocalDefId};
67
use rustc_hir::HirIdMap;
@@ -56,6 +57,11 @@ pub struct Inherited<'a, 'tcx> {
5657
pub(super) constness: hir::Constness,
5758

5859
pub(super) body_id: Option<hir::BodyId>,
60+
61+
/// Whenever we introduce an adjustment from `!` into a type variable,
62+
/// we record that type variable here. This is later used to inform
63+
/// fallback. See the `fallback` module for details.
64+
pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
5965
}
6066

6167
impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> {
@@ -121,6 +127,7 @@ impl Inherited<'a, 'tcx> {
121127
deferred_call_resolutions: RefCell::new(Default::default()),
122128
deferred_cast_checks: RefCell::new(Vec::new()),
123129
deferred_generator_interiors: RefCell::new(Vec::new()),
130+
diverging_type_vars: RefCell::new(Default::default()),
124131
constness,
125132
body_id,
126133
}

0 commit comments

Comments
 (0)