Make `<T as Trait>::U == V` always succeed if `<T as Trait>::U` is `!`
Nobody has claimed this yet.
- Dominant language
- Markdown
- Stars
- 6.6k
- Forks
- 1.7k
- Avg merge
- 16h 14m
- Merged PRs (30d)
- 1
Description
Using #![feature(never_type)] from RFC 1216, I'd like to write a Future instance for !, so that the following compiles:
#![feature(never_type)]
use futures::future::Future;
use std::io::Error;
fn main() {
// the type of `panic!()` doesn't matter as the function call is unreachable
i_take_a_future(panic!());
}
fn i_take_a_future<F>(f: F)
where F: Future<Item = u8, Error = Error>
{
// do whatever with the future
}
As described in RFC 1216, any trait whose only associated items are methods has a trivial instance for !: just fill in every method body with match self {}. Future, however, has two associated types, Item and Error. Definitions reproduced from futures-rs:
trait Future {
type Item;
type Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error>;
}
type Poll<T, E> = Result<Async<T>, E>;
enum Async<T> {
Ready(T),
NotReady,
}
A Future instance for ! can be written as follows:
impl Future for ! {
type Item = !;
type Error = !;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match self {}
}
}
This works in nightly Rust, but the instance isn't very useful, as it can only be used where Item and Error are expected to be !. Trying the initial example produces a type match error:
error[E0271]: type mismatch resolving `<! as Future>::Item == u8`
--> <anon>
|
| i_take_a_future(panic!());
| ^^^^^^^^^^^^^^^ expected !, found u8
|
= note: expected type `!`
= note: found type `u8`
= note: required by `i_take_a_future`
error[E0271]: type mismatch resolving `<! as Future>::Error == std::io::Error`
--> <anon>
|
| i_take_a_future(panic!());
| ^^^^^^^^^^^^^^^ expected !, found struct `std::io::Error`
|
= note: expected type `!`
= note: found type `std::io::Error`
= note: required by `i_take_a_future`
As far as I can tell, it would be safe for any <T as Trait>::U == V to match successfully if <T as Trait>::U is !, in the same way that expressions of type ! can implicitly cast cast to any type, because a value of type ! can never actually be produced.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading RFC 1216 and the never_type behavior described in this issue, then examine how associated-type equality constraints are handled for !. Use the Future example as the motivating case. Done means determining and specifying whether <T as Trait>::U == V may match when the associated type is !, with the safety and type-checking implications addressed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100