Skip to content

Commit 7b86249

Browse files
committed
add complexity to NoSnapshotLeaks
1 parent a7c0ac3 commit 7b86249

File tree

3 files changed

+117
-81
lines changed

3 files changed

+117
-81
lines changed

compiler/rustc_infer/src/infer/snapshot/check_leaks.rs

+12-17
Original file line numberDiff line numberDiff line change
@@ -103,29 +103,24 @@ macro_rules! type_foldable_verify_no_snapshot_leaks {
103103
use $crate::infer::snapshot::check_leaks::HasSnapshotLeaksVisitor;
104104
use $crate::infer::InferCtxt;
105105
impl<$tcx> $crate::infer::snapshot::NoSnapshotLeaks<$tcx> for $t {
106-
type DataStart = HasSnapshotLeaksVisitor;
107-
type DataEnd = HasSnapshotLeaksVisitor;
108-
fn mk_data_snapshot_start(
109-
infcx: &$crate::infer::InferCtxt<$tcx>,
110-
) -> Self::DataStart {
106+
type StartData = HasSnapshotLeaksVisitor;
107+
type EndData = ($t, HasSnapshotLeaksVisitor);
108+
fn snapshot_start_data(infcx: &$crate::infer::InferCtxt<$tcx>) -> Self::StartData {
111109
HasSnapshotLeaksVisitor::new(infcx)
112110
}
113-
fn mk_data_snapshot_end(
111+
fn end_of_snapshot(
114112
_: &InferCtxt<'tcx>,
115-
visitor: Self::DataStart,
116-
) -> Self::DataEnd {
117-
visitor
113+
value: $t,
114+
visitor: Self::StartData,
115+
) -> Self::EndData {
116+
(value, visitor)
118117
}
119-
fn avoid_leaks(
120-
self,
121-
_: &InferCtxt<$tcx>,
122-
mut visitor: HasSnapshotLeaksVisitor,
123-
) -> Self {
124-
if cfg!(debug_assertions) && self.visit_with(&mut visitor).is_break() {
125-
bug!("leaking vars from snapshot: {self:?}");
118+
fn avoid_leaks(_: &InferCtxt<$tcx>, (value, mut visitor): Self::EndData) -> Self {
119+
if cfg!(debug_assertions) && value.visit_with(&mut visitor).is_break() {
120+
bug!("leaking vars from snapshot: {value:?}");
126121
}
127122

128-
self
123+
value
129124
}
130125
}
131126
};

compiler/rustc_infer/src/infer/snapshot/fudge.rs

+42-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue, ConstVidKey};
2-
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
2+
use rustc_middle::ty::TypeVisitableExt;
33
use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};
4+
use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
45

56
use crate::infer::type_variable::TypeVariableOrigin;
67
use crate::infer::InferCtxt;
@@ -101,21 +102,34 @@ impl<'tcx> InferCtxt<'tcx> {
101102
macro_rules! fudge_vars_no_snapshot_leaks {
102103
($tcx:lifetime, $t:ty) => {
103104
const _: () = {
105+
use rustc_middle::ty::TypeVisitableExt;
104106
use $crate::infer::snapshot::fudge::InferenceFudgeData;
105107
impl<$tcx> $crate::infer::snapshot::NoSnapshotLeaks<$tcx> for $t {
106-
type DataStart = $crate::infer::snapshot::VariableLengths;
107-
type DataEnd = InferenceFudgeData;
108-
fn mk_data_snapshot_start(infcx: &InferCtxt<$tcx>) -> Self::DataStart {
108+
type StartData = $crate::infer::snapshot::VariableLengths;
109+
type EndData = ($t, Option<InferenceFudgeData>);
110+
fn snapshot_start_data(infcx: &InferCtxt<$tcx>) -> Self::StartData {
109111
infcx.variable_lengths()
110112
}
111-
fn mk_data_snapshot_end(
113+
fn end_of_snapshot(
112114
infcx: &InferCtxt<$tcx>,
113-
variable_lengths: Self::DataStart,
114-
) -> Self::DataEnd {
115-
InferenceFudgeData::new(infcx, variable_lengths)
115+
value: $t,
116+
variable_lengths: Self::StartData,
117+
) -> Self::EndData {
118+
if value.has_infer() {
119+
(value, Some(InferenceFudgeData::new(infcx, variable_lengths)))
120+
} else {
121+
(value, None)
122+
}
116123
}
117-
fn avoid_leaks(self, infcx: &InferCtxt<'tcx>, fudge_data: Self::DataEnd) -> Self {
118-
fudge_data.fudge_inference(infcx, self)
124+
fn avoid_leaks(
125+
infcx: &InferCtxt<'tcx>,
126+
(value, fudge_data): Self::EndData,
127+
) -> Self {
128+
if let Some(fudge_data) = fudge_data {
129+
fudge_data.fudge_inference(infcx, value)
130+
} else {
131+
value
132+
}
119133
}
120134
}
121135
};
@@ -124,19 +138,28 @@ macro_rules! fudge_vars_no_snapshot_leaks {
124138

125139
struct FudgeInference<T>(T);
126140
impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> NoSnapshotLeaks<'tcx> for FudgeInference<T> {
127-
type DataStart = VariableLengths;
128-
type DataEnd = InferenceFudgeData;
129-
fn mk_data_snapshot_start(infcx: &InferCtxt<'tcx>) -> Self::DataStart {
141+
type StartData = VariableLengths;
142+
type EndData = (T, Option<InferenceFudgeData>);
143+
fn snapshot_start_data(infcx: &InferCtxt<'tcx>) -> Self::StartData {
130144
infcx.variable_lengths()
131145
}
132-
fn mk_data_snapshot_end(
146+
fn end_of_snapshot(
133147
infcx: &InferCtxt<'tcx>,
134-
variable_lengths: Self::DataStart,
135-
) -> Self::DataEnd {
136-
InferenceFudgeData::new(infcx, variable_lengths)
148+
FudgeInference(value): FudgeInference<T>,
149+
variable_lengths: Self::StartData,
150+
) -> Self::EndData {
151+
if value.has_infer() {
152+
(value, Some(InferenceFudgeData::new(infcx, variable_lengths)))
153+
} else {
154+
(value, None)
155+
}
137156
}
138-
fn avoid_leaks(self, infcx: &InferCtxt<'tcx>, fudge_data: Self::DataEnd) -> Self {
139-
FudgeInference(fudge_data.fudge_inference(infcx, self.0))
157+
fn avoid_leaks(infcx: &InferCtxt<'tcx>, (value, fudge_data): Self::EndData) -> Self {
158+
if let Some(fudge_data) = fudge_data {
159+
FudgeInference(fudge_data.fudge_inference(infcx, value))
160+
} else {
161+
FudgeInference(value)
162+
}
140163
}
141164
}
142165

compiler/rustc_infer/src/infer/snapshot/mod.rs

+63-45
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl<'tcx> InferCtxt<'tcx> {
6363
F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>,
6464
E: NoSnapshotLeaks<'tcx>,
6565
{
66-
let no_leaks_data = E::mk_data_snapshot_start(self);
66+
let no_leaks_data = E::snapshot_start_data(self);
6767
let snapshot = self.start_snapshot();
6868
let r = f(&snapshot);
6969
debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok());
@@ -73,9 +73,9 @@ impl<'tcx> InferCtxt<'tcx> {
7373
Ok(value)
7474
}
7575
Err(err) => {
76-
let no_leaks_data = E::mk_data_snapshot_end(self, no_leaks_data);
76+
let no_leaks_data = E::end_of_snapshot(self, err, no_leaks_data);
7777
self.rollback_to(snapshot);
78-
Err(E::avoid_leaks(err, self, no_leaks_data))
78+
Err(E::avoid_leaks(self, no_leaks_data))
7979
}
8080
}
8181
}
@@ -87,12 +87,12 @@ impl<'tcx> InferCtxt<'tcx> {
8787
F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
8888
R: NoSnapshotLeaks<'tcx>,
8989
{
90-
let no_leaks_data = R::mk_data_snapshot_start(self);
90+
let no_leaks_data = R::snapshot_start_data(self);
9191
let snapshot = self.start_snapshot();
9292
let r = f(&snapshot);
93-
let no_leaks_data = R::mk_data_snapshot_end(self, no_leaks_data);
93+
let no_leaks_data = R::end_of_snapshot(self, r, no_leaks_data);
9494
self.rollback_to(snapshot);
95-
R::avoid_leaks(r, self, no_leaks_data)
95+
R::avoid_leaks(self, no_leaks_data)
9696
}
9797

9898
pub fn probe_unchecked<R, F>(&self, f: F) -> R
@@ -139,21 +139,30 @@ pub struct VariableLengths {
139139
}
140140

141141
pub trait NoSnapshotLeaks<'tcx> {
142-
type DataStart;
143-
type DataEnd;
144-
fn mk_data_snapshot_start(infcx: &InferCtxt<'tcx>) -> Self::DataStart;
145-
fn mk_data_snapshot_end(infcx: &InferCtxt<'tcx>, start: Self::DataStart) -> Self::DataEnd;
146-
fn avoid_leaks(self, infcx: &InferCtxt<'tcx>, data: Self::DataEnd) -> Self;
142+
type StartData;
143+
type EndData;
144+
fn snapshot_start_data(infcx: &InferCtxt<'tcx>) -> Self::StartData;
145+
fn end_of_snapshot(
146+
infcx: &InferCtxt<'tcx>,
147+
this: Self,
148+
start: Self::StartData,
149+
) -> Self::EndData;
150+
fn avoid_leaks(infcx: &InferCtxt<'tcx>, data: Self::EndData) -> Self;
147151
}
148152

149153
pub trait TrivialNoSnapshotLeaks<'tcx> {}
150154
impl<'tcx, T: TrivialNoSnapshotLeaks<'tcx>> NoSnapshotLeaks<'tcx> for T {
151-
type DataStart = ();
152-
type DataEnd = ();
153-
fn mk_data_snapshot_start(_: &InferCtxt<'tcx>) {}
154-
fn mk_data_snapshot_end(_: &InferCtxt<'tcx>, _: ()) {}
155-
fn avoid_leaks(self, _: &InferCtxt<'tcx>, _: ()) -> Self {
156-
self
155+
type StartData = ();
156+
type EndData = T;
157+
#[inline]
158+
fn snapshot_start_data(_: &InferCtxt<'tcx>) {}
159+
#[inline]
160+
fn end_of_snapshot(_: &InferCtxt<'tcx>, this: Self, _: ()) -> T {
161+
this
162+
}
163+
#[inline]
164+
fn avoid_leaks(_: &InferCtxt<'tcx>, this: T) -> Self {
165+
this
157166
}
158167
}
159168

@@ -200,16 +209,23 @@ mod impls {
200209
fudge_vars_no_snapshot_leaks!('tcx, MismatchedProjectionTypes<'tcx>);
201210

202211
impl<'tcx, T: NoSnapshotLeaks<'tcx>> NoSnapshotLeaks<'tcx> for Option<T> {
203-
type DataStart = T::DataStart;
204-
type DataEnd = T::DataEnd;
205-
fn mk_data_snapshot_start(infcx: &InferCtxt<'tcx>) -> T::DataStart {
206-
T::mk_data_snapshot_start(infcx)
212+
type StartData = T::StartData;
213+
type EndData = Option<T::EndData>;
214+
#[inline]
215+
fn snapshot_start_data(infcx: &InferCtxt<'tcx>) -> T::StartData {
216+
T::snapshot_start_data(infcx)
207217
}
208-
fn mk_data_snapshot_end(infcx: &InferCtxt<'tcx>, start_data: T::DataStart) -> T::DataEnd {
209-
T::mk_data_snapshot_end(infcx, start_data)
218+
#[inline]
219+
fn end_of_snapshot(
220+
infcx: &InferCtxt<'tcx>,
221+
this: Option<T>,
222+
start_data: T::StartData,
223+
) -> Option<T::EndData> {
224+
this.map(|this| T::end_of_snapshot(infcx, this, start_data))
210225
}
211-
fn avoid_leaks(self, infcx: &InferCtxt<'tcx>, data: Self::DataEnd) -> Self {
212-
self.map(|value| value.avoid_leaks(infcx, data))
226+
#[inline]
227+
fn avoid_leaks(infcx: &InferCtxt<'tcx>, data: Self::EndData) -> Self {
228+
data.map(|data| T::avoid_leaks(infcx, data))
213229
}
214230
}
215231

@@ -218,31 +234,33 @@ mod impls {
218234
T: NoSnapshotLeaks<'tcx>,
219235
E: NoSnapshotLeaks<'tcx>,
220236
{
221-
type DataStart = (T::DataStart, E::DataStart);
222-
type DataEnd = (T::DataEnd, E::DataEnd);
223-
fn mk_data_snapshot_start(infcx: &InferCtxt<'tcx>) -> Self::DataStart {
224-
(T::mk_data_snapshot_start(infcx), E::mk_data_snapshot_start(infcx))
237+
type StartData = (T::StartData, E::StartData);
238+
type EndData = Result<T::EndData, E::EndData>;
239+
#[inline]
240+
fn snapshot_start_data(infcx: &InferCtxt<'tcx>) -> Self::StartData {
241+
(T::snapshot_start_data(infcx), E::snapshot_start_data(infcx))
225242
}
226-
fn mk_data_snapshot_end(infcx: &InferCtxt<'tcx>, (t, e): Self::DataStart) -> Self::DataEnd {
227-
(T::mk_data_snapshot_end(infcx, t), E::mk_data_snapshot_end(infcx, e))
243+
#[inline]
244+
fn end_of_snapshot(
245+
infcx: &InferCtxt<'tcx>,
246+
this: Self,
247+
(t, e): Self::StartData,
248+
) -> Self::EndData {
249+
match this {
250+
Ok(value) => Ok(T::end_of_snapshot(infcx, value, t)),
251+
Err(err) => Err(E::end_of_snapshot(infcx, err, e)),
252+
}
228253
}
229-
fn avoid_leaks(self, infcx: &InferCtxt<'tcx>, (t, e): Self::DataEnd) -> Self {
230-
match self {
231-
Ok(value) => Ok(value.avoid_leaks(infcx, t)),
232-
Err(err) => Err(err.avoid_leaks(infcx, e)),
254+
255+
#[inline]
256+
fn avoid_leaks(infcx: &InferCtxt<'tcx>, data: Self::EndData) -> Self {
257+
match data {
258+
Ok(value) => Ok(T::avoid_leaks(infcx, value)),
259+
Err(err) => Err(E::avoid_leaks(infcx, err)),
233260
}
234261
}
235262
}
236263

237264
impl<'tcx, T: TrivialNoSnapshotLeaks<'tcx>> TrivialNoSnapshotLeaks<'tcx> for Vec<T> {}
238-
239-
impl<'tcx, V> NoSnapshotLeaks<'tcx> for Canonical<'tcx, V> {
240-
type DataStart = ();
241-
type DataEnd = ();
242-
fn mk_data_snapshot_start(_: &InferCtxt<'tcx>) {}
243-
fn mk_data_snapshot_end(_: &InferCtxt<'tcx>, _: ()) {}
244-
fn avoid_leaks(self, _: &InferCtxt<'tcx>, _: ()) -> Self {
245-
self
246-
}
247-
}
265+
impl<'tcx, V> TrivialNoSnapshotLeaks<'tcx> for Canonical<'tcx, V> {}
248266
}

0 commit comments

Comments
 (0)