Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.

Commit a4c43a3

Browse files
committed
Propose updates to closure pretty print
1 parent f7dae8b commit a4c43a3

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

update_closure_printing.md

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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

Comments
 (0)