Skip to content

Commit 33ef0ba

Browse files
committed
Auto merge of #59415 - varkor:values_since_snapshot, r=eddyb
Refactor InferenceFudger (née RegionFudger) - Rename `RegionFudger` (and related methods) to `InferenceFudger`. - Take integer and float inference variables into account. - Refactor `types_created_since_snapshot` and `vars_created_since_snapshot` with the [new version of ena](rust-lang/ena#21). - Some other refactoring in the area. r? @eddyb
2 parents c5fb4d0 + 86d5a69 commit 33ef0ba

File tree

9 files changed

+132
-100
lines changed

9 files changed

+132
-100
lines changed

Cargo.lock

+10-1
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,14 @@ dependencies = [
780780
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
781781
]
782782

783+
[[package]]
784+
name = "ena"
785+
version = "0.13.0"
786+
source = "registry+https://github.com/rust-lang/crates.io-index"
787+
dependencies = [
788+
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
789+
]
790+
783791
[[package]]
784792
name = "env_logger"
785793
version = "0.5.13"
@@ -2662,7 +2670,7 @@ name = "rustc_data_structures"
26622670
version = "0.0.0"
26632671
dependencies = [
26642672
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
2665-
"ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
2673+
"ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
26662674
"graphviz 0.0.0",
26672675
"jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
26682676
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4043,6 +4051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
40434051
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
40444052
"checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455"
40454053
"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00"
4054+
"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87"
40464055
"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
40474056
"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
40484057
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"

src/librustc/infer/canonical/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
360360
)
361361
}
362362

363-
CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()),
363+
CanonicalTyVarKind::Int => self.next_int_var(),
364364

365-
CanonicalTyVarKind::Float => self.tcx.mk_float_var(self.next_float_var_id()),
365+
CanonicalTyVarKind::Float => self.next_float_var(),
366366
};
367367
ty.into()
368368
}

src/librustc/infer/fudge.rs

+84-59
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use crate::infer::type_variable::TypeVariableMap;
2-
use crate::ty::{self, Ty, TyCtxt};
1+
use crate::ty::{self, Ty, TyCtxt, TyVid, IntVid, FloatVid, RegionVid};
32
use crate::ty::fold::{TypeFoldable, TypeFolder};
43

54
use super::InferCtxt;
65
use super::RegionVariableOrigin;
6+
use super::type_variable::TypeVariableOrigin;
7+
8+
use std::ops::Range;
79

810
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
911
/// This rather funky routine is used while processing expected
@@ -17,7 +19,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
1719
/// from `&[u32; 3]` to `&[u32]` and make the users life more
1820
/// pleasant.
1921
///
20-
/// The way we do this is using `fudge_regions_if_ok`. What the
22+
/// The way we do this is using `fudge_inference_if_ok`. What the
2123
/// routine actually does is to start a snapshot and execute the
2224
/// closure `f`. In our example above, what this closure will do
2325
/// is to unify the expectation (`Option<&[u32]>`) with the actual
@@ -26,7 +28,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
2628
/// with `&?a [u32]`, where `?a` is a fresh lifetime variable. The
2729
/// input type (`?T`) is then returned by `f()`.
2830
///
29-
/// At this point, `fudge_regions_if_ok` will normalize all type
31+
/// At this point, `fudge_inference_if_ok` will normalize all type
3032
/// variables, converting `?T` to `&?a [u32]` and end the
3133
/// snapshot. The problem is that we can't just return this type
3234
/// out, because it references the region variable `?a`, and that
@@ -42,36 +44,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
4244
/// regions in question are not particularly important. We will
4345
/// use the expected types to guide coercions, but we will still
4446
/// type-check the resulting types from those coercions against
45-
/// the actual types (`?T`, `Option<?T`) -- and remember that
47+
/// the actual types (`?T`, `Option<?T>`) -- and remember that
4648
/// after the snapshot is popped, the variable `?T` is no longer
4749
/// unified.
48-
pub fn fudge_regions_if_ok<T, E, F>(&self,
49-
origin: &RegionVariableOrigin,
50-
f: F) -> Result<T, E> where
50+
pub fn fudge_inference_if_ok<T, E, F>(
51+
&self,
52+
f: F,
53+
) -> Result<T, E> where
5154
F: FnOnce() -> Result<T, E>,
5255
T: TypeFoldable<'tcx>,
5356
{
54-
debug!("fudge_regions_if_ok(origin={:?})", origin);
57+
debug!("fudge_inference_if_ok()");
5558

56-
let (type_variables, region_vars, value) = self.probe(|snapshot| {
59+
let (mut fudger, value) = self.probe(|snapshot| {
5760
match f() {
5861
Ok(value) => {
5962
let value = self.resolve_type_vars_if_possible(&value);
6063

6164
// At this point, `value` could in principle refer
62-
// to types/regions that have been created during
65+
// to inference variables that have been created during
6366
// the snapshot. Once we exit `probe()`, those are
6467
// going to be popped, so we will have to
6568
// eliminate any references to them.
6669

67-
let type_variables =
68-
self.type_variables.borrow_mut().types_created_since_snapshot(
69-
&snapshot.type_snapshot);
70-
let region_vars =
71-
self.borrow_region_constraints().vars_created_since_snapshot(
72-
&snapshot.region_constraints_snapshot);
70+
let type_vars = self.type_variables.borrow_mut().vars_since_snapshot(
71+
&snapshot.type_snapshot,
72+
);
73+
let int_vars = self.int_unification_table.borrow_mut().vars_since_snapshot(
74+
&snapshot.int_snapshot,
75+
);
76+
let float_vars = self.float_unification_table.borrow_mut().vars_since_snapshot(
77+
&snapshot.float_snapshot,
78+
);
79+
let region_vars = self.borrow_region_constraints().vars_since_snapshot(
80+
&snapshot.region_constraints_snapshot,
81+
);
82+
83+
let fudger = InferenceFudger {
84+
infcx: self,
85+
type_vars,
86+
int_vars,
87+
float_vars,
88+
region_vars,
89+
};
7390

74-
Ok((type_variables, region_vars, value))
91+
Ok((fudger, value))
7592
}
7693
Err(e) => Err(e),
7794
}
@@ -84,69 +101,77 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
84101

85102
// Micro-optimization: if no variables have been created, then
86103
// `value` can't refer to any of them. =) So we can just return it.
87-
if type_variables.is_empty() && region_vars.is_empty() {
88-
return Ok(value);
104+
if fudger.type_vars.0.is_empty() &&
105+
fudger.int_vars.is_empty() &&
106+
fudger.float_vars.is_empty() &&
107+
fudger.region_vars.0.is_empty() {
108+
Ok(value)
109+
} else {
110+
Ok(value.fold_with(&mut fudger))
89111
}
90-
91-
let mut fudger = RegionFudger {
92-
infcx: self,
93-
type_variables: &type_variables,
94-
region_vars: &region_vars,
95-
origin,
96-
};
97-
98-
Ok(value.fold_with(&mut fudger))
99112
}
100113
}
101114

102-
pub struct RegionFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
115+
pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
103116
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
104-
type_variables: &'a TypeVariableMap,
105-
region_vars: &'a Vec<ty::RegionVid>,
106-
origin: &'a RegionVariableOrigin,
117+
type_vars: (Range<TyVid>, Vec<TypeVariableOrigin>),
118+
int_vars: Range<IntVid>,
119+
float_vars: Range<FloatVid>,
120+
region_vars: (Range<RegionVid>, Vec<RegionVariableOrigin>),
107121
}
108122

109-
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> {
123+
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> {
110124
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
111125
self.infcx.tcx
112126
}
113127

114128
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
115129
match ty.sty {
116130
ty::Infer(ty::InferTy::TyVar(vid)) => {
117-
match self.type_variables.get(&vid) {
118-
None => {
119-
// This variable was created before the
120-
// "fudging". Since we refresh all type
121-
// variables to their binding anyhow, we know
122-
// that it is unbound, so we can just return
123-
// it.
124-
debug_assert!(self.infcx.type_variables.borrow_mut()
125-
.probe(vid)
126-
.is_unknown());
127-
ty
128-
}
129-
130-
Some(&origin) => {
131-
// This variable was created during the
132-
// fudging. Recreate it with a fresh variable
133-
// here.
134-
self.infcx.next_ty_var(origin)
135-
}
131+
if self.type_vars.0.contains(&vid) {
132+
// This variable was created during the fudging.
133+
// Recreate it with a fresh variable here.
134+
let idx = (vid.index - self.type_vars.0.start.index) as usize;
135+
let origin = self.type_vars.1[idx];
136+
self.infcx.next_ty_var(origin)
137+
} else {
138+
// This variable was created before the
139+
// "fudging". Since we refresh all type
140+
// variables to their binding anyhow, we know
141+
// that it is unbound, so we can just return
142+
// it.
143+
debug_assert!(self.infcx.type_variables.borrow_mut()
144+
.probe(vid)
145+
.is_unknown());
146+
ty
147+
}
148+
}
149+
ty::Infer(ty::InferTy::IntVar(vid)) => {
150+
if self.int_vars.contains(&vid) {
151+
self.infcx.next_int_var()
152+
} else {
153+
ty
154+
}
155+
}
156+
ty::Infer(ty::InferTy::FloatVar(vid)) => {
157+
if self.float_vars.contains(&vid) {
158+
self.infcx.next_float_var()
159+
} else {
160+
ty
136161
}
137162
}
138163
_ => ty.super_fold_with(self),
139164
}
140165
}
141166

142167
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
143-
match *r {
144-
ty::ReVar(v) if self.region_vars.contains(&v) => {
145-
self.infcx.next_region_var(self.origin.clone())
146-
}
147-
_ => {
148-
r
168+
if let ty::ReVar(vid) = r {
169+
if self.region_vars.0.contains(&vid) {
170+
let idx = (vid.index() - self.region_vars.0.start.index()) as usize;
171+
let origin = self.region_vars.1[idx];
172+
return self.infcx.next_region_var(origin);
149173
}
150174
}
175+
r
151176
}
152177
}

src/librustc/infer/mod.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -999,14 +999,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
999999
self.tcx.mk_ty_var(self.next_ty_var_id(true, origin))
10001000
}
10011001

1002-
pub fn next_int_var_id(&self) -> IntVid {
1002+
fn next_int_var_id(&self) -> IntVid {
10031003
self.int_unification_table.borrow_mut().new_key(None)
10041004
}
10051005

1006-
pub fn next_float_var_id(&self) -> FloatVid {
1006+
pub fn next_int_var(&self) -> Ty<'tcx> {
1007+
self.tcx.mk_int_var(self.next_int_var_id())
1008+
}
1009+
1010+
fn next_float_var_id(&self) -> FloatVid {
10071011
self.float_unification_table.borrow_mut().new_key(None)
10081012
}
10091013

1014+
pub fn next_float_var(&self) -> Ty<'tcx> {
1015+
self.tcx.mk_float_var(self.next_float_var_id())
1016+
}
1017+
10101018
/// Creates a fresh region variable with the next available index.
10111019
/// The variable will be created in the maximum universe created
10121020
/// thus far, allowing it to name any region created thus far.

src/librustc/infer/region_constraints/mod.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::ty::{Region, RegionVid};
1616

1717
use std::collections::BTreeMap;
1818
use std::{cmp, fmt, mem, u32};
19+
use std::ops::Range;
1920

2021
mod leak_check;
2122

@@ -840,13 +841,14 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
840841
}
841842
}
842843

843-
pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec<RegionVid> {
844-
self.undo_log[mark.length..]
845-
.iter()
846-
.filter_map(|&elt| match elt {
847-
AddVar(vid) => Some(vid),
848-
_ => None,
849-
}).collect()
844+
pub fn vars_since_snapshot(
845+
&self,
846+
mark: &RegionSnapshot,
847+
) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
848+
let range = self.unification_table.vars_since_snapshot(&mark.region_snapshot);
849+
(range.clone(), (range.start.index()..range.end.index()).map(|index| {
850+
self.var_infos[ty::RegionVid::from(index)].origin.clone()
851+
}).collect())
850852
}
851853

852854
/// See [`RegionInference::region_constraints_added_in_snapshot`].

src/librustc/infer/type_variable.rs

+11-22
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use syntax::symbol::InternedString;
22
use syntax_pos::Span;
3-
use crate::ty::{self, Ty};
3+
use crate::ty::{self, Ty, TyVid};
44

55
use std::cmp;
66
use std::marker::PhantomData;
77
use std::u32;
8-
use rustc_data_structures::fx::FxHashMap;
8+
use std::ops::Range;
99
use rustc_data_structures::snapshot_vec as sv;
1010
use rustc_data_structures::unify as ut;
1111

@@ -58,8 +58,6 @@ pub enum TypeVariableOrigin {
5858
Generalized(ty::TyVid),
5959
}
6060

61-
pub type TypeVariableMap = FxHashMap<ty::TyVid, TypeVariableOrigin>;
62-
6361
struct TypeVariableData {
6462
origin: TypeVariableOrigin,
6563
diverging: bool,
@@ -292,24 +290,15 @@ impl<'tcx> TypeVariableTable<'tcx> {
292290
self.sub_relations.commit(sub_snapshot);
293291
}
294292

295-
/// Returns a map `{V1 -> V2}`, where the keys `{V1}` are
296-
/// ty-variables created during the snapshot, and the values
297-
/// `{V2}` are the root variables that they were unified with,
298-
/// along with their origin.
299-
pub fn types_created_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> TypeVariableMap {
300-
let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot);
301-
302-
actions_since_snapshot
303-
.iter()
304-
.filter_map(|action| match action {
305-
&sv::UndoLog::NewElem(index) => Some(ty::TyVid { index: index as u32 }),
306-
_ => None,
307-
})
308-
.map(|vid| {
309-
let origin = self.values.get(vid.index as usize).origin.clone();
310-
(vid, origin)
311-
})
312-
.collect()
293+
/// Returns a range of the type variables created during the snapshot.
294+
pub fn vars_since_snapshot(
295+
&mut self,
296+
s: &Snapshot<'tcx>,
297+
) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
298+
let range = self.eq_relations.vars_since_snapshot(&s.eq_snapshot);
299+
(range.start.vid..range.end.vid, (range.start.vid.index..range.end.vid.index).map(|index| {
300+
self.values.get(index as usize).origin.clone()
301+
}).collect())
313302
}
314303

315304
/// Finds the set of type variables that existed *before* `s`

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#![feature(non_exhaustive)]
4545
#![feature(proc_macro_internals)]
4646
#![feature(optin_builtin_traits)]
47+
#![feature(range_is_empty)]
4748
#![feature(refcell_replace_swap)]
4849
#![feature(rustc_diagnostic_macros)]
4950
#![feature(rustc_attrs)]

src/librustc_data_structures/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ path = "lib.rs"
1010
crate-type = ["dylib"]
1111

1212
[dependencies]
13-
ena = "0.11"
13+
ena = "0.13"
1414
log = "0.4"
1515
jobserver_crate = { version = "0.1", package = "jobserver" }
1616
lazy_static = "1"

0 commit comments

Comments
 (0)