Rust: can the `?` operator use `into` rather than `from`?

Created on 1 Jan 2017  路  9Comments  路  Source: rust-lang/rust

Since implementing From implies an implementation for Into, but not vice versa, this seems like it should admit strictly more programs. Not entirely convinced this would be backwards compatible though.

C-enhancement T-lang

Most helpful comment

@nikomatsakis would proper chalk integration for the trait solver be able to relax this limitation? (Could the relaxation be targeted exclusively to ??)

It would be nice if we could "fix" ? to use Into in an edition after rustc's trait solver is exclusively chalk (as far in the future as that is).

All 9 comments

Nominating for discussion. I feel like this might cause inference failures.

Conclusion from @rust-lang/lang meeting: we should try it and see!

This issue should probably get an update with the current state.

IIRC, there were some ugly inference issues when we last tried this, but I'm unable to find the discussion that tried.

I tried this in #60796, and indeed type inference was a problem. Maybe the compiler can learn some tricks to make that work better, but for now this change doesn't seem feasible.

The need for Into rather than From has come up for me in a real-world codebase. Here's a simplified motivating example:

struct E;

trait Fallible {
    type Error: Into<E>;
    fn e(&self) -> Result<(), Self::Error>;
}

fn test(f: &impl Fallible) -> Result<(), E> {
    Ok(f.e()?)
}

What the trait is trying to express is simple - any Error type that can be thrown needs to be convertible to E because of the way this trait is going to be used. Presently, this doesn't compile:

error[E0277]: `?` couldn't convert the error to `E`
 --> src/lib.rs:9:13
  |
9 |     Ok(f.e()?)
  |             ^ the trait `std::convert::From<<impl Fallible as Fallible>::Error>` is not implemented for `E`
  |
  = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
  = note: required by `std::convert::From::from`

But, there's no straightforward way to fix this since there is no way to express the "reverse bound" type Error: (E : From<Self::Error>). The only option is to decorate _all_ of the call sites with something verbose like the following, which is taken from the actual code:

        ReadError : From<<<K as Readable>::ReaderArray as ReaderArray>::Error>,
        ReadError : From<<<V as Readable>::ReaderArray as ReaderArray>::Error> {

Link to project: Tree-Buf

FWIW, you can put where E: From<Self::Error> on the trait, or even directly on the type declaration with #![feature(generic_associated_types)], but I think call sites still have trouble with #20671.

There is also a hard-coded limit in the trait system. If you have to solve a goal like ?X: Into<ReturnType>, we will fail to resolve, but if you have to solve a goal like ReturnType: From<?X>, we will potentially succeed and infer a value for ?X.

Edit: Here, ?X refers to some unknown inference variable. The hard-coded limit in today's trait system is that the Self type must be at least partly inferred for us to explore that option.

So I could see that changing ? to use Into could cause inference failures where none existed before.

I'm inclined to close this issue, myself.

I am also inclined to close this -- it seems clear that we cannot change this now anyway.

@nikomatsakis would proper chalk integration for the trait solver be able to relax this limitation? (Could the relaxation be targeted exclusively to ??)

It would be nice if we could "fix" ? to use Into in an edition after rustc's trait solver is exclusively chalk (as far in the future as that is).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cuviper picture cuviper  路  3Comments

mcarton picture mcarton  路  3Comments

zhendongsu picture zhendongsu  路  3Comments

pedrohjordao picture pedrohjordao  路  3Comments

dtolnay picture dtolnay  路  3Comments