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.
This commit is contained in:
parent
ebb8ff9edf
commit
1c004f2d43
@ -159,24 +159,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
|
||||
// Coercing from `!` to any type is allowed:
|
||||
if a.is_never() {
|
||||
// Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
|
||||
// type variable, we want `?T` to fallback to `!` if not
|
||||
// otherwise constrained. An example where this arises:
|
||||
//
|
||||
// let _: Option<?T> = Some({ return; });
|
||||
//
|
||||
// here, we would coerce from `!` to `?T`.
|
||||
return if b.is_ty_var() {
|
||||
// Micro-optimization: no need for this if `b` is
|
||||
// already resolved in some way.
|
||||
let diverging_ty = self.next_diverging_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::AdjustmentType,
|
||||
span: self.cause.span,
|
||||
});
|
||||
self.coerce_from_inference_variable(diverging_ty, b, simple(Adjust::NeverToAny))
|
||||
} else {
|
||||
success(simple(Adjust::NeverToAny)(b), b, vec![])
|
||||
};
|
||||
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
|
||||
}
|
||||
|
||||
// Coercing *from* an unresolved inference variable means that
|
||||
|
@ -2,7 +2,6 @@ use crate::check::FnCtxt;
|
||||
use rustc_data_structures::{
|
||||
fx::FxHashMap, graph::vec_graph::VecGraph, graph::WithSuccessors, stable_set::FxHashSet,
|
||||
};
|
||||
use rustc_infer::infer::type_variable::Diverging;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
@ -255,8 +254,27 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
|
||||
// Extract the unsolved type inference variable vids; note that some
|
||||
// unsolved variables are integer/float variables and are excluded.
|
||||
let unsolved_vids: Vec<_> =
|
||||
unsolved_variables.iter().filter_map(|ty| ty.ty_vid()).collect();
|
||||
let unsolved_vids = unsolved_variables.iter().filter_map(|ty| ty.ty_vid());
|
||||
|
||||
// Compute the diverging root vids D -- that is, the root vid of
|
||||
// those type variables that (a) are the target of a coercion from
|
||||
// a `!` type and (b) have not yet been solved.
|
||||
//
|
||||
// These variables are the ones that are targets for fallback to
|
||||
// either `!` or `()`.
|
||||
let diverging_roots: FxHashSet<ty::TyVid> = self
|
||||
.diverging_type_vars
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|&ty| self.infcx.shallow_resolve(ty))
|
||||
.filter_map(|ty| ty.ty_vid())
|
||||
.map(|vid| self.infcx.root_var(vid))
|
||||
.collect();
|
||||
debug!(
|
||||
"calculate_diverging_fallback: diverging_type_vars={:?}",
|
||||
self.diverging_type_vars.borrow()
|
||||
);
|
||||
debug!("calculate_diverging_fallback: diverging_roots={:?}", diverging_roots);
|
||||
|
||||
// Find all type variables that are reachable from a diverging
|
||||
// type variable. These will typically default to `!`, unless
|
||||
@ -265,27 +283,24 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
let mut roots_reachable_from_diverging = FxHashSet::default();
|
||||
let mut diverging_vids = vec![];
|
||||
let mut non_diverging_vids = vec![];
|
||||
for &unsolved_vid in &unsolved_vids {
|
||||
for unsolved_vid in unsolved_vids {
|
||||
let root_vid = self.infcx.root_var(unsolved_vid);
|
||||
debug!(
|
||||
"calculate_diverging_fallback: unsolved_vid={:?} diverges={:?}",
|
||||
"calculate_diverging_fallback: unsolved_vid={:?} root_vid={:?} diverges={:?}",
|
||||
unsolved_vid,
|
||||
self.infcx.ty_vid_diverges(unsolved_vid)
|
||||
root_vid,
|
||||
diverging_roots.contains(&root_vid),
|
||||
);
|
||||
match self.infcx.ty_vid_diverges(unsolved_vid) {
|
||||
Diverging::Diverges => {
|
||||
diverging_vids.push(unsolved_vid);
|
||||
let root_vid = self.infcx.root_var(unsolved_vid);
|
||||
debug!(
|
||||
"calculate_diverging_fallback: root_vid={:?} reaches {:?}",
|
||||
root_vid,
|
||||
coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
|
||||
);
|
||||
roots_reachable_from_diverging
|
||||
.extend(coercion_graph.depth_first_search(root_vid));
|
||||
}
|
||||
Diverging::NotDiverging => {
|
||||
non_diverging_vids.push(unsolved_vid);
|
||||
}
|
||||
if diverging_roots.contains(&root_vid) {
|
||||
diverging_vids.push(unsolved_vid);
|
||||
debug!(
|
||||
"calculate_diverging_fallback: root_vid={:?} reaches {:?}",
|
||||
root_vid,
|
||||
coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
|
||||
);
|
||||
roots_reachable_from_diverging.extend(coercion_graph.depth_first_search(root_vid));
|
||||
} else {
|
||||
non_diverging_vids.push(unsolved_vid);
|
||||
}
|
||||
}
|
||||
debug!(
|
||||
|
@ -286,6 +286,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
for a in &adj {
|
||||
if let Adjust::NeverToAny = a.kind {
|
||||
if a.target.is_ty_var() {
|
||||
self.diverging_type_vars.borrow_mut().insert(a.target);
|
||||
debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let autoborrow_mut = adj.iter().any(|adj| {
|
||||
matches!(
|
||||
adj,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::callee::DeferredCallResolution;
|
||||
use super::MaybeInProgressTables;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefIdMap, LocalDefId};
|
||||
use rustc_hir::HirIdMap;
|
||||
@ -56,6 +57,11 @@ pub struct Inherited<'a, 'tcx> {
|
||||
pub(super) constness: hir::Constness,
|
||||
|
||||
pub(super) body_id: Option<hir::BodyId>,
|
||||
|
||||
/// Whenever we introduce an adjustment from `!` into a type variable,
|
||||
/// we record that type variable here. This is later used to inform
|
||||
/// fallback. See the `fallback` module for details.
|
||||
pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> {
|
||||
@ -121,6 +127,7 @@ impl Inherited<'a, 'tcx> {
|
||||
deferred_call_resolutions: RefCell::new(Default::default()),
|
||||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
deferred_generator_interiors: RefCell::new(Vec::new()),
|
||||
diverging_type_vars: RefCell::new(Default::default()),
|
||||
constness,
|
||||
body_id,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user