Skip to content

covariant method return types on trait impls? #15687

Closed
@pnkfelix

Description

@pnkfelix

Do trait method signatures have to match exactly, or is there some subtyping relationship that is supposed to hold between an impl's methods and the methods of the trait definition itself?

If there is a subtyping relationship, then I would expect the following to compile:

#![crate_type="lib"]

// illustrating subtype relationship: typeof(g) <: typeof(f) ...
fn foo<'a,'b>(ignored: Option<&'a &'b ()>, f: || -> &'a int) { unimplemented!() }
fn bar<'a,'b>(ignored: Option<&'a &'b ()>, g: || -> &'b int) { foo(ignored, g) }

// ... but does that subtype relationship apply to the return types here?
trait T       { fn m<'a,'b>(self, ignored: Option<&'a &'b ()>) -> &'a int; }
impl T for () { fn m<'a,'b>(self, ignored: Option<&'a &'b ()>) -> &'b int { unimplemented!() } }

(it currently does not compile; it complains of the mismatch between the lifetime parameters.)

If there is not a subtyping relationship, then I would not expect the following to compile:

#![crate_type="lib"]

trait T<'a>                       { fn m(&'a self) -> &'a int; }
impl<'ignored> T<'ignored> for () { fn m<'a>(&'a self) -> &'a int { unimplemented!() } }

(it currently does compile.)

Note that the latter case seems sound to me, but the fact that this works in the latter case but does not for the former case just makes me worry about what the rules actually are that we are enforcing with respect to how much an impl needs to conform with its corresponding trait.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions