|
| 1 | +# Update closure pretty printing |
| 2 | + |
| 3 | +Currently the compiler prints the capture information (name and type) of the root variable being captured. For example, current pretty print: |
| 4 | + |
| 5 | +```rust |
| 6 | +struct Point { |
| 7 | + x: i32, |
| 8 | + y: i32, |
| 9 | +} |
| 10 | + |
| 11 | +let p = Point { x: 10, y: 20 }; |
| 12 | + |
| 13 | +// pretty print: [closure@src/main.rs:8:14: 10:6 p:_] |
| 14 | +let c1 = || { |
| 15 | + println!("{}", p.x); |
| 16 | +}; |
| 17 | + |
| 18 | +// pretty print: [closure@src/main.rs:11:14: 13:6 p:_] |
| 19 | +let c2 = || { |
| 20 | + println!("{}", p.y); |
| 21 | +}; |
| 22 | +``` |
| 23 | +(`p:_`, means p is captured and its type hasn't been inferred yet) |
| 24 | + |
| 25 | + |
| 26 | +## Motivation for change |
| 27 | +- This information isn't really diagnostically useful to the end user. |
| 28 | +- Once [RFC 2229](https://github.com/rust-lang/rfcs/blob/master/text/2229-capture-disjoint-fields.md) is implemented, the current closure pretty print won't be completely accurate. In the above example, after RFC-2229 `c1` only captures `p.x` and c2 only captures `p.y`. |
| 29 | +- Closures don't print information about generics they inherit from their parent scope. |
| 30 | + |
| 31 | +## Proposed changes |
| 32 | +- Don't print capture information for closures unless `-Zverbose` is specified. |
| 33 | +- When the compiler is invoked with `-Zverbose` only print the type of the capture and not the name of or path to the variable. |
| 34 | + |
| 35 | +Applying these two changes to example above we get |
| 36 | +```rust |
| 37 | +// pretty print: [closure@src/main.rs:8:14: 10:6] |
| 38 | +let c1 = || { |
| 39 | + println!("{}", p.x); |
| 40 | +}; |
| 41 | + |
| 42 | +// compile-flags: -Zverbose |
| 43 | +// pretty print: [closure@src/main.rs:8:14: 10:6 (&i32)] |
| 44 | +let c1 = || { |
| 45 | + println!("{}", p.x); |
| 46 | +}; |
| 47 | +``` |
| 48 | +(Note this example is missing changes explained below) |
| 49 | + |
| 50 | +- If type information about captures isn't available or can't be verified as available then the information won't be printed out. |
| 51 | + |
| 52 | +```rust |
| 53 | +// compile-flags: -Zverbose |
| 54 | +// pretty print: [closure@src/main.rs:8:14: 10:6 (unavailable)] |
| 55 | +let c1 = || { |
| 56 | + println!("{}", p.x); |
| 57 | +}; |
| 58 | + |
| 59 | +let c :() = c1; // Error here prevents us from doing capture analysis |
| 60 | +``` |
| 61 | +(Note this example is missing changes explained below) |
| 62 | + |
| 63 | +- Print the path to the closure instead of the `[closure]` notation, similar to how types defined within the closure are printed. If `-Zverbose` is passed to the compiler then we print generics as part of the path. |
| 64 | + |
| 65 | +```rust |
| 66 | +mod mod1 { |
| 67 | + pub fn f<T: std::fmt::Display>(t: T) |
| 68 | + { |
| 69 | + let x = 20; |
| 70 | + |
| 71 | + // pretty print: mod1::f::{{closure}}#0 |
| 72 | + let c = || println!("{} {}", t, x); |
| 73 | + c(); // * |
| 74 | + } |
| 75 | +} |
| 76 | + |
| 77 | +fn main() { |
| 78 | + f(format!("S")); |
| 79 | +} |
| 80 | +``` |
| 81 | + |
| 82 | +If `-Zverbose` is set then pretty print for the closure will be `mod1::f<T>::{{closure}}#0 (&T, &i32)`. |
| 83 | + |
| 84 | +If `-Zverbose` is set and the line marked with `*` is changed to `let c1 :() = c`, that is it prevents us from starting capture analysis, the pretty print will be `mod1::f<T>::{{closure}}#0 (unavailable)`. |
0 commit comments