@@ -98,6 +98,12 @@ impl<'tcx> InferCtxt<'tcx> {
98
98
}
99
99
}
100
100
101
+ /// To avoid leaking inference variables from snapshots, fudge inference
102
+ /// by replacing inference variables from the snapshot with fresh ones
103
+ /// created outside of it.
104
+ ///
105
+ /// To see how this works, check out the documentation of the [`FudgeInference`]
106
+ /// wrapper used by [`fn InferCtxt::fudge_inference_if_ok`].
101
107
#[ macro_export]
102
108
macro_rules! fudge_vars_no_snapshot_leaks {
103
109
( $tcx: lifetime, $t: ty) => {
@@ -136,13 +142,22 @@ macro_rules! fudge_vars_no_snapshot_leaks {
136
142
} ;
137
143
}
138
144
145
+ /// When rolling back a snapshot, replaces inference variables in `T` created
146
+ /// during the snapshot with new inference variables created afterwards.
139
147
struct FudgeInference < T > ( T ) ;
140
148
impl < ' tcx , T : TypeFoldable < TyCtxt < ' tcx > > > NoSnapshotLeaks < ' tcx > for FudgeInference < T > {
141
149
type StartData = VariableLengths ;
142
150
type EndData = ( T , Option < InferenceFudgeData > ) ;
151
+
152
+ /// Store which inference variables already exist at the start
153
+ /// of the snapshot.
143
154
fn snapshot_start_data ( infcx : & InferCtxt < ' tcx > ) -> Self :: StartData {
144
155
infcx. variable_lengths ( )
145
156
}
157
+ /// At the end of the snapshot, fetch the metadata for all variables
158
+ /// created during the snapshot. As these variables get discarded during
159
+ /// rollback, we have to get this information before rollback and use it
160
+ /// to create new inference variables after.
146
161
fn end_of_snapshot (
147
162
infcx : & InferCtxt < ' tcx > ,
148
163
FudgeInference ( value) : FudgeInference < T > ,
@@ -154,6 +169,9 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> NoSnapshotLeaks<'tcx> for FudgeInferen
154
169
( value, None )
155
170
}
156
171
}
172
+ /// Using the metadata fetched in `fn end_of_snapshot`, replace all leaking
173
+ /// inference variables with new ones, reusing the metadata of the leaked
174
+ /// variables.
157
175
fn avoid_leaks ( infcx : & InferCtxt < ' tcx > , ( value, fudge_data) : Self :: EndData ) -> Self {
158
176
if let Some ( fudge_data) = fudge_data {
159
177
FudgeInference ( fudge_data. fudge_inference ( infcx, value) )
@@ -163,6 +181,8 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> NoSnapshotLeaks<'tcx> for FudgeInferen
163
181
}
164
182
}
165
183
184
+ /// At the end of a snpashot, right before rollback, remember all newly created
185
+ /// inference variables and their metadata.
166
186
pub struct InferenceFudgeData {
167
187
type_vars : ( Range < TyVid > , Vec < TypeVariableOrigin > ) ,
168
188
int_vars : Range < IntVid > ,
@@ -210,6 +230,10 @@ impl InferenceFudgeData {
210
230
}
211
231
}
212
232
233
+ /// Using the `InferenceFudgeData` created right before rollback, replace
234
+ /// all leaked inference variables of the snapshot with newly created ones.
235
+ ///
236
+ /// This is used after the snapshot has already been rolled back.
213
237
struct InferenceFudger < ' a , ' tcx > {
214
238
infcx : & ' a InferCtxt < ' tcx > ,
215
239
data : InferenceFudgeData ,
0 commit comments