Skip to content

Commit 7432a2c

Browse files
committed
Revert "Update question 5 for universe transition"
The breaking change was reverted in rust-lang/rust#58592. This reverts commit 6fd0e82.
1 parent 5e531c3 commit 7432a2c

File tree

1 file changed

+13
-24
lines changed

1 file changed

+13
-24
lines changed
+13-24
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,32 @@
1-
Answer: error
2-
Difficulty: 3
1+
Answer: 112
2+
Difficulty: 2
33

44
# Hint
55

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.
89

9-
# Explanation
10+
[hrtb]: https://doc.rust-lang.org/nomicon/hrtb.html
1011

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
1413

1514
The first impl applies to function pointers of type `fn(T)` where `T` is any
1615
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`.
2118

2219
Inside of `main`, the compiler is going to use type inference to substitute all
2320
occurrences of `_` in a type by some concrete type.
2421

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 `()`.
2724

2825
For `b` we infer `_ = &'x u8` for some concrete lifetime `'x` that will
2926
ultimately feed into the borrow checker. The type of `b` is `fn(&'x u8)`.
3027

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)`.
3330

3431
Framed in this way, it follows that the trait method calls at the end of `main`
3532
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

Comments
 (0)