|
1 |
| -Answer: error |
2 |
| -Difficulty: 3 |
| 1 | +Answer: 112 |
| 2 | +Difficulty: 2 |
3 | 3 |
|
4 | 4 | # Hint
|
5 | 5 |
|
6 |
| -The answer is different for Rust versions 1.0 through 1.32 vs 1.33+. The answer |
7 |
| -accepted as correct here is the one for compilers 1.33+. |
| 6 | +If you are familiar with [higher-rank trait bound][hrtb] syntax, try desugaring |
| 7 | +all the types in the impl signatures and types in `main` into their fully |
| 8 | +explicit form. |
8 | 9 |
|
9 |
| -# Explanation |
| 10 | +[hrtb]: https://doc.rust-lang.org/nomicon/hrtb.html |
10 | 11 |
|
11 |
| -This is a rare example of a Rust program that *used to* compile. This code |
12 |
| -compiles and runs successfully with every Rust version 1.0 through 1.32, |
13 |
| -printing the output `112`. The reasoning on those compilers is as follows. |
| 12 | +# Explanation |
14 | 13 |
|
15 | 14 | The first impl applies to function pointers of type `fn(T)` where `T` is any
|
16 | 15 | single concrete type. The second impl applies to function pointers of
|
17 |
| -[higher-ranked] type `for<'a> fn(&'a T)` for some concrete type `T` that |
18 |
| -outlives `'a`. |
19 |
| - |
20 |
| -[higher-ranked]: https://doc.rust-lang.org/nomicon/hrtb.html |
| 16 | +higher-ranked type `for<'a> fn(&'a T)` for some concrete type `T` that outlives |
| 17 | +`'a`. |
21 | 18 |
|
22 | 19 | Inside of `main`, the compiler is going to use type inference to substitute all
|
23 | 20 | occurrences of `_` in a type by some concrete type.
|
24 | 21 |
|
25 |
| -For the function pointer `a` we infer `_ = u8`, yielding the function pointer |
26 |
| -type `fn(u8)` taking an argument of type `u8` and returning `()`. |
| 22 | +For the closure `a` we infer `_ = u8`, yielding the closure type `fn(u8)` taking |
| 23 | +an argument of type `u8` and returning `()`. |
27 | 24 |
|
28 | 25 | For `b` we infer `_ = &'x u8` for some concrete lifetime `'x` that will
|
29 | 26 | ultimately feed into the borrow checker. The type of `b` is `fn(&'x u8)`.
|
30 | 27 |
|
31 |
| -And finally for `c` we infer `_ = u8`, yielding the higher-ranked function |
32 |
| -pointer type `for<'a> fn(&'a u8)`. |
| 28 | +And finally for `c` we infer `_ = u8`, yielding the higher-ranked closure type |
| 29 | +`for<'a> fn(&'a u8)`. |
33 | 30 |
|
34 | 31 | Framed in this way, it follows that the trait method calls at the end of `main`
|
35 | 32 | print `112`.
|
36 |
| - |
37 |
| -The compiler's reasoning changed in Rust version 1.33 as part of the ["universe |
38 |
| -transition"] and this program no longer compiles. Under the new model the first |
39 |
| -impl applies to all three function pointers. If the second impl didn't exist, |
40 |
| -the program would compile and print `111`. But with both impls present these are |
41 |
| -considered conflicting impls and the program fails to compile. |
42 |
| - |
43 |
| -["universe transition"]: https://github.com/rust-lang/rust/issues/56105 |
0 commit comments