@@ -202,9 +202,48 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
202
202
///
203
203
/// ## False edges
204
204
///
205
- /// We don't want to have the exact structure of the decision tree be
206
- /// visible through borrow checking. False edges ensure that the CFG as
207
- /// seen by borrow checking doesn't encode this. False edges are added:
205
+ /// We don't want to have the exact structure of the decision tree be visible through borrow
206
+ /// checking. Specifically we want borrowck to think that:
207
+ /// - at any point, any or none of the patterns and guards seen so far may have been tested;
208
+ /// - after the match, any of the patterns may have matched.
209
+ ///
210
+ /// For example, all of these would fail to error if borrowck could see the real CFG (taken from
211
+ /// `tests/ui/nll/match-cfg-fake-edges.rs`):
212
+ /// ```rust,ignore(too many errors)
213
+ /// let x = String::new();
214
+ /// let _ = match true {
215
+ /// _ => {},
216
+ /// _ => drop(x),
217
+ /// };
218
+ /// // Borrowck must not know the second arm is never run.
219
+ /// drop(x); //~ ERROR use of moved value
220
+ ///
221
+ /// let x;
222
+ /// match y {
223
+ /// _ if { x = 2; true } => {},
224
+ /// // Borrowck must not know the guard is always run.
225
+ /// _ => drop(x), //~ ERROR used binding `x` is possibly-uninitialized
226
+ /// };
227
+ ///
228
+ /// let x = String::new();
229
+ /// match y {
230
+ /// false if { drop(x); true } => {},
231
+ /// // Borrowck must not know the guard is not run in the `true` case.
232
+ /// true => drop(x), //~ ERROR use of moved value: `x`
233
+ /// false => {},
234
+ /// };
235
+ ///
236
+ /// let r = &mut y.1;
237
+ /// match y {
238
+ /// //~^ ERROR cannot use `y.1` because it was mutably borrowed
239
+ /// (false, true) => {}
240
+ /// // Borrowck must not know we don't test `y.1` when `y.0` is `true`.
241
+ /// (true, _) => drop(r),
242
+ /// (false, _) => {}
243
+ /// };
244
+ /// ```
245
+ ///
246
+ /// To ensure this, we add false edges:
208
247
///
209
248
/// * From each pre-binding block to the next pre-binding block.
210
249
/// * From each otherwise block to the next pre-binding block.
0 commit comments