Skip to content

Commit 8f80259

Browse files
committed
Explain false edges in more detail
1 parent 50103ab commit 8f80259

File tree

1 file changed

+45
-3
lines changed
  • compiler/rustc_mir_build/src/build/matches

1 file changed

+45
-3
lines changed

compiler/rustc_mir_build/src/build/matches/mod.rs

+45-3
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
214214
///
215215
/// ## False edges
216216
///
217-
/// We don't want to have the exact structure of the decision tree be
218-
/// visible through borrow checking. False edges ensure that the CFG as
219-
/// seen by borrow checking doesn't encode this. False edges are added:
217+
/// We don't want to have the exact structure of the decision tree be visible through borrow
218+
/// checking. Specifically we want borrowck to think that:
219+
/// - at any point, any or none of the patterns and guards seen so far may have been tested;
220+
/// - after the match, any of the patterns may have matched.
221+
///
222+
/// For example, all of these would fail to error if borrowck could see the real CFG (examples
223+
/// taken from `tests/ui/nll/match-cfg-fake-edges.rs`):
224+
/// ```ignore (too many errors, this is already in the test suite)
225+
/// let x = String::new();
226+
/// let _ = match true {
227+
/// _ => {},
228+
/// _ => drop(x),
229+
/// };
230+
/// // Borrowck must not know the second arm is never run.
231+
/// drop(x); //~ ERROR use of moved value
232+
///
233+
/// let x;
234+
/// # let y = true;
235+
/// match y {
236+
/// _ if { x = 2; true } => {},
237+
/// // Borrowck must not know the guard is always run.
238+
/// _ => drop(x), //~ ERROR used binding `x` is possibly-uninitialized
239+
/// };
240+
///
241+
/// let x = String::new();
242+
/// # let y = true;
243+
/// match y {
244+
/// false if { drop(x); true } => {},
245+
/// // Borrowck must not know the guard is not run in the `true` case.
246+
/// true => drop(x), //~ ERROR use of moved value: `x`
247+
/// false => {},
248+
/// };
249+
///
250+
/// # let mut y = (true, true);
251+
/// let r = &mut y.1;
252+
/// match y {
253+
/// //~^ ERROR cannot use `y.1` because it was mutably borrowed
254+
/// (false, true) => {}
255+
/// // Borrowck must not know we don't test `y.1` when `y.0` is `true`.
256+
/// (true, _) => drop(r),
257+
/// (false, _) => {}
258+
/// };
259+
/// ```
260+
///
261+
/// To ensure this, we add false edges:
220262
///
221263
/// * From each pre-binding block to the next pre-binding block.
222264
/// * From each otherwise block to the next pre-binding block.

0 commit comments

Comments
 (0)