Skip to content

? can not use assiciated type constraints usable by .into() #55984

Open
@chrysn

Description

@chrysn

When an error type is guaranteed to come From<> a result error type by means of a trait constraint in a generic function with a constant result type, the idiom some_result.map_err(|e| e.into()) works, but the should-be equivalent Ok(some_result?) does not and produces:

the trait `std::convert::From<<W as Worker>::Error>` is not implemented for `GenericError`

That can be alleviated by explicitly demanding that From<<W as Worker>::Error> of the generic function's error type, but my expectation would be that this is implied by the type constraint -- especially since the .map_err version that should be equivalent to the ? one does "get it".

Full example:

#[derive(Debug)]
struct GenericError();

// impl Into<GenericError> for i32 {
//     fn into(self) -> GenericError {
//         GenericError()
//     }
// }

impl From<i32> for GenericError {
    fn from(_: i32) -> Self {
        GenericError()
    }
}

trait Worker {
    type Error: Into<GenericError>;

    fn do_something(&self) -> Result<(), Self::Error>;
}

struct IntegerWorker();

impl Worker for IntegerWorker {
    type Error = i32;

    fn do_something(&self) -> Result<(), Self::Error> {
        Err(42)
    }
}

fn process<W>(w: W) -> Result<(), GenericError> where
    W: Worker,
    // GenericError: From<<W as Worker>::Error>
{
    let some_result = w.do_something();
    // // This works:
    // some_result.map_err(|e| e.into())
    // This doesn't
    Ok(some_result?)
}

fn main() {
    let w = IntegerWorker();
    println!("Result: {:?}", process(w));
}

This fails to build with the above error message, while the commented-out version with .map_err(|e| e.into()) builds fine. Adding the GenericError: From<...> "where" clause solves the build error, but is unergonomic (it'd clutter all functions working on that type).

In case it is relevant: If Into<> is implemented instead of the equivalent From<> (top comment block), then the problem still exists, but adding the additional constraint does not solve it any more but produces a different error message.

Meta

Previous research on web and issue tracker search turned out dry, and disucssion on IRC just helped rule out some possible oversights. The behavior is the same with 1.29.0, 1.30.0 and current nightly; full example version:

rustc 1.30.1 (1433507eb 2018-11-07)                                                                                                                            
binary: rustc                                                                                                                                                  
commit-hash: 1433507eba7d1a114e4c6f27ae0e1a74f60f20de                                                                                                          
commit-date: 2018-11-07                                                                                                                                        
host: x86_64-unknown-linux-gnu                                                                                                                                 
release: 1.30.1                                                                                                                                                
LLVM version: 8.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-trait-systemArea: Trait systemT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions