Skip to content

syntax: Parse field/method access after type ascription and cast expressions - #33380

Closed
petrochenkov wants to merge 1 commit into
rust-lang:masterfrom
petrochenkov:ascrdot
Closed

petrochenkov wants to merge 1 commit into
rust-lang:masterfrom
petrochenkov:ascrdot

Conversation

@petrochenkov

Copy link
Copy Markdown
Contributor

Addresses #23416 (comment) / rust-lang/rfcs#1539 (comment)

This patch allows type ascription (and cast expressions) to be followed by field/method access syntax.
Therefore it allows type ascription to be used in method chains like

let sv = v.iter().
           collect(): Vec<_>.
           into_sorted();

and also makes unsuffixed integer literals with type ascription almost as convenient as literal suffixes

let s = 10u8.to_string();
let s = 10: u8.to_string();

r? @nikomatsakis

@nikomatsakis

Copy link
Copy Markdown
Contributor

Hmm. This has implications for possible future extensions to the type grammar (. is largely out of bounds). I'd want @rust-lang/lang to weight in on this.

@nikomatsakis nikomatsakis added I-nominated T-lang Relevant to the language team labels May 3, 2016
@nikomatsakis

Copy link
Copy Markdown
Contributor

But I agree 10:u8.foo() is pretty (though 10_u8.foo() seems ok too).

@petrochenkov

Copy link
Copy Markdown
Contributor Author

To give some practical example, here's a commit converting lrs library to use type ascription: lrs-lang/lib@5dc95b6.
That commit would look much nicer if type ascription supported chaining.

@nikomatsakis

nikomatsakis commented May 6, 2016 •

Copy link
Copy Markdown
Contributor

We discussed this in the recent @rust-lang/lang meeting. We all agreed that the motivation here is pretty reasonable. In particular, this change enables the use of : in method chains:

vec.iter()
   .map()
   .collect(): Vec<_>
   .something()

which is a pretty clear improvement on the version with ():

(vec.iter()
    .map()
    .collect(): Vec<_>)
    .something()

@aturon has also harbored secret dreams of removing the need for "special purpose" converter methods. The commit you cited for example has a number of lines that convert calls to as_ref to use foo.as_ref(): &[u8]. We did some various comparisons of possibly syntaxes:

(self.as_ref():&[u8]).to_rmo_with(pool)
(self.as_ref(): &[u8]).to_rmo_with(pool) // current rustfmt output
self.as_ref():&[u8].to_rmo_with(pool)
self.as_ref::<[u8]>().to_rmo_with(pool)
self.as_ref<[u8]>().to_rmo_with(pool) // what we wanted, but can't get
self.as_bytes().to_rmo_with(pool)

Opinions were somewhat varied, but basically we didn't feel like any of the first three examples (using ascription) were really improvements over as_bytes. The existing self.as_ref::<[u8]>() is also generally considered unergonomic, of course, and sadly self.as_ref<[u8]>() introduces parsing ambiguities.

As another example, here are some calls with into:

(self.into():PathBuf).do_something()
self.into():PathBuf.do_something()
self.into::<PathBuf>().do_something()
self.into<PathBuf>().do_something() // what we wanted, but can't get yet
self.into_path_buf().do_something()
self.into(PathBuf).do_something() // magical

In general, we were very concerned that this syntax produces some things that are just plain conusing and hard to parse (for a human, that is). Example:

self.into():PathBuf.do_something()

On the other hand, not having this syntax really devalues type ascription, since it makes usage in method chains unergonomic.

In the end, we decided that we would rather not accept this PR. If you're really enthusiastically in favor of this syntax, we would of course consider an RFC, which would then get a broader set of feedback than this PR.

However, if we don't accept this PR, it does raise some questions as to whether type ascription carries its weight, given that using it with collect is kind of unergonomic in a method chain. There are still uses -- to be sure -- but they are fewer than before, and it introduces some confusion, since there is this overlap in purpose between : and as (also considered one of the features of type ascription, of course). However, @nrc felt strongly that we ought to wait until we have the full semantics of type ascription implemented before rendering a final judgement.

@petrochenkov

Copy link
Copy Markdown
Contributor Author

If you're really enthusiastically in favor of this syntax, we would of course consider an RFC

I do consider this a noticeable improvement, however this is a simple backward compatible change and it can be applied at any moment, so I'll just wait for the decision about type ascription in general.

@kriomant

Copy link
Copy Markdown

10: u8.to_string() is interpreted by me (not compiler) as calling .to_string() on variable named u8, and some strange 10: syntax before. While space before type is a good thing, here it doesn't agree with operation order.

@petrochenkov
petrochenkov deleted the ascrdot branch September 21, 2016 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-lang Relevant to the language team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants