Allow uncallable method impls to be omitted #1699
Note: This has implications beyond !. It would also allow one to write:
trait Foo {
fn foo(self) where Self: Sized;
}
impl<T> Foo for [T] {}Currently, this can't even be implemented. This is a bit ridiculous considering the fact that the following impl is fine (because T may be sized):
impl<T: ?Sized> Foo for T {
fn foo(self) where Self: Sized {}
}@Stebalien Interesting, I never thought of cases like that. I was really only thinking of cases where a method takes an uninhabited type.
@Stebalien's example seems orthogonal from the RFC to me. In @Stebalien's case, it would be a type error to call that method because a constraint was not met, whereas in the RFC the method is well typed, but will never execute.
@Stebalien's example seems like something that should be allowed, but like the previous RFC, I am not convinced that implementing traits for ! is a frequent enough activity that it deserves any special sugar or consideration.
@withoutboats it doesn't seem orthogonal to this RFC to me. This RFC states that if a method can't be called, then you don't have to implement it. The example in the RFC and @Stebalien's example are orthogonal reasons for a method being un-callable, but the end result is the same - can't be called => don't need to impl.
Or to be clear, the examples are different by the rules of the RFC, but not by the spirit.
@nrc In its motivation and detailed design, this RFC discusses methods which are uncallable because they take an uninhabited argument. I don't think we can consider an RFC which proposes any property for all "methods which can't be called," since that is not a clearly defined set of cases.
For example, here is another case where a method is uncallable. Does this RFC include this in its scope?
A dependency defines and exports this struct and trait:
struct Foo {
_secret: ()
}
trait Bar {
fn bar(&self, foo: Foo) -> Foo;
}
The library defines no public constructor for Foo, and contains no functions which take a T: Bar or a Bar trait object as arguments.
When I implement Bar for my own types, the method bar will never be called, because I cannot construct a Foo or pass my type to that library. Moreover, I cannot provide a definition which doesn't diverge, because I cannot construct a Foo.
This is an "uncallable method," should I be allowed not to write it? I don't think so (that opens a huge can of backcompat problems for libraries!), but more importantly, I don't think this is in scope for this RFC.
@withoutboats that's only uncallable in safe/sane code. However, I didn't read the detailed design so I simply assumed that the examples given in the motivation/summary were just that, examples.
Given that being able to simply implement my examples is orthogonal to being able to implement them without explicitly defining the uncallable methods, I've filed a separate issue rust-lang/rust#35369.
Also, there's a big drawback that hasn't been mentioned: a type can go from uninhabited to inhabited without changing any public type definition:
struct TBD(!);
trait MyTrait {
// For now, this always panics...
fn foo(&self) -> TBD;
}I don't really see how this could be useful outside of prototyping but it's still an issue.
@withoutboats that's only uncallable in safe/sane code.
True, you can construct a Foo through mem::uninitialized.
Also, there's a big drawback that hasn't been mentioned: a type can go from uninhabited to inhabited without changing any public type definition
Also true! I don't think we should make this a breaking change (and I don't think it should be visible to users who don't read the source that TBD is uninhabited).
Sorry, more context would have been good. =) rust-lang/rust#20021 was an issue opened with respect to where-clauses -- sometimes, in a specific impl, you can tell that a given fn will never be called because its where-clauses cannot be satisfied. This also comes up for trait objects.
Example:
trait Foo { fn bar() where Self: Copy; }
impl Foo for Box<i32> { fn bar() { panic!() } }Nobody could call x.bar() in the case where x: Box<i32>.
For your consideration.
Rendered