From 7432a2c14c6305fa28d9cc48f365f77ebebd3d53 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 23 Feb 2019 12:44:36 -0800 Subject: [PATCH] Revert "Update question 5 for universe transition" The breaking change was reverted in rust-lang/rust#58592. This reverts commit 6fd0e82ac05c24327bae5c89ae0a6fd8e2a802fa. --- questions/005-trait-resolution-hrtb.md | 37 +++++++++----------------- 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/questions/005-trait-resolution-hrtb.md b/questions/005-trait-resolution-hrtb.md index b182426..86da19c 100644 --- a/questions/005-trait-resolution-hrtb.md +++ b/questions/005-trait-resolution-hrtb.md @@ -1,43 +1,32 @@ -Answer: error -Difficulty: 3 +Answer: 112 +Difficulty: 2 # Hint -The answer is different for Rust versions 1.0 through 1.32 vs 1.33+. The answer -accepted as correct here is the one for compilers 1.33+. +If you are familiar with [higher-rank trait bound][hrtb] syntax, try desugaring +all the types in the impl signatures and types in `main` into their fully +explicit form. -# Explanation +[hrtb]: https://doc.rust-lang.org/nomicon/hrtb.html -This is a rare example of a Rust program that *used to* compile. This code -compiles and runs successfully with every Rust version 1.0 through 1.32, -printing the output `112`. The reasoning on those compilers is as follows. +# Explanation The first impl applies to function pointers of type `fn(T)` where `T` is any single concrete type. The second impl applies to function pointers of -[higher-ranked] type `for<'a> fn(&'a T)` for some concrete type `T` that -outlives `'a`. - -[higher-ranked]: https://doc.rust-lang.org/nomicon/hrtb.html +higher-ranked type `for<'a> fn(&'a T)` for some concrete type `T` that outlives +`'a`. Inside of `main`, the compiler is going to use type inference to substitute all occurrences of `_` in a type by some concrete type. -For the function pointer `a` we infer `_ = u8`, yielding the function pointer -type `fn(u8)` taking an argument of type `u8` and returning `()`. +For the closure `a` we infer `_ = u8`, yielding the closure type `fn(u8)` taking +an argument of type `u8` and returning `()`. For `b` we infer `_ = &'x u8` for some concrete lifetime `'x` that will ultimately feed into the borrow checker. The type of `b` is `fn(&'x u8)`. -And finally for `c` we infer `_ = u8`, yielding the higher-ranked function -pointer type `for<'a> fn(&'a u8)`. +And finally for `c` we infer `_ = u8`, yielding the higher-ranked closure type +`for<'a> fn(&'a u8)`. Framed in this way, it follows that the trait method calls at the end of `main` print `112`. - -The compiler's reasoning changed in Rust version 1.33 as part of the ["universe -transition"] and this program no longer compiles. Under the new model the first -impl applies to all three function pointers. If the second impl didn't exist, -the program would compile and print `111`. But with both impls present these are -considered conflicting impls and the program fails to compile. - -["universe transition"]: https://github.com/rust-lang/rust/issues/56105