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

Dynamically sized type parameter syntax #357

Closed
ftxqxd opened this issue Oct 7, 2014 · 6 comments
Closed

Dynamically sized type parameter syntax #357

ftxqxd opened this issue Oct 7, 2014 · 6 comments

Comments

@ftxqxd
Copy link
Contributor

ftxqxd commented Oct 7, 2014

The current syntax for denoting a dynamically-sized type parameter is Sized? T. This acts as a way of removing the implicit Sized bound that all type parameters have by default. This has the nice advantage of being open to adding other default trait bounds in the future with a similar syntax for opting out. (Drop could be one: uninitialised pointers are not able to be dropped, but everything else is.) However, to me it seems inconsistent with the syntax for normal bounds, which come after the type parameter name. It also can’t be used in a where clause, unlike everything else applied to type parameters. Because DST never went through a proper RFC, and the syntax for DSTs has changed twice, it would be nice if we could get some proper feedback on want the syntax should actually be. I personally prefer T: Sized?, but perhaps other people will have other ideas.

For the record, here are the different syntaxes we’ve gone through:

  • unsized T: the original, obvious syntax
  • type T: there was a blog post on this
    • Motivation: Sized ∪ Unsized = All types
  • Sized? T: the current syntax
    • Motivation: Makes the implicit Sized bound normally present in all type parameters optional
@reem
Copy link

reem commented Oct 7, 2014

I agree and would really like to see a proper DST RFC surface and be discussed by the community so we can iron-out kinks like this one and have an official "source of truth" for what DST is, why it's being added to Rust, and what the exact features it brings are.

This is just one small issue that could be clarified with a real RFC.

@nrc
Copy link
Member

nrc commented Oct 7, 2014

To give a bit of background on the naming, we need a name which means 'maybe sized' rather than 'unsized', since we are relaxing the 'Sized' bound rather than asserting the type is definitely not sized. Thus type (as opposed to just sized types), but of course that is kind of vague. It is better (probably) to actually involve the trait Sized. The reason it comes before the type is partly historical (the other keywords do) and partly to separate it from normal bounds. If you imagine multiple bounds, some opting in, some out, then a type would look like Foo+Bar? T: Baz+Qux (of course for now the only bound you can opt out of is Sized). If the opt-out bounds were also after the variable it would be easier to confuse the two kinds of bounds.

OTOH, no-one is really happy with the Sized? syntax, having a bound before the parameter is pretty weird. We also end up wanting this un-bound more often than we thought we would, so perhaps the defaults here are not great (requiring T: Sized all over the place is not much fun either though) or perhaps we want some kind of lightweight syntax.

@pnkfelix
Copy link
Member

pnkfelix commented Oct 7, 2014

I agree that it would be good to have some syntax that works with where clauses.


Regarding the positioning of the tokens here: My recollection was that there was one particularly good reason for a generalization marker like Sized? to not be mixed in with the bounds: it is not just the fact that it is not a bound; It is the dual of a bound. Everything is backward, and the best way I can think of to emphasize that is to put it in the opposite location of where bounds go.

A concrete example:

trait T<X: Bound> : S<X>
trait U<Y> : R<Y>
trait V<Sized? Y> : R<Y>

In the case of T and S, you get to assume that X is constrained by Bound, including when you feed X into the trait definition for S; so there is information flow from the definition of T into the use of S. S may or may not require Bound of X.

In the case of V and R, you now lose an assumption about Y. You are not feeding new bounds on Y into its use in R<Y>. Since Y may or may not be Sized, R must itself be able to handle either case (as illustrated by its use with the trait U), and thus must be defined via trait R<Sized? W> { ... }.

These are complete opposites in terms of the reasoning involved.


A statement like "having a bound (sic) before the parameter is pretty weird" just re-enforces this point to me: These are weird. A weird syntax is appropriate. You should have to think a little harder when encountering it.

@huonw
Copy link
Member

huonw commented Oct 7, 2014

Considering the where-clause issue, is there an obvious (or non-obvious) problem with where Sized? T?

@reem
Copy link

reem commented Oct 9, 2014

@pnkfelix This is all the more reason to have an RFC. You've expressed a strong and intelligent design rationale for the way things are, just the sort of thing that should go in an RFC.

The design rationale for DST was never really covered anywhere, and I know I'm not alone in just being lost at trying to understand how DST works, why we have it, what problems it solves, why it looks this way, how do I use it, &c. An RFC would really help inform the community about all of these things.

@nikomatsakis
Copy link
Contributor

I think this is basically settled now. Closing.

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

No branches or pull requests

6 participants