-
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
Allow bounds on all type parameters. #20
Conversation
Allow bounds on formal type parameters in structs and enums (as well as traits and functions). Check all types for well-formedness.
I'm not opposed to this change. That said, a good part of what would be needed to implement this RFC will be done as part of the work in opt-in kinds. That is, a subroutine that checks whether a type This change deserves its own RFC but it could probably wait until the RFC 003 has been implemented. |
Perhaps we should instead remove bounds on generic parameters to traits. These seem a design mistake, since they should be put on the trait impls instead. |
Doesn't work with default methods, which occasionally/often need to use the bounds on the parameters. |
@flaper87 Yeah, after submitting this RFC, I then discovered that we don't check bounds even where we can. I would very much like to do that, but I worry I am missing some understanding of why we chose that approach in the first place. In any case, I think this RFC is a prerequisite to doing that. And yes, we should have another RFC for that and it should probably wait till you are done with RFC 3. |
@bill-myers Could you expand on why you think it is a design mistake please? My position (atm) is that any formal type parameter should (be allowed to) have bounds and any actual type parameter should be checked against the corresponding formal's bounds. I don't see why that should be relaxed for either structs or traits. |
@huonw That's an interesting point, but I think it actually means that default methods are also wrong in this world view. A simple fix is to remove them from the trait declaration and put them in a "default impl", where a type bound can be added just like a normal impl. @nick29581 Well, it's clear that the current design is broken, and that it needs to be fixed either as this RFC suggest, or by removing bounds on traits and moving out default methods. The logic of not having bounds on struct generic types is that it nicely separates data and traits and avoids having them on both structs and impls (on impls they are needed anyway, or expressiveness is lost). The logic of having them is that it avoids having to repeat the bound everywhere, for bounds that will always be present on impls; also, if associated types are added, then you can have them bounded more easily. Overall I think this RFC might be a good idea, but the reason should not really be "to fix trait bounds checking" (which can be done otherwise), but rather because we want to have bounds on structs and traits and not just impls. |
@bill-myers I think I like the suggestion that default methods should be in an impl. That would require us to have impls for just a trait, which we don't have at the moment, right? I'm also not convinced that this means we don't need bounds for type variables used by method declarations - not for better checking, but to better indicate programmer intent. Not sure about that though. It is not clear to me that the current design is broken and I write this RFC :-p I think it could be better certainly, but I don't think I agree that it is broken, as such. I also don't see how not having bounds on structs leads to separation of data from traits (behaviour). Wouldn't adding them would mean more repetition not less? Or are you thinking we wouldn't need them then on impls? |
So I see three parts to this
2 probably deserves its own RFC, 3 can be follow up work and also deserves its own RFC. Does anyone object to (or have thoughts about) 1? |
I'm in favor of permitting bounds in more places. At minimum, let's permit builtin bounds and check them when instances are created. I'd like to work on improving trait process (working on prototype impl I plan to describe in an RFC very soon) in the near term, I can incorporate some of this there as well. |
Being able to separate the default impl from the trait would allow writing something like trait AddAssign<RHS> {
fn add_assign(&mut self, val: RHS);
}
default_impl<T> AddAssign<T, Self> for Self: Add<T, Self> {
fn add_assign(&mut self, val: T) {
*self = *self + val
}
}
trait Clone {
fn clone(&self) -> Self;
}
default_impl Clone for Self: Copy {
fn clone(&self) -> Self { *self }
} i.e. not require a super trait, but provide a helper method in the case when there is a sensible trait that can be used in the implementation. |
What practical benefit do we get for allowing bounds on type parameters in struct definitions? My initial reaction was in favor of this change, but it doesn't actually remove the need to specify bounds elsewhere. struct Foo<T: Copy> { x: T }
impl<T> Foo<T> {}
// ^ error because T is under-constrained
// still need to say impl<T: Copy> The only thing this does is preventing someone from using a type in such a way that it has no methods or traits, and if you really care about that, just give the type a private field and require the use of As for |
@kballard as you note, I don't think we disallow any more programs. I think the advantage is clearer type rules and simpler type checking. Also better signalling of programmer intent and hopefully even better error messages because we throw an error closer to where the problem comes from. I'd be keen to more discussion of removing bounds in traits and default_impl, etc. to another RFC - it is facilitated by this one, but otherwise unrelated. |
I'm going to merge this RFC with #34 as discussed at today's meeting |
Add Ember issue to 0001-improved-cp-syntax.md
Substantial rewrites based on discussions at Rust lang meetings.
Allow bounds on formal type parameters in structs and enums (as well as traits and functions). Check all types for well-formedness.