-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tweaks to the object-safety rules #817
Tweaks to the object-safety rules #817
Conversation
an exemption that permits individual methods to require that `Self:Sized`.
The reason that this makes sense is that if one were writing a generic | ||
function with a type parameter `T` that may range over the trait | ||
object, that type parameter would have to be declared `?Sized`, and | ||
hence would not have access to the `bar` method: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be "the new
method"? Also on line 167.
Does this obsolete the need for an |
@alexcrichton I believe that is correct, yes. Ideally, though, we'd find a way for those methods to be usable on iterator objects as well! I guess the major problem is that they frequently take |
@aturon and I discussed this a little more today, and it looks like we won't actually want to remove the From what we talked about though, any consuming method no longer necessarily needs to live in an extension trait as they can all just be tagged with |
I’d rather like a built-in trait which is automatically implemented for all types except trait objects, allowing things like @alexcrichton On the topic of object safety rules, but slightly off-topic from the actual RFC, I’ve often wanted to tweak the ‘must not use |
I'm in favour. If we ever get type inequalities this would be "optimal" as |
I just pushed a slight adjustment that permits by-value self methods as well. The reasoning is two-fold:
In particular, this allows us to define I also included some text highlighting that there is room to make the rules more liberal in the future. |
(Note also that the question of |
How exactly could by-value If we ever do allow unsized by-value |
What about type parameters or associated types that default to |
@P1start The key here is a realization we had a while back about fn cycle(self) -> Cycle<Self> where Self: Clone This is a method that only needs to be implemented on The same principle is being applied here, with |
I was talking with @wycats and realized that the use of In particular, since Put differently, given the above, the only reason to have the object safety check is to force people to manually annotate with |
@aturon I understand the trait Foo {
fn foo(self);
} Trait impl Foo for Foo {
fn foo(self) { self.foo() } // error: the trait `core::marker::Sized` is not implemented for the type `Foo`
} So I don’t see how this could be considered object-safe. |
@P1start Ah, sorry! I think the point is that by-value self is interpreted as an implicit |
@aturon interesting thought. One downside is that, as @huonw has pointed out, |
(I guess @huonw's suggestion of |
@nikomatsakis Yes. @huonw and I chatted about this on IRC -- in my proposal, I don't literally mean interpreting as |
@aturon well, you have to be able to write it out, because we need to be able to use it as a bound on generic fns like |
(Or rather, we need them to not be callable if |
Basically I guess you can interpret the object safety rules as an additional way of ruling out that for |
So, to be clear, we'll want to eventually be able to write it out to take full advantage of the flexibility. But in the meantime, interpreting as something compiler-internal should be enough to (1) provide (But maybe I'm confused?) |
@aturon my point is that it cripples traits that do not need to be object safe. For example, if I wrote a trait trait MapToVec {
fn map_to_vec<U>(&self) -> Vec<U>;
}
impl<T> MapToVec for [T] { ... } and I wanted to use that trait: fn use_map_to_vec<T:MapToVec+?Sized>(t: &T) -> Vec<i32> {
t.map_to_vec::<i32>()
} The compiler would presumably have to disallow the call to That example is a bit odd in that I left out some type parameters and other things one would need to make it realistic, but doesn't seem especially far-fetched to me. |
I'd like to point out though that we can easily evolve object safety in the direction you propose, which I consider promising, though of course we won't be able to go back and fix traits in the meantime. |
@nikomatsakis Thanks, I understand the worry better now. But yes, I'm a little worried about precisely what we'll freeze into e.g. |
The conservative path seems to be keeping While I find the idea that all traits are object-safe very appealing, it's not clear to me how much that change would give us forwards compatibility. In particular, if we allows fns that use banned features to assume that "Self is not a trait object" (and hence use methods with other banned features), then if we expand the set of things that are possible to do with objects -- e.g., I'd like to include by-value self -- we're in a certain amount of trouble, since existing impls might be relying on that guarantee. But if we make them right it out specifically in the form of a where clause, then the trait is still locked into not support object type receivers when it could. On the other hand, I don't see how we could ever support generic methods through virtual dispatch, at least without dynamic code generation or some additional list (on the trait) of pre-defined types. So that's a fairly safe case where you can assume that |
Strictly speaking, it's possible to be relying on I think going with |
@aturon agreed. I'd also really like to move forward with this RFC because it allows motion on fn trait inheritance. |
Just FYI, impl is rust-lang/rust#22301 :) |
FWIW I'm happy to land this RFC for now and separately follow up on the more implicit design later. |
👍 I was able to do some nice cleanup of parts of rust-postgres using @nikomatsakis's branch: sfackler/rust-postgres@aa4cad7. |
This RFC makes it possible to have your cake and eat it too: we get |
…ods, r=huonw RFC 817 is not yet accepted, but I wanted to put this code up so people can see how it works. And to be ready lest it should be accepted. cc rust-lang/rfcs#817
Amend object safety RFC to include the complete set of rules, along with an exemption that permits individual methods to require that
Self:Sized
.Implemented on the following branch:
https://github.com/nikomatsakis/rust/tree/object-safe-sized-methods