Skip to content

object-safety and static methods #428

Closed
@nrc

Description

@nrc

RFC #255 glossed over the issue of static methods. With the current implementation (plus rust-lang/rust#18527) we ignore static methods when deciding on object-safety (pre rust-lang/rust#18527, we ICE'ed). However, this does not allow us to use object-safety to guide the use of trait objects with traits (the 'auto-impl's for trait objects). E.g.,

trait T {
    fn foo();
}

fn bar<X: T>(x: Box<T>) {
    X::foo();
}

fn main() {
    let y: Box<T> = ...;
    bar(y);
}

Here, the call to bar should be disallowed because the call X::foo() cannot be resolved because foo is static.

I see three options:

  • Require no static methods in object-safe traits (this is restrictive, due to the constructor issue)
  • Check that traits are 'static-safe' when doing the 'auto-impl' trick when binding a type variable to a trait (this is slightly unfortunate since the object-safety principle was supposed to mean no extra checks here, and instead only restricting the traits which could be used as objects)
  • Abandon object-safety at object creation time and instead check object-safety and 'static-safety' when doing the 'auto-impl' (this would be a shame, I think object-safety is a good principle)

We could also relax the check on static methods where the method is provided rather than required, since there is then an implementation for a method when making a static method call. However, this would lose the usual, expected overriding behaviour (the provided method would always be called, even if the dynamic concrete type overrides it).

I think my favoured solution is option 1 with the provided method relaxation. I believe (though might be wrong here) that there is only benefit to having static constructor methods in a trait, rather than a concrete type, if there is a provided default method. So, the only cases which become inconvenient are where there is a provided constructor and this is overridden in a concrete type which is used to make an object.

See also discussion in rust-lang/rust#18527

cc @aturon @nikomatsakis

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions