Skip to content
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

Closed
wants to merge 1 commit into from

Conversation

nrc
Copy link
Member

@nrc nrc commented Mar 26, 2014

Allow bounds on formal type parameters in structs and enums (as well as traits and functions). Check all types for well-formedness.

Allow bounds on formal type parameters in structs and enums (as well as traits and functions). Check all types for well-formedness.
@flaper87
Copy link

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 T meets the bound B. The difference is that in the opt-in work, this will be done just for the built-in bounds, whereas in this proposal it'll be needed for all bounds.

This change deserves its own RFC but it could probably wait until the RFC 003 has been implemented.

@bill-myers
Copy link

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.

@huonw
Copy link
Member

huonw commented Mar 29, 2014

Doesn't work with default methods, which occasionally/often need to use the bounds on the parameters.

@nrc
Copy link
Member Author

nrc commented Mar 30, 2014

@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.

@nrc
Copy link
Member Author

nrc commented Mar 30, 2014

@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.

@bill-myers
Copy link

@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.

@nrc
Copy link
Member Author

nrc commented Mar 31, 2014

@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?

@nrc
Copy link
Member Author

nrc commented Apr 3, 2014

So I see three parts to this

  1. Add bounds to type variables on structs and enums and check these bounds against the impl's type variables;
  2. Typed well-formedness checks everywhere;
  3. Possibly remove bounds from traits.

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?

@nikomatsakis
Copy link
Contributor

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.

@huonw
Copy link
Member

huonw commented Apr 3, 2014

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.

@nrc
Copy link
Member Author

nrc commented Apr 5, 2014

@flaper87 I filed issue #34 for that change

@lilyball
Copy link
Contributor

lilyball commented Apr 5, 2014

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 ::new() to construct it.


As for default_impl I'm on the fence. I can see the potential benefit for being able to separate the requirements for implementing the trait from the requirements for getting default method implementations. But I'm afraid that it might be more confusing than it's worth. Having a brand new way of expressing an impl block that only exists for traits (and not other types) is weird. And it's more than just syntax. With @huonw's default_impl for Self: Add<T, Self> I'm worried that this will feel like all types that implement Add<T, Self> will automatically get the default trait implementation without having to explicitly impl the trait. Except that's not the case. I'm also worried that being able to use default methods in some impls of a trait and not in other impls of the same trait would be confusing and hard to produce good errors for that indicate why the default impl isn't available.

@nrc
Copy link
Member Author

nrc commented Apr 5, 2014

@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.

@nrc
Copy link
Member Author

nrc commented Apr 23, 2014

I'm going to merge this RFC with #34 as discussed at today's meeting

@nrc nrc closed this Apr 23, 2014
@nrc nrc deleted the struct-bounds branch April 23, 2014 01:45
wycats pushed a commit to wycats/rust-rfcs that referenced this pull request Mar 5, 2019
Add Ember issue to 0001-improved-cp-syntax.md
traviscross pushed a commit that referenced this pull request May 6, 2024
Substantial rewrites based on discussions at Rust lang meetings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants