mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 15:32:06 +00:00
perf: Reduce snapshot/rollback overhead
By merging the undo_log of all structures part of the snapshot the cost of creating a snapshot becomes much cheaper. Since snapshots with no or few changes are so frequent this ends up mattering more than the slight overhead of dispatching on the variants that map to each field.
This commit is contained in:
parent
61621e2667
commit
1506b1fc6a
@ -987,8 +987,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ena"
|
name = "ena"
|
||||||
version = "0.13.1"
|
version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/Marwes/ena?branch=detach_undo_log#9b977ea7f209a35f46d65d33cdd74b8f4931fb8a"
|
||||||
checksum = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
@ -65,5 +65,7 @@ rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' }
|
|||||||
rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' }
|
rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' }
|
||||||
rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' }
|
rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' }
|
||||||
|
|
||||||
|
ena = { version = "0.13.1", git = "https://github.com/Marwes/ena", branch = "detach_undo_log" }
|
||||||
|
|
||||||
[patch."https://github.com/rust-lang/rust-clippy"]
|
[patch."https://github.com/rust-lang/rust-clippy"]
|
||||||
clippy_lints = { path = "src/tools/clippy/clippy_lints" }
|
clippy_lints = { path = "src/tools/clippy/clippy_lints" }
|
||||||
|
@ -84,6 +84,7 @@ pub mod sync;
|
|||||||
pub mod thin_vec;
|
pub mod thin_vec;
|
||||||
pub mod tiny_list;
|
pub mod tiny_list;
|
||||||
pub mod transitive_relation;
|
pub mod transitive_relation;
|
||||||
|
pub use ena::undo_log;
|
||||||
pub use ena::unify;
|
pub use ena::unify;
|
||||||
mod atomic_ref;
|
mod atomic_ref;
|
||||||
pub mod fingerprint;
|
pub mod fingerprint;
|
||||||
|
@ -76,7 +76,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
|||||||
(&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => {
|
(&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => {
|
||||||
self.inner
|
self.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.int_unification_table
|
.int_unification_table()
|
||||||
.unify_var_var(a_id, b_id)
|
.unify_var_var(a_id, b_id)
|
||||||
.map_err(|e| int_unification_error(a_is_expected, e))?;
|
.map_err(|e| int_unification_error(a_is_expected, e))?;
|
||||||
Ok(a)
|
Ok(a)
|
||||||
@ -98,7 +98,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
|||||||
(&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => {
|
(&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => {
|
||||||
self.inner
|
self.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.float_unification_table
|
.float_unification_table()
|
||||||
.unify_var_var(a_id, b_id)
|
.unify_var_var(a_id, b_id)
|
||||||
.map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
|
.map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
|
||||||
Ok(a)
|
Ok(a)
|
||||||
@ -133,8 +133,8 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
|||||||
return Ok(a);
|
return Ok(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
let a = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table, a);
|
let a = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table(), a);
|
||||||
let b = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table, b);
|
let b = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table(), b);
|
||||||
|
|
||||||
let a_is_expected = relation.a_is_expected();
|
let a_is_expected = relation.a_is_expected();
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
|||||||
) => {
|
) => {
|
||||||
self.inner
|
self.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.const_unification_table
|
.const_unification_table()
|
||||||
.unify_var_var(a_vid, b_vid)
|
.unify_var_var(a_vid, b_vid)
|
||||||
.map_err(|e| const_unification_error(a_is_expected, e))?;
|
.map_err(|e| const_unification_error(a_is_expected, e))?;
|
||||||
return Ok(a);
|
return Ok(a);
|
||||||
@ -179,7 +179,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
|||||||
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||||
self.inner
|
self.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.const_unification_table
|
.const_unification_table()
|
||||||
.unify_var_value(
|
.unify_var_value(
|
||||||
vid,
|
vid,
|
||||||
ConstVarValue {
|
ConstVarValue {
|
||||||
@ -202,7 +202,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
|||||||
) -> RelateResult<'tcx, Ty<'tcx>> {
|
) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||||
self.inner
|
self.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.int_unification_table
|
.int_unification_table()
|
||||||
.unify_var_value(vid, Some(val))
|
.unify_var_value(vid, Some(val))
|
||||||
.map_err(|e| int_unification_error(vid_is_expected, e))?;
|
.map_err(|e| int_unification_error(vid_is_expected, e))?;
|
||||||
match val {
|
match val {
|
||||||
@ -219,7 +219,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
|||||||
) -> RelateResult<'tcx, Ty<'tcx>> {
|
) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||||
self.inner
|
self.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.float_unification_table
|
.float_unification_table()
|
||||||
.unify_var_value(vid, Some(ty::FloatVarValue(val)))
|
.unify_var_value(vid, Some(ty::FloatVarValue(val)))
|
||||||
.map_err(|e| float_unification_error(vid_is_expected, e))?;
|
.map_err(|e| float_unification_error(vid_is_expected, e))?;
|
||||||
Ok(self.tcx.mk_mach_float(val))
|
Ok(self.tcx.mk_mach_float(val))
|
||||||
@ -266,7 +266,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||||||
use self::RelationDir::*;
|
use self::RelationDir::*;
|
||||||
|
|
||||||
// Get the actual variable that b_vid has been inferred to
|
// Get the actual variable that b_vid has been inferred to
|
||||||
debug_assert!(self.infcx.inner.borrow_mut().type_variables.probe(b_vid).is_unknown());
|
debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
|
||||||
|
|
||||||
debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);
|
debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||||||
"instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})",
|
"instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})",
|
||||||
a_ty, dir, b_vid, b_ty
|
a_ty, dir, b_vid, b_ty
|
||||||
);
|
);
|
||||||
self.infcx.inner.borrow_mut().type_variables.instantiate(b_vid, b_ty);
|
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
|
||||||
|
|
||||||
if needs_wf {
|
if needs_wf {
|
||||||
self.obligations.push(Obligation::new(
|
self.obligations.push(Obligation::new(
|
||||||
@ -344,7 +344,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||||||
|
|
||||||
debug!("generalize: ambient_variance = {:?}", ambient_variance);
|
debug!("generalize: ambient_variance = {:?}", ambient_variance);
|
||||||
|
|
||||||
let for_universe = match self.infcx.inner.borrow_mut().type_variables.probe(for_vid) {
|
let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) {
|
||||||
v @ TypeVariableValue::Known { .. } => {
|
v @ TypeVariableValue::Known { .. } => {
|
||||||
panic!("instantiating {:?} which has a known value {:?}", for_vid, v,)
|
panic!("instantiating {:?} which has a known value {:?}", for_vid, v,)
|
||||||
}
|
}
|
||||||
@ -356,7 +356,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||||||
let mut generalize = Generalizer {
|
let mut generalize = Generalizer {
|
||||||
infcx: self.infcx,
|
infcx: self.infcx,
|
||||||
span: self.trace.cause.span,
|
span: self.trace.cause.span,
|
||||||
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables.sub_root_var(for_vid),
|
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
|
||||||
for_universe,
|
for_universe,
|
||||||
ambient_variance,
|
ambient_variance,
|
||||||
needs_wf: false,
|
needs_wf: false,
|
||||||
@ -508,14 +508,14 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||||||
// us from creating infinitely sized types.
|
// us from creating infinitely sized types.
|
||||||
match t.kind {
|
match t.kind {
|
||||||
ty::Infer(ty::TyVar(vid)) => {
|
ty::Infer(ty::TyVar(vid)) => {
|
||||||
let vid = self.infcx.inner.borrow_mut().type_variables.root_var(vid);
|
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
|
||||||
let sub_vid = self.infcx.inner.borrow_mut().type_variables.sub_root_var(vid);
|
let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
|
||||||
if sub_vid == self.for_vid_sub_root {
|
if sub_vid == self.for_vid_sub_root {
|
||||||
// If sub-roots are equal, then `for_vid` and
|
// If sub-roots are equal, then `for_vid` and
|
||||||
// `vid` are related via subtyping.
|
// `vid` are related via subtyping.
|
||||||
Err(TypeError::CyclicTy(self.root_ty))
|
Err(TypeError::CyclicTy(self.root_ty))
|
||||||
} else {
|
} else {
|
||||||
let probe = self.infcx.inner.borrow_mut().type_variables.probe(vid);
|
let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
|
||||||
match probe {
|
match probe {
|
||||||
TypeVariableValue::Known { value: u } => {
|
TypeVariableValue::Known { value: u } => {
|
||||||
debug!("generalize: known value {:?}", u);
|
debug!("generalize: known value {:?}", u);
|
||||||
@ -542,12 +542,13 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let origin =
|
let origin =
|
||||||
*self.infcx.inner.borrow_mut().type_variables.var_origin(vid);
|
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
|
||||||
let new_var_id = self.infcx.inner.borrow_mut().type_variables.new_var(
|
let new_var_id = self
|
||||||
self.for_universe,
|
.infcx
|
||||||
false,
|
.inner
|
||||||
origin,
|
.borrow_mut()
|
||||||
);
|
.type_variables()
|
||||||
|
.new_var(self.for_universe, false, origin);
|
||||||
let u = self.tcx().mk_ty_var(new_var_id);
|
let u = self.tcx().mk_ty_var(new_var_id);
|
||||||
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
||||||
Ok(u)
|
Ok(u)
|
||||||
@ -618,7 +619,8 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||||||
|
|
||||||
match c.val {
|
match c.val {
|
||||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||||
let variable_table = &mut self.infcx.inner.borrow_mut().const_unification_table;
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
|
let variable_table = &mut inner.const_unification_table();
|
||||||
let var_value = variable_table.probe_value(vid);
|
let var_value = variable_table.probe_value(vid);
|
||||||
match var_value.val {
|
match var_value.val {
|
||||||
ConstVariableValue::Known { value: u } => self.relate(&u, &u),
|
ConstVariableValue::Known { value: u } => self.relate(&u, &u),
|
||||||
|
@ -72,14 +72,14 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let infcx = self.fields.infcx;
|
let infcx = self.fields.infcx;
|
||||||
let a = infcx.inner.borrow_mut().type_variables.replace_if_possible(a);
|
let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
|
||||||
let b = infcx.inner.borrow_mut().type_variables.replace_if_possible(b);
|
let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
|
||||||
|
|
||||||
debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b);
|
debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b);
|
||||||
|
|
||||||
match (&a.kind, &b.kind) {
|
match (&a.kind, &b.kind) {
|
||||||
(&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
|
(&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
|
||||||
infcx.inner.borrow_mut().type_variables.equate(a_id, b_id);
|
infcx.inner.borrow_mut().type_variables().equate(a_id, b_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::Infer(TyVar(a_id)), _) => {
|
(&ty::Infer(TyVar(a_id)), _) => {
|
||||||
|
@ -59,7 +59,7 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
|
|||||||
.infcx
|
.infcx
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.type_variables
|
.type_variables()
|
||||||
.sub_unified(a_vid, b_vid),
|
.sub_unified(a_vid, b_vid),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@ -194,7 +194,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
highlight: Option<ty::print::RegionHighlightMode>,
|
highlight: Option<ty::print::RegionHighlightMode>,
|
||||||
) -> (String, Option<Span>, Cow<'static, str>, Option<String>, Option<&'static str>) {
|
) -> (String, Option<Span>, Cow<'static, str>, Option<String>, Option<&'static str>) {
|
||||||
if let ty::Infer(ty::TyVar(ty_vid)) = ty.kind {
|
if let ty::Infer(ty::TyVar(ty_vid)) = ty.kind {
|
||||||
let ty_vars = &self.inner.borrow().type_variables;
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
let ty_vars = &inner.type_variables();
|
||||||
let var_origin = ty_vars.var_origin(ty_vid);
|
let var_origin = ty_vars.var_origin(ty_vid);
|
||||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind {
|
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind {
|
||||||
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
|
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
|
||||||
@ -248,7 +249,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
|
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
|
||||||
let ty_vars = &self.inner.borrow().type_variables;
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
let ty_vars = inner.type_variables();
|
||||||
let getter = move |ty_vid| {
|
let getter = move |ty_vid| {
|
||||||
let var_origin = ty_vars.var_origin(ty_vid);
|
let var_origin = ty_vars.var_origin(ty_vid);
|
||||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
|
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
|
||||||
|
@ -147,7 +147,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
|
|||||||
|
|
||||||
match t.kind {
|
match t.kind {
|
||||||
ty::Infer(ty::TyVar(v)) => {
|
ty::Infer(ty::TyVar(v)) => {
|
||||||
let opt_ty = self.infcx.inner.borrow_mut().type_variables.probe(v).known();
|
let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
|
||||||
self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
|
self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
|
|||||||
self.infcx
|
self.infcx
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.int_unification_table
|
.int_unification_table()
|
||||||
.probe_value(v)
|
.probe_value(v)
|
||||||
.map(|v| v.to_type(tcx)),
|
.map(|v| v.to_type(tcx)),
|
||||||
ty::IntVar(v),
|
ty::IntVar(v),
|
||||||
@ -166,7 +166,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
|
|||||||
self.infcx
|
self.infcx
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.float_unification_table
|
.float_unification_table()
|
||||||
.probe_value(v)
|
.probe_value(v)
|
||||||
.map(|v| v.to_type(tcx)),
|
.map(|v| v.to_type(tcx)),
|
||||||
ty::FloatVar(v),
|
ty::FloatVar(v),
|
||||||
@ -222,7 +222,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
|
|||||||
.infcx
|
.infcx
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.const_unification_table
|
.const_unification_table()
|
||||||
.probe_value(v)
|
.probe_value(v)
|
||||||
.val
|
.val
|
||||||
.known();
|
.known();
|
||||||
|
@ -3,18 +3,30 @@ use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt,
|
|||||||
|
|
||||||
use super::type_variable::TypeVariableOrigin;
|
use super::type_variable::TypeVariableOrigin;
|
||||||
use super::InferCtxt;
|
use super::InferCtxt;
|
||||||
use super::{ConstVariableOrigin, RegionVariableOrigin};
|
use super::{ConstVariableOrigin, RegionVariableOrigin, UnificationTable};
|
||||||
|
|
||||||
|
use rustc_data_structures::snapshot_vec as sv;
|
||||||
use rustc_data_structures::unify as ut;
|
use rustc_data_structures::unify as ut;
|
||||||
use ut::UnifyKey;
|
use ut::UnifyKey;
|
||||||
|
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
|
fn vars_since_snapshot<'tcx, T>(
|
||||||
|
table: &mut UnificationTable<'_, 'tcx, T>,
|
||||||
|
snapshot: usize,
|
||||||
|
) -> Range<T>
|
||||||
|
where
|
||||||
|
T: UnifyKey,
|
||||||
|
super::UndoLog<'tcx>: From<sv::UndoLog<ut::Delegate<T>>>,
|
||||||
|
{
|
||||||
|
T::from_index(snapshot as u32)..T::from_index(table.len() as u32)
|
||||||
|
}
|
||||||
|
|
||||||
fn const_vars_since_snapshot<'tcx>(
|
fn const_vars_since_snapshot<'tcx>(
|
||||||
table: &mut ut::UnificationTable<ut::InPlace<ConstVid<'tcx>>>,
|
table: &mut UnificationTable<'_, 'tcx, ConstVid<'tcx>>,
|
||||||
snapshot: &ut::Snapshot<ut::InPlace<ConstVid<'tcx>>>,
|
snapshot: usize,
|
||||||
) -> (Range<ConstVid<'tcx>>, Vec<ConstVariableOrigin>) {
|
) -> (Range<ConstVid<'tcx>>, Vec<ConstVariableOrigin>) {
|
||||||
let range = table.vars_since_snapshot(snapshot);
|
let range = vars_since_snapshot(table, snapshot);
|
||||||
(
|
(
|
||||||
range.start..range.end,
|
range.start..range.end,
|
||||||
(range.start.index..range.end.index)
|
(range.start.index..range.end.index)
|
||||||
@ -83,17 +95,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
let type_vars =
|
let type_vars =
|
||||||
inner.type_variables.vars_since_snapshot(&snapshot.type_snapshot);
|
inner.type_variables().vars_since_snapshot(&snapshot.type_snapshot);
|
||||||
let int_vars =
|
let int_vars = vars_since_snapshot(
|
||||||
inner.int_unification_table.vars_since_snapshot(&snapshot.int_snapshot);
|
&mut inner.int_unification_table(),
|
||||||
let float_vars =
|
snapshot.int_snapshot,
|
||||||
inner.float_unification_table.vars_since_snapshot(&snapshot.float_snapshot);
|
);
|
||||||
|
let float_vars = vars_since_snapshot(
|
||||||
|
&mut inner.float_unification_table(),
|
||||||
|
snapshot.float_snapshot,
|
||||||
|
);
|
||||||
let region_vars = inner
|
let region_vars = inner
|
||||||
.unwrap_region_constraints()
|
.unwrap_region_constraints()
|
||||||
.vars_since_snapshot(&snapshot.region_constraints_snapshot);
|
.vars_since_snapshot(&snapshot.region_constraints_snapshot);
|
||||||
let const_vars = const_vars_since_snapshot(
|
let const_vars = const_vars_since_snapshot(
|
||||||
&mut inner.const_unification_table,
|
&mut inner.const_unification_table(),
|
||||||
&snapshot.const_snapshot,
|
snapshot.const_snapshot,
|
||||||
);
|
);
|
||||||
|
|
||||||
let fudger = InferenceFudger {
|
let fudger = InferenceFudger {
|
||||||
@ -161,7 +177,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> {
|
|||||||
// that it is unbound, so we can just return
|
// that it is unbound, so we can just return
|
||||||
// it.
|
// it.
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.infcx.inner.borrow_mut().type_variables.probe(vid).is_unknown()
|
self.infcx.inner.borrow_mut().type_variables().probe(vid).is_unknown()
|
||||||
);
|
);
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let infcx = this.infcx();
|
let infcx = this.infcx();
|
||||||
let a = infcx.inner.borrow_mut().type_variables.replace_if_possible(a);
|
let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
|
||||||
let b = infcx.inner.borrow_mut().type_variables.replace_if_possible(b);
|
let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
|
||||||
match (&a.kind, &b.kind) {
|
match (&a.kind, &b.kind) {
|
||||||
// If one side is known to be a variable and one is not,
|
// If one side is known to be a variable and one is not,
|
||||||
// create a variable (`v`) to represent the LUB. Make sure to
|
// create a variable (`v`) to represent the LUB. Make sure to
|
||||||
|
@ -10,7 +10,9 @@ use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
|
|||||||
|
|
||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
|
use rustc_data_structures::snapshot_vec as sv;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
use rustc_data_structures::undo_log::{Rollback, Snapshots, UndoLogs};
|
||||||
use rustc_data_structures::unify as ut;
|
use rustc_data_structures::unify as ut;
|
||||||
use rustc_errors::DiagnosticBuilder;
|
use rustc_errors::DiagnosticBuilder;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@ -36,6 +38,7 @@ use rustc_span::Span;
|
|||||||
use std::cell::{Cell, Ref, RefCell};
|
use std::cell::{Cell, Ref, RefCell};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use self::combine::CombineFields;
|
use self::combine::CombineFields;
|
||||||
use self::free_regions::RegionRelations;
|
use self::free_regions::RegionRelations;
|
||||||
@ -141,16 +144,17 @@ pub struct InferCtxtInner<'tcx> {
|
|||||||
/// We instantiate `UnificationTable` with `bounds<Ty>` because the types
|
/// We instantiate `UnificationTable` with `bounds<Ty>` because the types
|
||||||
/// that might instantiate a general type variable have an order,
|
/// that might instantiate a general type variable have an order,
|
||||||
/// represented by its upper and lower bounds.
|
/// represented by its upper and lower bounds.
|
||||||
type_variables: type_variable::TypeVariableTable<'tcx>,
|
type_variables: type_variable::TypeVariableStorage<'tcx>,
|
||||||
|
undo_log: Logs<'tcx>,
|
||||||
|
|
||||||
/// Map from const parameter variable to the kind of const it represents.
|
/// Map from const parameter variable to the kind of const it represents.
|
||||||
const_unification_table: ut::UnificationTable<ut::InPlace<ty::ConstVid<'tcx>>>,
|
const_unification_table: ut::UnificationStorage<ty::ConstVid<'tcx>>,
|
||||||
|
|
||||||
/// Map from integral variable to the kind of integer it represents.
|
/// Map from integral variable to the kind of integer it represents.
|
||||||
int_unification_table: ut::UnificationTable<ut::InPlace<ty::IntVid>>,
|
int_unification_table: ut::UnificationStorage<ty::IntVid>,
|
||||||
|
|
||||||
/// Map from floating variable to the kind of float it represents.
|
/// Map from floating variable to the kind of float it represents.
|
||||||
float_unification_table: ut::UnificationTable<ut::InPlace<ty::FloatVid>>,
|
float_unification_table: ut::UnificationStorage<ty::FloatVid>,
|
||||||
|
|
||||||
/// Tracks the set of region variables and the constraints between them.
|
/// Tracks the set of region variables and the constraints between them.
|
||||||
/// This is initially `Some(_)` but when
|
/// This is initially `Some(_)` but when
|
||||||
@ -197,20 +201,220 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||||||
fn new() -> InferCtxtInner<'tcx> {
|
fn new() -> InferCtxtInner<'tcx> {
|
||||||
InferCtxtInner {
|
InferCtxtInner {
|
||||||
projection_cache: Default::default(),
|
projection_cache: Default::default(),
|
||||||
type_variables: type_variable::TypeVariableTable::new(),
|
type_variables: type_variable::TypeVariableStorage::new(),
|
||||||
const_unification_table: ut::UnificationTable::new(),
|
undo_log: Logs::default(),
|
||||||
int_unification_table: ut::UnificationTable::new(),
|
const_unification_table: ut::UnificationStorage::new(),
|
||||||
float_unification_table: ut::UnificationTable::new(),
|
int_unification_table: ut::UnificationStorage::new(),
|
||||||
|
float_unification_table: ut::UnificationStorage::new(),
|
||||||
region_constraints: Some(RegionConstraintCollector::new()),
|
region_constraints: Some(RegionConstraintCollector::new()),
|
||||||
region_obligations: vec![],
|
region_obligations: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_variables(&mut self) -> type_variable::TypeVariableTable<'tcx, '_> {
|
||||||
|
self.type_variables.with_log(&mut self.undo_log)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn int_unification_table(
|
||||||
|
&mut self,
|
||||||
|
) -> ut::UnificationTable<
|
||||||
|
ut::InPlace<ty::IntVid, &mut ut::UnificationStorage<ty::IntVid>, &mut Logs<'tcx>>,
|
||||||
|
> {
|
||||||
|
ut::UnificationTable::with_log(&mut self.int_unification_table, &mut self.undo_log)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn float_unification_table(
|
||||||
|
&mut self,
|
||||||
|
) -> ut::UnificationTable<
|
||||||
|
ut::InPlace<ty::FloatVid, &mut ut::UnificationStorage<ty::FloatVid>, &mut Logs<'tcx>>,
|
||||||
|
> {
|
||||||
|
ut::UnificationTable::with_log(&mut self.float_unification_table, &mut self.undo_log)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn const_unification_table(
|
||||||
|
&mut self,
|
||||||
|
) -> ut::UnificationTable<
|
||||||
|
ut::InPlace<
|
||||||
|
ty::ConstVid<'tcx>,
|
||||||
|
&mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
|
||||||
|
&mut Logs<'tcx>,
|
||||||
|
>,
|
||||||
|
> {
|
||||||
|
ut::UnificationTable::with_log(&mut self.const_unification_table, &mut self.undo_log)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unwrap_region_constraints(&mut self) -> &mut RegionConstraintCollector<'tcx> {
|
pub fn unwrap_region_constraints(&mut self) -> &mut RegionConstraintCollector<'tcx> {
|
||||||
self.region_constraints.as_mut().expect("region constraints already solved")
|
self.region_constraints.as_mut().expect("region constraints already solved")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Snapshot<'tcx> {
|
||||||
|
undo_len: usize,
|
||||||
|
_marker: PhantomData<&'tcx ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) enum UndoLog<'tcx> {
|
||||||
|
TypeVariables(type_variable::UndoLog<'tcx>),
|
||||||
|
ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
|
||||||
|
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
||||||
|
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>) -> Self {
|
||||||
|
UndoLog::TypeVariables(type_variable::UndoLog::EqRelation(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<ut::Delegate<ty::TyVid>>) -> Self {
|
||||||
|
UndoLog::TypeVariables(type_variable::UndoLog::SubRelation(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<type_variable::Delegate>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<type_variable::Delegate>) -> Self {
|
||||||
|
UndoLog::TypeVariables(type_variable::UndoLog::Values(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<type_variable::Instantiate> for UndoLog<'tcx> {
|
||||||
|
fn from(l: type_variable::Instantiate) -> Self {
|
||||||
|
UndoLog::TypeVariables(type_variable::UndoLog::from(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<type_variable::UndoLog<'tcx>> for UndoLog<'tcx> {
|
||||||
|
fn from(t: type_variable::UndoLog<'tcx>) -> Self {
|
||||||
|
Self::TypeVariables(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>) -> Self {
|
||||||
|
Self::ConstUnificationTable(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::IntVid>>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<ut::Delegate<ty::IntVid>>) -> Self {
|
||||||
|
Self::IntUnificationTable(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::FloatVid>>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<ut::Delegate<ty::FloatVid>>) -> Self {
|
||||||
|
Self::FloatUnificationTable(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) type UnificationTable<'a, 'tcx, T> =
|
||||||
|
ut::UnificationTable<ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut Logs<'tcx>>>;
|
||||||
|
|
||||||
|
struct RollbackView<'tcx, 'a> {
|
||||||
|
type_variables: type_variable::RollbackView<'tcx, 'a>,
|
||||||
|
const_unification_table: &'a mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
|
||||||
|
int_unification_table: &'a mut ut::UnificationStorage<ty::IntVid>,
|
||||||
|
float_unification_table: &'a mut ut::UnificationStorage<ty::FloatVid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Rollback<UndoLog<'tcx>> for RollbackView<'tcx, '_> {
|
||||||
|
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
||||||
|
match undo {
|
||||||
|
UndoLog::TypeVariables(undo) => self.type_variables.reverse(undo),
|
||||||
|
UndoLog::ConstUnificationTable(undo) => self.const_unification_table.reverse(undo),
|
||||||
|
UndoLog::IntUnificationTable(undo) => self.int_unification_table.reverse(undo),
|
||||||
|
UndoLog::FloatUnificationTable(undo) => self.float_unification_table.reverse(undo),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct Logs<'tcx> {
|
||||||
|
logs: Vec<UndoLog<'tcx>>,
|
||||||
|
num_open_snapshots: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Logs<'_> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { logs: Default::default(), num_open_snapshots: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, T> UndoLogs<T> for Logs<'tcx>
|
||||||
|
where
|
||||||
|
UndoLog<'tcx>: From<T>,
|
||||||
|
{
|
||||||
|
fn num_open_snapshots(&self) -> usize {
|
||||||
|
self.num_open_snapshots
|
||||||
|
}
|
||||||
|
fn push(&mut self, undo: T) {
|
||||||
|
if self.in_snapshot() {
|
||||||
|
self.logs.push(undo.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn extend<J>(&mut self, undos: J)
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
J: IntoIterator<Item = T>,
|
||||||
|
{
|
||||||
|
if self.in_snapshot() {
|
||||||
|
self.logs.extend(undos.into_iter().map(UndoLog::from))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Snapshots<UndoLog<'tcx>> for Logs<'tcx> {
|
||||||
|
type Snapshot = Snapshot<'tcx>;
|
||||||
|
fn actions_since_snapshot(&self, snapshot: &Self::Snapshot) -> &[UndoLog<'tcx>] {
|
||||||
|
&self.logs[snapshot.undo_len..]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_snapshot(&mut self) -> Self::Snapshot {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rollback_to(&mut self, values: &mut impl Rollback<UndoLog<'tcx>>, snapshot: Self::Snapshot) {
|
||||||
|
debug!("rollback_to({})", snapshot.undo_len);
|
||||||
|
self.assert_open_snapshot(&snapshot);
|
||||||
|
|
||||||
|
while self.logs.len() > snapshot.undo_len {
|
||||||
|
values.reverse(self.logs.pop().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.num_open_snapshots == 1 {
|
||||||
|
// The root snapshot. It's safe to clear the undo log because
|
||||||
|
// there's no snapshot further out that we might need to roll back
|
||||||
|
// to.
|
||||||
|
assert!(snapshot.undo_len == 0);
|
||||||
|
self.logs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.num_open_snapshots -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit(&mut self, snapshot: Self::Snapshot) {
|
||||||
|
debug!("commit({})", snapshot.undo_len);
|
||||||
|
|
||||||
|
if self.num_open_snapshots == 1 {
|
||||||
|
// The root snapshot. It's safe to clear the undo log because
|
||||||
|
// there's no snapshot further out that we might need to roll back
|
||||||
|
// to.
|
||||||
|
assert!(snapshot.undo_len == 0);
|
||||||
|
self.logs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.num_open_snapshots -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Logs<'tcx> {
|
||||||
|
fn assert_open_snapshot(&self, snapshot: &Snapshot<'tcx>) {
|
||||||
|
// Failures here may indicate a failure to follow a stack discipline.
|
||||||
|
assert!(self.logs.len() >= snapshot.undo_len);
|
||||||
|
assert!(self.num_open_snapshots > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct InferCtxt<'a, 'tcx> {
|
pub struct InferCtxt<'a, 'tcx> {
|
||||||
pub tcx: TyCtxt<'tcx>,
|
pub tcx: TyCtxt<'tcx>,
|
||||||
|
|
||||||
@ -644,10 +848,11 @@ impl<'tcx> InferOk<'tcx, ()> {
|
|||||||
#[must_use = "once you start a snapshot, you should always consume it"]
|
#[must_use = "once you start a snapshot, you should always consume it"]
|
||||||
pub struct CombinedSnapshot<'a, 'tcx> {
|
pub struct CombinedSnapshot<'a, 'tcx> {
|
||||||
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
|
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
|
||||||
|
undo_snapshot: Snapshot<'tcx>,
|
||||||
type_snapshot: type_variable::Snapshot<'tcx>,
|
type_snapshot: type_variable::Snapshot<'tcx>,
|
||||||
const_snapshot: ut::Snapshot<ut::InPlace<ty::ConstVid<'tcx>>>,
|
const_snapshot: usize,
|
||||||
int_snapshot: ut::Snapshot<ut::InPlace<ty::IntVid>>,
|
int_snapshot: usize,
|
||||||
float_snapshot: ut::Snapshot<ut::InPlace<ty::FloatVid>>,
|
float_snapshot: usize,
|
||||||
region_constraints_snapshot: RegionSnapshot,
|
region_constraints_snapshot: RegionSnapshot,
|
||||||
region_obligations_snapshot: usize,
|
region_obligations_snapshot: usize,
|
||||||
universe: ty::UniverseIndex,
|
universe: ty::UniverseIndex,
|
||||||
@ -667,7 +872,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> bool {
|
pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> bool {
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
ty::Infer(ty::TyVar(vid)) => self.inner.borrow().type_variables.var_diverges(vid),
|
ty::Infer(ty::TyVar(vid)) => self.inner.borrow_mut().type_variables().var_diverges(vid),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -681,14 +886,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
use rustc_middle::ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt};
|
use rustc_middle::ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt};
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
ty::Infer(ty::IntVar(vid)) => {
|
ty::Infer(ty::IntVar(vid)) => {
|
||||||
if self.inner.borrow_mut().int_unification_table.probe_value(vid).is_some() {
|
if self.inner.borrow_mut().int_unification_table().probe_value(vid).is_some() {
|
||||||
Neither
|
Neither
|
||||||
} else {
|
} else {
|
||||||
UnconstrainedInt
|
UnconstrainedInt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Infer(ty::FloatVar(vid)) => {
|
ty::Infer(ty::FloatVar(vid)) => {
|
||||||
if self.inner.borrow_mut().float_unification_table.probe_value(vid).is_some() {
|
if self.inner.borrow_mut().float_unification_table().probe_value(vid).is_some() {
|
||||||
Neither
|
Neither
|
||||||
} else {
|
} else {
|
||||||
UnconstrainedFloat
|
UnconstrainedFloat
|
||||||
@ -703,21 +908,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
// FIXME(const_generics): should there be an equivalent function for const variables?
|
// FIXME(const_generics): should there be an equivalent function for const variables?
|
||||||
|
|
||||||
let mut vars: Vec<Ty<'_>> = inner
|
let mut vars: Vec<Ty<'_>> = inner
|
||||||
.type_variables
|
.type_variables()
|
||||||
.unsolved_variables()
|
.unsolved_variables()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|t| self.tcx.mk_ty_var(t))
|
.map(|t| self.tcx.mk_ty_var(t))
|
||||||
.collect();
|
.collect();
|
||||||
vars.extend(
|
vars.extend(
|
||||||
(0..inner.int_unification_table.len())
|
(0..inner.int_unification_table().len())
|
||||||
.map(|i| ty::IntVid { index: i as u32 })
|
.map(|i| ty::IntVid { index: i as u32 })
|
||||||
.filter(|&vid| inner.int_unification_table.probe_value(vid).is_none())
|
.filter(|&vid| inner.int_unification_table().probe_value(vid).is_none())
|
||||||
.map(|v| self.tcx.mk_int_var(v)),
|
.map(|v| self.tcx.mk_int_var(v)),
|
||||||
);
|
);
|
||||||
vars.extend(
|
vars.extend(
|
||||||
(0..inner.float_unification_table.len())
|
(0..inner.float_unification_table().len())
|
||||||
.map(|i| ty::FloatVid { index: i as u32 })
|
.map(|i| ty::FloatVid { index: i as u32 })
|
||||||
.filter(|&vid| inner.float_unification_table.probe_value(vid).is_none())
|
.filter(|&vid| inner.float_unification_table().probe_value(vid).is_none())
|
||||||
.map(|v| self.tcx.mk_float_var(v)),
|
.map(|v| self.tcx.mk_float_var(v)),
|
||||||
);
|
);
|
||||||
vars
|
vars
|
||||||
@ -769,12 +974,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
let in_snapshot = self.in_snapshot.replace(true);
|
let in_snapshot = self.in_snapshot.replace(true);
|
||||||
|
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
|
||||||
|
inner.undo_log.num_open_snapshots += 1;
|
||||||
|
let undo_snapshot = Snapshot { undo_len: inner.undo_log.logs.len(), _marker: PhantomData };
|
||||||
CombinedSnapshot {
|
CombinedSnapshot {
|
||||||
projection_cache_snapshot: inner.projection_cache.snapshot(),
|
projection_cache_snapshot: inner.projection_cache.snapshot(),
|
||||||
type_snapshot: inner.type_variables.snapshot(),
|
undo_snapshot,
|
||||||
const_snapshot: inner.const_unification_table.snapshot(),
|
type_snapshot: inner.type_variables().snapshot(),
|
||||||
int_snapshot: inner.int_unification_table.snapshot(),
|
const_snapshot: inner.const_unification_table().len(),
|
||||||
float_snapshot: inner.float_unification_table.snapshot(),
|
int_snapshot: inner.int_unification_table().len(),
|
||||||
|
float_snapshot: inner.float_unification_table().len(),
|
||||||
region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
|
region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
|
||||||
region_obligations_snapshot: inner.region_obligations.len(),
|
region_obligations_snapshot: inner.region_obligations.len(),
|
||||||
universe: self.universe(),
|
universe: self.universe(),
|
||||||
@ -790,10 +999,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
debug!("rollback_to(cause={})", cause);
|
debug!("rollback_to(cause={})", cause);
|
||||||
let CombinedSnapshot {
|
let CombinedSnapshot {
|
||||||
projection_cache_snapshot,
|
projection_cache_snapshot,
|
||||||
type_snapshot,
|
undo_snapshot,
|
||||||
const_snapshot,
|
type_snapshot: _,
|
||||||
int_snapshot,
|
const_snapshot: _,
|
||||||
float_snapshot,
|
int_snapshot: _,
|
||||||
|
float_snapshot: _,
|
||||||
region_constraints_snapshot,
|
region_constraints_snapshot,
|
||||||
region_obligations_snapshot,
|
region_obligations_snapshot,
|
||||||
universe,
|
universe,
|
||||||
@ -807,11 +1017,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
self.skip_leak_check.set(was_skip_leak_check);
|
self.skip_leak_check.set(was_skip_leak_check);
|
||||||
|
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
let inner = &mut *inner;
|
||||||
|
let InferCtxtInner {
|
||||||
|
type_variables,
|
||||||
|
const_unification_table,
|
||||||
|
int_unification_table,
|
||||||
|
float_unification_table,
|
||||||
|
..
|
||||||
|
} = inner;
|
||||||
|
inner.undo_log.rollback_to(
|
||||||
|
&mut RollbackView {
|
||||||
|
type_variables: type_variable::RollbackView::from(type_variables),
|
||||||
|
const_unification_table,
|
||||||
|
int_unification_table,
|
||||||
|
float_unification_table,
|
||||||
|
},
|
||||||
|
undo_snapshot,
|
||||||
|
);
|
||||||
inner.projection_cache.rollback_to(projection_cache_snapshot);
|
inner.projection_cache.rollback_to(projection_cache_snapshot);
|
||||||
inner.type_variables.rollback_to(type_snapshot);
|
|
||||||
inner.const_unification_table.rollback_to(const_snapshot);
|
|
||||||
inner.int_unification_table.rollback_to(int_snapshot);
|
|
||||||
inner.float_unification_table.rollback_to(float_snapshot);
|
|
||||||
inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
|
inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
|
||||||
inner.region_obligations.truncate(region_obligations_snapshot);
|
inner.region_obligations.truncate(region_obligations_snapshot);
|
||||||
}
|
}
|
||||||
@ -820,10 +1043,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
debug!("commit_from()");
|
debug!("commit_from()");
|
||||||
let CombinedSnapshot {
|
let CombinedSnapshot {
|
||||||
projection_cache_snapshot,
|
projection_cache_snapshot,
|
||||||
type_snapshot,
|
undo_snapshot,
|
||||||
const_snapshot,
|
type_snapshot: _,
|
||||||
int_snapshot,
|
const_snapshot: _,
|
||||||
float_snapshot,
|
int_snapshot: _,
|
||||||
|
float_snapshot: _,
|
||||||
region_constraints_snapshot,
|
region_constraints_snapshot,
|
||||||
region_obligations_snapshot: _,
|
region_obligations_snapshot: _,
|
||||||
universe: _,
|
universe: _,
|
||||||
@ -836,11 +1060,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
self.skip_leak_check.set(was_skip_leak_check);
|
self.skip_leak_check.set(was_skip_leak_check);
|
||||||
|
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
inner.undo_log.commit(undo_snapshot);
|
||||||
inner.projection_cache.commit(projection_cache_snapshot);
|
inner.projection_cache.commit(projection_cache_snapshot);
|
||||||
inner.type_variables.commit(type_snapshot);
|
|
||||||
inner.const_unification_table.commit(const_snapshot);
|
|
||||||
inner.int_unification_table.commit(int_snapshot);
|
|
||||||
inner.float_unification_table.commit(float_snapshot);
|
|
||||||
inner.unwrap_region_constraints().commit(region_constraints_snapshot);
|
inner.unwrap_region_constraints().commit(region_constraints_snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1032,7 +1253,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
|
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
|
||||||
self.inner.borrow_mut().type_variables.new_var(self.universe(), diverging, origin)
|
self.inner.borrow_mut().type_variables().new_var(self.universe(), diverging, origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
||||||
@ -1044,7 +1265,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
origin: TypeVariableOrigin,
|
origin: TypeVariableOrigin,
|
||||||
universe: ty::UniverseIndex,
|
universe: ty::UniverseIndex,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let vid = self.inner.borrow_mut().type_variables.new_var(universe, false, origin);
|
let vid = self.inner.borrow_mut().type_variables().new_var(universe, false, origin);
|
||||||
self.tcx.mk_ty_var(vid)
|
self.tcx.mk_ty_var(vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1069,20 +1290,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
let vid = self
|
let vid = self
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.const_unification_table
|
.const_unification_table()
|
||||||
.new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } });
|
.new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } });
|
||||||
self.tcx.mk_const_var(vid, ty)
|
self.tcx.mk_const_var(vid, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> {
|
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> {
|
||||||
self.inner.borrow_mut().const_unification_table.new_key(ConstVarValue {
|
self.inner.borrow_mut().const_unification_table().new_key(ConstVarValue {
|
||||||
origin,
|
origin,
|
||||||
val: ConstVariableValue::Unknown { universe: self.universe() },
|
val: ConstVariableValue::Unknown { universe: self.universe() },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_int_var_id(&self) -> IntVid {
|
fn next_int_var_id(&self) -> IntVid {
|
||||||
self.inner.borrow_mut().int_unification_table.new_key(None)
|
self.inner.borrow_mut().int_unification_table().new_key(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_int_var(&self) -> Ty<'tcx> {
|
pub fn next_int_var(&self) -> Ty<'tcx> {
|
||||||
@ -1090,7 +1311,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_float_var_id(&self) -> FloatVid {
|
fn next_float_var_id(&self) -> FloatVid {
|
||||||
self.inner.borrow_mut().float_unification_table.new_key(None)
|
self.inner.borrow_mut().float_unification_table().new_key(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_float_var(&self) -> Ty<'tcx> {
|
pub fn next_float_var(&self) -> Ty<'tcx> {
|
||||||
@ -1161,7 +1382,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
// used in a path such as `Foo::<T, U>::new()` will
|
// used in a path such as `Foo::<T, U>::new()` will
|
||||||
// use an inference variable for `C` with `[T, U]`
|
// use an inference variable for `C` with `[T, U]`
|
||||||
// as the substitutions for the default, `(T, U)`.
|
// as the substitutions for the default, `(T, U)`.
|
||||||
let ty_var_id = self.inner.borrow_mut().type_variables.new_var(
|
let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
|
||||||
self.universe(),
|
self.universe(),
|
||||||
false,
|
false,
|
||||||
TypeVariableOrigin {
|
TypeVariableOrigin {
|
||||||
@ -1181,7 +1402,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
};
|
};
|
||||||
let const_var_id =
|
let const_var_id =
|
||||||
self.inner.borrow_mut().const_unification_table.new_key(ConstVarValue {
|
self.inner.borrow_mut().const_unification_table().new_key(ConstVarValue {
|
||||||
origin,
|
origin,
|
||||||
val: ConstVariableValue::Unknown { universe: self.universe() },
|
val: ConstVariableValue::Unknown { universe: self.universe() },
|
||||||
});
|
});
|
||||||
@ -1335,7 +1556,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
|
pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
|
||||||
use self::type_variable::TypeVariableValue;
|
use self::type_variable::TypeVariableValue;
|
||||||
|
|
||||||
match self.inner.borrow_mut().type_variables.probe(vid) {
|
match self.inner.borrow_mut().type_variables().probe(vid) {
|
||||||
TypeVariableValue::Known { value } => Ok(value),
|
TypeVariableValue::Known { value } => Ok(value),
|
||||||
TypeVariableValue::Unknown { universe } => Err(universe),
|
TypeVariableValue::Unknown { universe } => Err(universe),
|
||||||
}
|
}
|
||||||
@ -1357,7 +1578,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||||
self.inner.borrow_mut().type_variables.root_var(var)
|
self.inner.borrow_mut().type_variables().root_var(var)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Where possible, replaces type/const variables in
|
/// Where possible, replaces type/const variables in
|
||||||
@ -1395,7 +1616,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
vid: ty::ConstVid<'tcx>,
|
vid: ty::ConstVid<'tcx>,
|
||||||
) -> Result<&'tcx ty::Const<'tcx>, ty::UniverseIndex> {
|
) -> Result<&'tcx ty::Const<'tcx>, ty::UniverseIndex> {
|
||||||
match self.inner.borrow_mut().const_unification_table.probe_value(vid).val {
|
match self.inner.borrow_mut().const_unification_table().probe_value(vid).val {
|
||||||
ConstVariableValue::Known { value } => Ok(value),
|
ConstVariableValue::Known { value } => Ok(value),
|
||||||
ConstVariableValue::Unknown { universe } => Err(universe),
|
ConstVariableValue::Unknown { universe } => Err(universe),
|
||||||
}
|
}
|
||||||
@ -1576,14 +1797,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
//
|
//
|
||||||
// Note: if these two lines are combined into one we get
|
// Note: if these two lines are combined into one we get
|
||||||
// dynamic borrow errors on `self.inner`.
|
// dynamic borrow errors on `self.inner`.
|
||||||
let known = self.inner.borrow_mut().type_variables.probe(v).known();
|
let known = self.inner.borrow_mut().type_variables().probe(v).known();
|
||||||
known.map(|t| self.shallow_resolve_ty(t)).unwrap_or(typ)
|
known.map(|t| self.shallow_resolve_ty(t)).unwrap_or(typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Infer(ty::IntVar(v)) => self
|
ty::Infer(ty::IntVar(v)) => self
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.int_unification_table
|
.int_unification_table()
|
||||||
.probe_value(v)
|
.probe_value(v)
|
||||||
.map(|v| v.to_type(self.tcx))
|
.map(|v| v.to_type(self.tcx))
|
||||||
.unwrap_or(typ),
|
.unwrap_or(typ),
|
||||||
@ -1591,7 +1812,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
ty::Infer(ty::FloatVar(v)) => self
|
ty::Infer(ty::FloatVar(v)) => self
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.float_unification_table
|
.float_unification_table()
|
||||||
.probe_value(v)
|
.probe_value(v)
|
||||||
.map(|v| v.to_type(self.tcx))
|
.map(|v| v.to_type(self.tcx))
|
||||||
.unwrap_or(typ),
|
.unwrap_or(typ),
|
||||||
@ -1617,7 +1838,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
// If `inlined_probe` returns a `Known` value, it never equals
|
// If `inlined_probe` returns a `Known` value, it never equals
|
||||||
// `ty::Infer(ty::TyVar(v))`.
|
// `ty::Infer(ty::TyVar(v))`.
|
||||||
match self.inner.borrow_mut().type_variables.inlined_probe(v) {
|
match self.inner.borrow_mut().type_variables().inlined_probe(v) {
|
||||||
TypeVariableValue::Unknown { .. } => false,
|
TypeVariableValue::Unknown { .. } => false,
|
||||||
TypeVariableValue::Known { .. } => true,
|
TypeVariableValue::Known { .. } => true,
|
||||||
}
|
}
|
||||||
@ -1627,7 +1848,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
// If `inlined_probe_value` returns a value it's always a
|
// If `inlined_probe_value` returns a value it's always a
|
||||||
// `ty::Int(_)` or `ty::UInt(_)`, which never matches a
|
// `ty::Int(_)` or `ty::UInt(_)`, which never matches a
|
||||||
// `ty::Infer(_)`.
|
// `ty::Infer(_)`.
|
||||||
self.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some()
|
self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
TyOrConstInferVar::TyFloat(v) => {
|
TyOrConstInferVar::TyFloat(v) => {
|
||||||
@ -1635,7 +1856,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
// `ty::Float(_)`, which never matches a `ty::Infer(_)`.
|
// `ty::Float(_)`, which never matches a `ty::Infer(_)`.
|
||||||
//
|
//
|
||||||
// Not `inlined_probe_value(v)` because this call site is colder.
|
// Not `inlined_probe_value(v)` because this call site is colder.
|
||||||
self.inner.borrow_mut().float_unification_table.probe_value(v).is_some()
|
self.inner.borrow_mut().float_unification_table().probe_value(v).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
TyOrConstInferVar::Const(v) => {
|
TyOrConstInferVar::Const(v) => {
|
||||||
@ -1718,7 +1939,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
|
|||||||
self.infcx
|
self.infcx
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.const_unification_table
|
.const_unification_table()
|
||||||
.probe_value(*vid)
|
.probe_value(*vid)
|
||||||
.val
|
.val
|
||||||
.known()
|
.known()
|
||||||
|
@ -311,7 +311,7 @@ where
|
|||||||
match value_ty.kind {
|
match value_ty.kind {
|
||||||
ty::Infer(ty::TyVar(value_vid)) => {
|
ty::Infer(ty::TyVar(value_vid)) => {
|
||||||
// Two type variables: just equate them.
|
// Two type variables: just equate them.
|
||||||
self.infcx.inner.borrow_mut().type_variables.equate(vid, value_vid);
|
self.infcx.inner.borrow_mut().type_variables().equate(vid, value_vid);
|
||||||
return Ok(value_ty);
|
return Ok(value_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +332,7 @@ where
|
|||||||
assert!(!generalized_ty.has_infer_types_or_consts());
|
assert!(!generalized_ty.has_infer_types_or_consts());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.infcx.inner.borrow_mut().type_variables.instantiate(vid, generalized_ty);
|
self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty);
|
||||||
|
|
||||||
// The generalized values we extract from `canonical_var_values` have
|
// The generalized values we extract from `canonical_var_values` have
|
||||||
// been fully instantiated and hence the set of scopes we have
|
// been fully instantiated and hence the set of scopes we have
|
||||||
@ -362,7 +362,7 @@ where
|
|||||||
delegate: &mut self.delegate,
|
delegate: &mut self.delegate,
|
||||||
first_free_index: ty::INNERMOST,
|
first_free_index: ty::INNERMOST,
|
||||||
ambient_variance: self.ambient_variance,
|
ambient_variance: self.ambient_variance,
|
||||||
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables.sub_root_var(for_vid),
|
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
|
||||||
universe,
|
universe,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -859,7 +859,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
ty::Infer(ty::TyVar(vid)) => {
|
ty::Infer(ty::TyVar(vid)) => {
|
||||||
let variables = &mut self.infcx.inner.borrow_mut().type_variables;
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
|
let variables = &mut inner.type_variables();
|
||||||
let vid = variables.root_var(vid);
|
let vid = variables.root_var(vid);
|
||||||
let sub_vid = variables.sub_root_var(vid);
|
let sub_vid = variables.sub_root_var(vid);
|
||||||
if sub_vid == self.for_vid_sub_root {
|
if sub_vid == self.for_vid_sub_root {
|
||||||
@ -961,7 +962,8 @@ where
|
|||||||
bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
|
bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||||
let variable_table = &mut self.infcx.inner.borrow_mut().const_unification_table;
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
|
let variable_table = &mut inner.const_unification_table();
|
||||||
let var_value = variable_table.probe_value(vid);
|
let var_value = variable_table.probe_value(vid);
|
||||||
match var_value.val.known() {
|
match var_value.val.known() {
|
||||||
Some(u) => self.relate(&u, &u),
|
Some(u) => self.relate(&u, &u),
|
||||||
|
@ -123,7 +123,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
|
|||||||
// Since we called `shallow_resolve` above, this must
|
// Since we called `shallow_resolve` above, this must
|
||||||
// be an (as yet...) unresolved inference variable.
|
// be an (as yet...) unresolved inference variable.
|
||||||
let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
|
let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
|
||||||
let ty_vars = &self.infcx.inner.borrow().type_variables;
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
|
let ty_vars = &inner.type_variables();
|
||||||
if let TypeVariableOrigin {
|
if let TypeVariableOrigin {
|
||||||
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
|
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
|
||||||
span,
|
span,
|
||||||
|
@ -80,8 +80,8 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let infcx = self.fields.infcx;
|
let infcx = self.fields.infcx;
|
||||||
let a = infcx.inner.borrow_mut().type_variables.replace_if_possible(a);
|
let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
|
||||||
let b = infcx.inner.borrow_mut().type_variables.replace_if_possible(b);
|
let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
|
||||||
match (&a.kind, &b.kind) {
|
match (&a.kind, &b.kind) {
|
||||||
(&ty::Infer(TyVar(a_vid)), &ty::Infer(TyVar(b_vid))) => {
|
(&ty::Infer(TyVar(a_vid)), &ty::Infer(TyVar(b_vid))) => {
|
||||||
// Shouldn't have any LBR here, so we can safely put
|
// Shouldn't have any LBR here, so we can safely put
|
||||||
@ -95,7 +95,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
|
|||||||
// have to record in the `type_variables` tracker that
|
// have to record in the `type_variables` tracker that
|
||||||
// the two variables are equal modulo subtyping, which
|
// the two variables are equal modulo subtyping, which
|
||||||
// is important to the occurs check later on.
|
// is important to the occurs check later on.
|
||||||
infcx.inner.borrow_mut().type_variables.sub(a_vid, b_vid);
|
infcx.inner.borrow_mut().type_variables().sub(a_vid, b_vid);
|
||||||
self.fields.obligations.push(Obligation::new(
|
self.fields.obligations.push(Obligation::new(
|
||||||
self.fields.trace.cause.clone(),
|
self.fields.trace.cause.clone(),
|
||||||
self.fields.param_env,
|
self.fields.param_env,
|
||||||
|
@ -3,19 +3,76 @@ use rustc_middle::ty::{self, Ty, TyVid};
|
|||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
use crate::infer::Logs;
|
||||||
|
|
||||||
use rustc_data_structures::snapshot_vec as sv;
|
use rustc_data_structures::snapshot_vec as sv;
|
||||||
use rustc_data_structures::unify as ut;
|
use rustc_data_structures::unify as ut;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
pub struct TypeVariableTable<'tcx> {
|
use rustc_data_structures::undo_log::{Rollback, Snapshots, UndoLogs};
|
||||||
values: sv::SnapshotVec<Delegate>,
|
|
||||||
|
pub(crate) enum UndoLog<'tcx> {
|
||||||
|
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
|
||||||
|
SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
|
||||||
|
Values(sv::UndoLog<Delegate>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) -> Self {
|
||||||
|
UndoLog::EqRelation(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<ut::Delegate<ty::TyVid>>) -> Self {
|
||||||
|
UndoLog::SubRelation(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<sv::UndoLog<Delegate>> for UndoLog<'tcx> {
|
||||||
|
fn from(l: sv::UndoLog<Delegate>) -> Self {
|
||||||
|
UndoLog::Values(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<Instantiate> for UndoLog<'tcx> {
|
||||||
|
fn from(l: Instantiate) -> Self {
|
||||||
|
UndoLog::Values(sv::UndoLog::Other(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct RollbackView<'tcx, 'a> {
|
||||||
|
pub(crate) eq_relations: &'a mut ut::UnificationStorage<TyVidEqKey<'tcx>>,
|
||||||
|
pub(crate) sub_relations: &'a mut ut::UnificationStorage<ty::TyVid>,
|
||||||
|
pub(crate) values: &'a mut Vec<TypeVariableData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, 'a> From<&'a mut TypeVariableStorage<'tcx>> for RollbackView<'tcx, 'a> {
|
||||||
|
fn from(l: &'a mut TypeVariableStorage<'tcx>) -> Self {
|
||||||
|
let TypeVariableStorage { eq_relations, sub_relations, values } = l;
|
||||||
|
Self { eq_relations, sub_relations, values }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Rollback<UndoLog<'tcx>> for RollbackView<'tcx, '_> {
|
||||||
|
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
||||||
|
match undo {
|
||||||
|
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
|
||||||
|
UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
|
||||||
|
UndoLog::Values(undo) => self.values.reverse(undo),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TypeVariableStorage<'tcx> {
|
||||||
|
values: Vec<TypeVariableData>,
|
||||||
|
|
||||||
/// Two variables are unified in `eq_relations` when we have a
|
/// Two variables are unified in `eq_relations` when we have a
|
||||||
/// constraint `?X == ?Y`. This table also stores, for each key,
|
/// constraint `?X == ?Y`. This table also stores, for each key,
|
||||||
/// the known value.
|
/// the known value.
|
||||||
eq_relations: ut::UnificationTable<ut::InPlace<TyVidEqKey<'tcx>>>,
|
eq_relations: ut::UnificationStorage<TyVidEqKey<'tcx>>,
|
||||||
|
|
||||||
/// Two variables are unified in `sub_relations` when we have a
|
/// Two variables are unified in `sub_relations` when we have a
|
||||||
/// constraint `?X <: ?Y` *or* a constraint `?Y <: ?X`. This second
|
/// constraint `?X <: ?Y` *or* a constraint `?Y <: ?X`. This second
|
||||||
@ -34,7 +91,17 @@ pub struct TypeVariableTable<'tcx> {
|
|||||||
/// This is reasonable because, in Rust, subtypes have the same
|
/// This is reasonable because, in Rust, subtypes have the same
|
||||||
/// "skeleton" and hence there is no possible type such that
|
/// "skeleton" and hence there is no possible type such that
|
||||||
/// (e.g.) `Box<?3> <: ?3` for any `?3`.
|
/// (e.g.) `Box<?3> <: ?3` for any `?3`.
|
||||||
sub_relations: ut::UnificationTable<ut::InPlace<ty::TyVid>>,
|
sub_relations: ut::UnificationStorage<ty::TyVid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TypeVariableTable<'tcx, 'a> {
|
||||||
|
values: &'a mut Vec<TypeVariableData>,
|
||||||
|
|
||||||
|
eq_relations: &'a mut ut::UnificationStorage<TyVidEqKey<'tcx>>,
|
||||||
|
|
||||||
|
sub_relations: &'a mut ut::UnificationStorage<ty::TyVid>,
|
||||||
|
|
||||||
|
undo_log: &'a mut Logs<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@ -62,7 +129,7 @@ pub enum TypeVariableOriginKind {
|
|||||||
LatticeVariable,
|
LatticeVariable,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TypeVariableData {
|
pub(crate) struct TypeVariableData {
|
||||||
origin: TypeVariableOrigin,
|
origin: TypeVariableOrigin,
|
||||||
diverging: bool,
|
diverging: bool,
|
||||||
}
|
}
|
||||||
@ -92,32 +159,41 @@ impl<'tcx> TypeVariableValue<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Snapshot<'tcx> {
|
pub struct Snapshot<'tcx> {
|
||||||
snapshot: sv::Snapshot,
|
value_count: u32,
|
||||||
eq_snapshot: ut::Snapshot<ut::InPlace<TyVidEqKey<'tcx>>>,
|
_marker: PhantomData<&'tcx ()>,
|
||||||
sub_snapshot: ut::Snapshot<ut::InPlace<ty::TyVid>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Instantiate {
|
pub(crate) struct Instantiate {
|
||||||
vid: ty::TyVid,
|
vid: ty::TyVid,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Delegate;
|
pub(crate) struct Delegate;
|
||||||
|
|
||||||
impl<'tcx> TypeVariableTable<'tcx> {
|
impl<'tcx> TypeVariableStorage<'tcx> {
|
||||||
pub fn new() -> TypeVariableTable<'tcx> {
|
pub fn new() -> TypeVariableStorage<'tcx> {
|
||||||
TypeVariableTable {
|
TypeVariableStorage {
|
||||||
values: sv::SnapshotVec::new(),
|
values: Vec::new(),
|
||||||
eq_relations: ut::UnificationTable::new(),
|
eq_relations: ut::UnificationStorage::new(),
|
||||||
sub_relations: ut::UnificationTable::new(),
|
sub_relations: ut::UnificationStorage::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn with_log<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
undo_log: &'a mut Logs<'tcx>,
|
||||||
|
) -> TypeVariableTable<'tcx, 'a> {
|
||||||
|
let TypeVariableStorage { values, eq_relations, sub_relations } = self;
|
||||||
|
TypeVariableTable { values, eq_relations, sub_relations, undo_log }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeVariableTable<'tcx, '_> {
|
||||||
/// Returns the diverges flag given when `vid` was created.
|
/// Returns the diverges flag given when `vid` was created.
|
||||||
///
|
///
|
||||||
/// Note that this function does not return care whether
|
/// Note that this function does not return care whether
|
||||||
/// `vid` has been unified with something else or not.
|
/// `vid` has been unified with something else or not.
|
||||||
pub fn var_diverges(&self, vid: ty::TyVid) -> bool {
|
pub fn var_diverges(&self, vid: ty::TyVid) -> bool {
|
||||||
self.values.get(vid.index as usize).diverging
|
self.values.get(vid.index as usize).unwrap().diverging
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the origin that was given when `vid` was created.
|
/// Returns the origin that was given when `vid` was created.
|
||||||
@ -125,7 +201,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
/// Note that this function does not return care whether
|
/// Note that this function does not return care whether
|
||||||
/// `vid` has been unified with something else or not.
|
/// `vid` has been unified with something else or not.
|
||||||
pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
|
pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
|
||||||
&self.values.get(vid.index as usize).origin
|
&self.values.get(vid.index as usize).unwrap().origin
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Records that `a == b`, depending on `dir`.
|
/// Records that `a == b`, depending on `dir`.
|
||||||
@ -134,8 +210,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
pub fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
pub fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
||||||
debug_assert!(self.probe(a).is_unknown());
|
debug_assert!(self.probe(a).is_unknown());
|
||||||
debug_assert!(self.probe(b).is_unknown());
|
debug_assert!(self.probe(b).is_unknown());
|
||||||
self.eq_relations.union(a, b);
|
self.eq_relations().union(a, b);
|
||||||
self.sub_relations.union(a, b);
|
self.sub_relations().union(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Records that `a <: b`, depending on `dir`.
|
/// Records that `a <: b`, depending on `dir`.
|
||||||
@ -144,7 +220,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
pub fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
pub fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
||||||
debug_assert!(self.probe(a).is_unknown());
|
debug_assert!(self.probe(a).is_unknown());
|
||||||
debug_assert!(self.probe(b).is_unknown());
|
debug_assert!(self.probe(b).is_unknown());
|
||||||
self.sub_relations.union(a, b);
|
self.sub_relations().union(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiates `vid` with the type `ty`.
|
/// Instantiates `vid` with the type `ty`.
|
||||||
@ -154,18 +230,18 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
let vid = self.root_var(vid);
|
let vid = self.root_var(vid);
|
||||||
debug_assert!(self.probe(vid).is_unknown());
|
debug_assert!(self.probe(vid).is_unknown());
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.eq_relations.probe_value(vid).is_unknown(),
|
self.eq_relations().probe_value(vid).is_unknown(),
|
||||||
"instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
|
"instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
|
||||||
vid,
|
vid,
|
||||||
ty,
|
ty,
|
||||||
self.eq_relations.probe_value(vid)
|
self.eq_relations().probe_value(vid)
|
||||||
);
|
);
|
||||||
self.eq_relations.union_value(vid, TypeVariableValue::Known { value: ty });
|
self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty });
|
||||||
|
|
||||||
// Hack: we only need this so that `types_escaping_snapshot`
|
// Hack: we only need this so that `types_escaping_snapshot`
|
||||||
// can see what has been unified; see the Delegate impl for
|
// can see what has been unified; see the Delegate impl for
|
||||||
// more details.
|
// more details.
|
||||||
self.values.record(Instantiate { vid });
|
self.undo_log.push(Instantiate { vid });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new type variable.
|
/// Creates a new type variable.
|
||||||
@ -184,12 +260,12 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
diverging: bool,
|
diverging: bool,
|
||||||
origin: TypeVariableOrigin,
|
origin: TypeVariableOrigin,
|
||||||
) -> ty::TyVid {
|
) -> ty::TyVid {
|
||||||
let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown { universe });
|
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
|
||||||
|
|
||||||
let sub_key = self.sub_relations.new_key(());
|
let sub_key = self.sub_relations().new_key(());
|
||||||
assert_eq!(eq_key.vid, sub_key);
|
assert_eq!(eq_key.vid, sub_key);
|
||||||
|
|
||||||
let index = self.values.push(TypeVariableData { origin, diverging });
|
let index = self.values().push(TypeVariableData { origin, diverging });
|
||||||
assert_eq!(eq_key.vid.index, index as u32);
|
assert_eq!(eq_key.vid.index, index as u32);
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
@ -211,7 +287,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
/// algorithm), so `root_var(a) == root_var(b)` implies that `a ==
|
/// algorithm), so `root_var(a) == root_var(b)` implies that `a ==
|
||||||
/// b` (transitively).
|
/// b` (transitively).
|
||||||
pub fn root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
pub fn root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
||||||
self.eq_relations.find(vid).vid
|
self.eq_relations().find(vid).vid
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the "root" variable of `vid` in the `sub_relations`
|
/// Returns the "root" variable of `vid` in the `sub_relations`
|
||||||
@ -222,7 +298,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
///
|
///
|
||||||
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
|
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
|
||||||
pub fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
pub fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
||||||
self.sub_relations.find(vid)
|
self.sub_relations().find(vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if `a` and `b` have same "sub-root" (i.e., exists some
|
/// Returns `true` if `a` and `b` have same "sub-root" (i.e., exists some
|
||||||
@ -240,7 +316,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
/// An always-inlined variant of `probe`, for very hot call sites.
|
/// An always-inlined variant of `probe`, for very hot call sites.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn inlined_probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
|
pub fn inlined_probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
|
||||||
self.eq_relations.inlined_probe_value(vid)
|
self.eq_relations().inlined_probe_value(vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `t` is a type-inference variable, and it has been
|
/// If `t` is a type-inference variable, and it has been
|
||||||
@ -261,40 +337,31 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
/// (`rollback_to()`). Nested snapshots are permitted, but must
|
/// (`rollback_to()`). Nested snapshots are permitted, but must
|
||||||
/// be processed in a stack-like fashion.
|
/// be processed in a stack-like fashion.
|
||||||
pub fn snapshot(&mut self) -> Snapshot<'tcx> {
|
pub fn snapshot(&mut self) -> Snapshot<'tcx> {
|
||||||
Snapshot {
|
Snapshot { value_count: self.eq_relations().len() as u32, _marker: PhantomData }
|
||||||
snapshot: self.values.start_snapshot(),
|
|
||||||
eq_snapshot: self.eq_relations.snapshot(),
|
|
||||||
sub_snapshot: self.sub_relations.snapshot(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Undoes all changes since the snapshot was created. Any
|
fn values(&mut self) -> sv::SnapshotVec<Delegate, &mut Vec<TypeVariableData>, &mut Logs<'tcx>> {
|
||||||
/// snapshots created since that point must already have been
|
sv::SnapshotVec::with_log(self.values, self.undo_log)
|
||||||
/// committed or rolled back.
|
|
||||||
pub fn rollback_to(&mut self, s: Snapshot<'tcx>) {
|
|
||||||
debug!("rollback_to{:?}", {
|
|
||||||
for action in self.values.actions_since_snapshot(&s.snapshot) {
|
|
||||||
if let sv::UndoLog::NewElem(index) = *action {
|
|
||||||
debug!("inference variable _#{}t popped", index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let Snapshot { snapshot, eq_snapshot, sub_snapshot } = s;
|
|
||||||
self.values.rollback_to(snapshot);
|
|
||||||
self.eq_relations.rollback_to(eq_snapshot);
|
|
||||||
self.sub_relations.rollback_to(sub_snapshot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Commits all changes since the snapshot was created, making
|
fn eq_relations(
|
||||||
/// them permanent (unless this snapshot was created within
|
&mut self,
|
||||||
/// another snapshot). Any snapshots created since that point
|
) -> ut::UnificationTable<
|
||||||
/// must already have been committed or rolled back.
|
ut::InPlace<
|
||||||
pub fn commit(&mut self, s: Snapshot<'tcx>) {
|
TyVidEqKey<'tcx>,
|
||||||
let Snapshot { snapshot, eq_snapshot, sub_snapshot } = s;
|
&mut ut::UnificationStorage<TyVidEqKey<'tcx>>,
|
||||||
self.values.commit(snapshot);
|
&mut Logs<'tcx>,
|
||||||
self.eq_relations.commit(eq_snapshot);
|
>,
|
||||||
self.sub_relations.commit(sub_snapshot);
|
> {
|
||||||
|
ut::UnificationTable::with_log(self.eq_relations, self.undo_log)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sub_relations(
|
||||||
|
&mut self,
|
||||||
|
) -> ut::UnificationTable<
|
||||||
|
ut::InPlace<ty::TyVid, &mut ut::UnificationStorage<ty::TyVid>, &mut Logs<'tcx>>,
|
||||||
|
> {
|
||||||
|
ut::UnificationTable::with_log(self.sub_relations, self.undo_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a range of the type variables created during the snapshot.
|
/// Returns a range of the type variables created during the snapshot.
|
||||||
@ -302,11 +369,12 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
s: &Snapshot<'tcx>,
|
s: &Snapshot<'tcx>,
|
||||||
) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
|
) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
|
||||||
let range = self.eq_relations.vars_since_snapshot(&s.eq_snapshot);
|
let range =
|
||||||
|
TyVid { index: s.value_count }..TyVid { index: self.eq_relations().len() as u32 };
|
||||||
(
|
(
|
||||||
range.start.vid..range.end.vid,
|
range.start..range.end,
|
||||||
(range.start.vid.index..range.end.vid.index)
|
(range.start.index..range.end.index)
|
||||||
.map(|index| self.values.get(index as usize).origin)
|
.map(|index| self.values.get(index as usize).unwrap().origin)
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -317,14 +385,15 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
/// a type variable `V0`, then we started the snapshot, then we
|
/// a type variable `V0`, then we started the snapshot, then we
|
||||||
/// created a type variable `V1`, unified `V0` with `T0`, and
|
/// created a type variable `V1`, unified `V0` with `T0`, and
|
||||||
/// unified `V1` with `T1`, this function would return `{T0}`.
|
/// unified `V1` with `T1`, this function would return `{T0}`.
|
||||||
pub fn types_escaping_snapshot(&mut self, s: &Snapshot<'tcx>) -> Vec<Ty<'tcx>> {
|
pub fn types_escaping_snapshot(&mut self, s: &super::Snapshot<'tcx>) -> Vec<Ty<'tcx>> {
|
||||||
let mut new_elem_threshold = u32::MAX;
|
let mut new_elem_threshold = u32::MAX;
|
||||||
let mut escaping_types = Vec::new();
|
let mut escaping_types = Vec::new();
|
||||||
let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot);
|
let actions_since_snapshot = self.undo_log.actions_since_snapshot(s);
|
||||||
debug!("actions_since_snapshot.len() = {}", actions_since_snapshot.len());
|
debug!("actions_since_snapshot.len() = {}", actions_since_snapshot.len());
|
||||||
for action in actions_since_snapshot {
|
for i in 0..actions_since_snapshot.len() {
|
||||||
match *action {
|
let actions_since_snapshot = self.undo_log.actions_since_snapshot(s);
|
||||||
sv::UndoLog::NewElem(index) => {
|
match actions_since_snapshot[i] {
|
||||||
|
super::UndoLog::TypeVariables(UndoLog::Values(sv::UndoLog::NewElem(index))) => {
|
||||||
// if any new variables were created during the
|
// if any new variables were created during the
|
||||||
// snapshot, remember the lower index (which will
|
// snapshot, remember the lower index (which will
|
||||||
// always be the first one we see). Note that this
|
// always be the first one we see). Note that this
|
||||||
@ -334,11 +403,17 @@ impl<'tcx> TypeVariableTable<'tcx> {
|
|||||||
debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold);
|
debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
sv::UndoLog::Other(Instantiate { vid, .. }) => {
|
super::UndoLog::TypeVariables(UndoLog::Values(sv::UndoLog::Other(
|
||||||
|
Instantiate { vid, .. },
|
||||||
|
))) => {
|
||||||
if vid.index < new_elem_threshold {
|
if vid.index < new_elem_threshold {
|
||||||
// quick check to see if this variable was
|
// quick check to see if this variable was
|
||||||
// created since the snapshot started or not.
|
// created since the snapshot started or not.
|
||||||
let escaping_type = match self.eq_relations.probe_value(vid) {
|
let mut eq_relations = ut::UnificationTable::with_log(
|
||||||
|
&mut *self.eq_relations,
|
||||||
|
&mut *self.undo_log,
|
||||||
|
);
|
||||||
|
let escaping_type = match eq_relations.probe_value(vid) {
|
||||||
TypeVariableValue::Unknown { .. } => bug!(),
|
TypeVariableValue::Unknown { .. } => bug!(),
|
||||||
TypeVariableValue::Known { value } => value,
|
TypeVariableValue::Known { value } => value,
|
||||||
};
|
};
|
||||||
@ -395,7 +470,7 @@ impl sv::SnapshotVecDelegate for Delegate {
|
|||||||
/// for the `eq_relations`; they carry a `TypeVariableValue` along
|
/// for the `eq_relations`; they carry a `TypeVariableValue` along
|
||||||
/// with them.
|
/// with them.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
struct TyVidEqKey<'tcx> {
|
pub(crate) struct TyVidEqKey<'tcx> {
|
||||||
vid: ty::TyVid,
|
vid: ty::TyVid,
|
||||||
|
|
||||||
// in the table, we map each ty-vid to one of these:
|
// in the table, we map each ty-vid to one of these:
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use crate::ty::{self, FloatVarValue, InferConst, IntVarValue, Ty, TyCtxt};
|
use crate::ty::{self, FloatVarValue, InferConst, IntVarValue, Ty, TyCtxt};
|
||||||
use rustc_data_structures::unify::InPlace;
|
use rustc_data_structures::snapshot_vec;
|
||||||
use rustc_data_structures::unify::{EqUnifyValue, NoError, UnificationTable, UnifyKey, UnifyValue};
|
use rustc_data_structures::undo_log::UndoLogs;
|
||||||
|
use rustc_data_structures::unify::{
|
||||||
|
self, EqUnifyValue, InPlace, NoError, UnificationTable, UnifyKey, UnifyValue,
|
||||||
|
};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
@ -212,10 +215,14 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
|
|||||||
|
|
||||||
impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {}
|
impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {}
|
||||||
|
|
||||||
pub fn replace_if_possible(
|
pub fn replace_if_possible<V, L>(
|
||||||
table: &mut UnificationTable<InPlace<ty::ConstVid<'tcx>>>,
|
table: &mut UnificationTable<InPlace<ty::ConstVid<'tcx>, V, L>>,
|
||||||
c: &'tcx ty::Const<'tcx>,
|
c: &'tcx ty::Const<'tcx>,
|
||||||
) -> &'tcx ty::Const<'tcx> {
|
) -> &'tcx ty::Const<'tcx>
|
||||||
|
where
|
||||||
|
V: snapshot_vec::VecLike<unify::Delegate<ty::ConstVid<'tcx>>>,
|
||||||
|
L: UndoLogs<snapshot_vec::UndoLog<unify::Delegate<ty::ConstVid<'tcx>>>>,
|
||||||
|
{
|
||||||
if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = c {
|
if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = c {
|
||||||
match table.probe_value(*vid).val.known() {
|
match table.probe_value(*vid).val.known() {
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
|
Loading…
Reference in New Issue
Block a user