Skip to content

type parameters of trait functions and impl selection combine in confusing ways #5221

Closed

Description

@Kimundi

It started with this error:

pub trait VideoDriver {
    static fn init() -> Self;
}

pub trait Platform {
    static fn init<D: VideoDriver>() -> Self;
    static fn foo() -> bool;
}

pub fn run<P: Platform, D: VideoDriver>() {
    let platform: P = Platform::init::<D>();

}
---------------------------------------------------------------------------------------------
trait_generic_method.rs:11:19: 11:38 error: not enough type parameters provided for this item
trait_generic_method.rs:11     let platform: P = Platform::init::<D>();
                                              ^~~~~~~~~~~~~~~~~~~~~~
trait_generic_method.rs:11:19: 11:38 error: cannot determine a type for this bounded type parameter: unconstrained type
trait_generic_method.rs:11     let platform: P = Platform::init::<D>();
                                              ^~~~~~~~~~~~~~~~~~~~~~

Which is confusing because the init() method is just defined on one type parameter.
However if I change the line to let platform: P = Platform::init::<P, D>(); it compiles, which is confusing for the same reasons.

The cause for this is that you can specify the type of an trait impl by appending an ::<T> to the call of an function like this: let is_foo = Platform::foo::<int>(), which is fine as long as the function itself has no specific trait bounds. Combined though it's a mess, as it's not even clear in which order the parameters go.

As the type selection really belongs to the trait, and not to an function of that trait, I propose that the syntax should get changed to let platform = Platform::<P>::init::<D>().
More linenoise, but at least it's not confusing.

Activity

  1. bstrie commented on Mar 4, 2013

    @bstrie
    Contributor

    Or, since Rust has already diverged from C++ in this area, perhaps it's time to think of a less-hideous way to specify types at use sites. :)

  2. Kimundi commented on Mar 4, 2013

    @Kimundi
    ContributorAuthor

    @bstrie sure, but how? ^^

  3. bstrie commented on Mar 4, 2013

    @bstrie
    Contributor

    Putting aside syntax for the moment, I still don't understand the error here. In the line:

    Platform::init::<P, D>()
    

    what, exactly, is P, and why is it necessary?

  4. Kimundi commented on Mar 4, 2013

    @Kimundi
    ContributorAuthor

    @bstrie: The P there means 'use the implementation of Platform for type P'. It should be inferred because P is already given as type of the variable, but apparently it is required if you want to give any other specific types.

  5. nikomatsakis commented on Mar 5, 2013

    @nikomatsakis
    Contributor

    Yes, we need to integrate type parameters into paths in a better way.

  6. catamorphism commented on May 23, 2013

    @catamorphism
    Contributor

    Still a bug. Since this potentially involves changing syntax, I'm nominating for milestone 1, well-defined.

  7. graydon commented on May 23, 2013

    @graydon
    Contributor

    accepted for well-defined milestone

  8. graydon commented on May 23, 2013

    @graydon
    Contributor

    accepted for backwards-compatible milestone

  9. graydon commented on May 23, 2013

    @graydon
    Contributor

    relative of #5527

  10. emberian commented on Jul 21, 2013

    @emberian
    Contributor

    triage bump

  11. catamorphism commented on Oct 10, 2013

    @catamorphism
    Contributor

    This is done.

  12. added a commit that references this issue on May 2, 2020
  13. added a commit that references this issue on Jul 26, 2026
  14. added a commit that references this issue on Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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