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

Tracking issue for RFC 803, "Type ascription" #23416

Open
nikomatsakis opened this issue Mar 16, 2015 · 59 comments
Open

Tracking issue for RFC 803, "Type ascription" #23416

nikomatsakis opened this issue Mar 16, 2015 · 59 comments

Comments

@nikomatsakis
Copy link
Contributor

@nikomatsakis nikomatsakis commented Mar 16, 2015

Tracking issue for rust-lang/rfcs#803. Important points:

  • Implement the expr:Type syntax
  • Ensure soundness with respect to ref positions:
    • let ref x = <expr> / let mut ref = <expr>
    • match <expr>: Type { ref x => ... }
    • (<expr>: Type).method_with_ref_self()
  • Permit coercions like &[1, 2, 3]: &[u8] -- #78248
@alexcrichton alexcrichton added the T-lang label Aug 11, 2015
bors added a commit that referenced this issue Dec 19, 2015
This PR is a rebase of the original PR by @eddyb #21836 with some unrebasable parts manually reapplied, feature gate added + type equality restriction added as described below.

This implementation is partial because the type equality restriction is applied to all type ascription expressions and not only those in lvalue contexts. Thus, all difficulties with detection of these contexts and translation of coercions having effect in runtime are avoided.
So, you can't write things with coercions like `let slice = &[1, 2, 3]: &[u8];`. It obviously makes type ascription less useful than it should be, but it's still much more useful than not having type ascription at all.
In particular, things like `let v = something.iter().collect(): Vec<_>;` and `let u = t.into(): U;` work as expected and I'm pretty happy with these improvements alone.

Part of #23416
@petrochenkov
Copy link
Contributor

@petrochenkov petrochenkov commented Dec 22, 2015

There's one thing making type ascription less convenient than it could potentially be. While it has the same operator priority as as (it is modeled after as in general), i.e. the highest from binary operators, it's still lower than member access . (dot).

Compare these two expressions

let v = v.iter().collect::<Vec<_>>().sort(); // Parens are not required
let v = (v.iter().collect(): Vec<_>).sort(); // Parens are required
// Formatted on several lines
let v = (v.iter().
           collect(): Vec<_>). // Looks bad, man
           sort();

I'm not sure if it is worth fixing or if it can be fixed without hacks, but it is worth discussing at least.

@hoodie
Copy link
Contributor

@hoodie hoodie commented Dec 22, 2015

BTW: This has is a breaking change for crates that implement a similar macro syntax already, such as prettytables.

@jonas-schievink
Copy link
Member

@jonas-schievink jonas-schievink commented Dec 22, 2015

@hoodie I opened #30531, since this seems worth tracking

@nrc
Copy link
Member

@nrc nrc commented Jan 5, 2016

cc @nrc

@vi
Copy link
Contributor

@vi vi commented Mar 21, 2016

Is it a good idea to only do ascription inside parentheses, so let a = x : T is not ascription yet, but let a = (x : T) is? This can allow more room for some further syntax additions.

@petrochenkov
Copy link
Contributor

@petrochenkov petrochenkov commented May 6, 2016

For the record: a patch implementing support for method chaining with type ascription #33380

@ottworks
Copy link

@ottworks ottworks commented Jul 3, 2016

Why is this in the book if it won't compile? (1.9.0)

https://doc.rust-lang.org/book/closures.html

@hoodie
Copy link
Contributor

@hoodie hoodie commented Jul 3, 2016

@0TT what exactly?

@retep998
Copy link
Member

@retep998 retep998 commented Jul 3, 2016

@0TT Type ascription is specifically when adding a : T type annotation after an expression. Not in the parameters to a closure or a function, and not on a variable binding. Only when it follows an expression which I do not see any cases of on the page you linked.

@ottworks
Copy link

@ottworks ottworks commented Jul 3, 2016

Oops. I accidentally typo'd a semicolon as a colon:

let plus_two = |x| {
    let mut result: i32 = x;

    result += 1:
    result += 1;

    result
};
assert_eq!(4, plus_two(2));
@hoodie
Copy link
Contributor

@hoodie hoodie commented Jul 3, 2016

that happens, how about an RFC to replace all semicolons with a less confusable character?

let plus_two = |x| {
    let mut result: i32 = x✓

    result += 1✓
    result += 1✓

    result
}✓
assert_eq!(4, plus_two(2))✓

makes the language even look safer, everything is checked after all 😀

@ottworks
Copy link

@ottworks ottworks commented Jul 3, 2016

Should use emoji tbh. A language for the future.

@nrc
Copy link
Member

@nrc nrc commented Aug 17, 2016

re the soundness question in the OP, this comment is probably the best summary.

@crumblingstatue
Copy link
Contributor

@crumblingstatue crumblingstatue commented Dec 7, 2016

Before stabilizing this feature, I would like to see how this potentially impacts optional and named arguments, namely the expr : type syntax in function call argument position.

Could named arguments use this syntax if it wasn't for type ascription?

If yes, and no other syntaxes could be devised that are as optimal as name : type, I'd strongly recommend changing the syntax for type ascription, in favor of allowing the optimal syntax for named arguments.

I believe named arguments would be much more widely used than type ascription, and the syntax optimization for ergonomics should go there instead.

Ref rust-lang/rfcs#323

@sunchao sunchao mentioned this issue May 11, 2018
1 of 5 tasks complete
@Centril
Copy link
Contributor

@Centril Centril commented May 26, 2018

I think @scottmcm's plan sounds good. Repeating what I said on #rust-lang: I can live with the problem of not having 100% consistency personally. Some inconsistency is to me better than not having the feature at all. Unfortunately, with the current language and our backwards compatibility promises, we can't achieve 100% consistency with typing judgements in the language across the board and I'm not advocating that we write:

let foo as type = expr;

That said, I think the idea due to @cramertj to have some sort of expr.type!(MyType) or say expr.as!(MyType) or even expr.at!(MyType) (read as: "expr is typed at MyType") is interesting. With postfix macros as in rust-lang/rfcs#2442 you could build that.

An example:

let vec = iter.map(..).filter(..).collect().at!(Vec<u32>);

The benefit of post macros here is that it allows chaining... however, I think it is unlikely to have many type ascriptions per expression.

zackmdavis added a commit to zackmdavis/rust that referenced this issue Jun 24, 2018
The top level message shouldn't be too long; the
replaced-by-coercion/temporary-variable advice can live in a note. Also,
don't mention type ascription when it's not actually available as a real
thing. (The current state of discussion on the type ascription tracking
issue rust-lang#23416 makes one rather suspect it will never be a stable thing in
its current form, but that's not for us to adjudicate in this commit.)
zackmdavis added a commit to zackmdavis/rust that referenced this issue Jun 24, 2018
The top level message shouldn't be too long; the
replaced-by-coercion/temporary-variable advice can live in a note. Also,
don't mention type ascription when it's not actually available as a real
thing. (The current state of discussion on the type ascription tracking
issue rust-lang#23416 makes one rather suspect it will never be a stable thing in
its current form, but that's not for us to adjudicate in this commit.)
zackmdavis added a commit to zackmdavis/rust that referenced this issue Jun 24, 2018
The top level message shouldn't be too long; the
replaced-by-coercion/temporary-variable advice can live in a note. Also,
don't mention type ascription when it's not actually available as a real
thing. (The current state of discussion on the type ascription tracking
issue rust-lang#23416 makes one rather suspect it will never be a stable thing in
its current form, but that's not for us to adjudicate in this commit.)

While we're here, yank out the differentiating parts of the
numeric/other conditional and only have one codepath emitting the
diagnostic.
@Ichoran
Copy link

@Ichoran Ichoran commented Jul 12, 2018

As a long-time user of Scala, I have only very rarely seen anyone confuse : Foo with .asInstanceOf[Foo]. Granted, as Foo is less different syntactically, but I still think it is very important for correctness to be able to distinguish between telling the compiler "I believe this type to be that, but check it for me" and "I want you to make this type be that if you can". That is, I want some way to avoid coercion, because coercion may be the wrong thing to do.

(Numeric types in Scala have a notion of "weak conformance" which means they can get coerced unexpectedly; this has turned into a a fruitful source of puzzlers. Rust has much less of an issue presently, but dropping the distinction between pure ascription and request for coercion is likely to erode the improvement. It would be especially pernicious if the very thing you would use to check your assumptions could break them instead!)

@mikhail-krainik
Copy link

@mikhail-krainik mikhail-krainik commented Mar 19, 2019

@nikomatsakis could we improve error message in this case

proto::Status:ok()

I got

error[E0658]: type ascription is experimental (see issue #23416)
  --> src/main.rs:6:26
   |
76 |             status: Some(proto::Status:ok())
   |                          ^^^^^^^^^^^^^^^^^^
   |
   = help: add #![feature(type_ascription)] to the crate attributes to enable

According this RFC type ascription should contain : and space between words. But it's spreading on typo mistake with ::

@Centril
Copy link
Contributor

@Centril Centril commented Mar 19, 2019

cc @estebank ^-- We discussed this at the all hands on a night out... the idea, if you remember, was that you check for this pattern when the LHS of : is valid under <LHS> and RHS is not an existing type.

@estebank
Copy link
Contributor

@estebank estebank commented Mar 19, 2019

@Centril I remember. I made #59150 with a different approach, more hacky but one that would have given the right error above.

@Centril
Copy link
Contributor

@Centril Centril commented Mar 19, 2019

@estebank Oh haha; I even reviewed that one... 😅

@Centril Centril changed the title Type ascription (tracking issue for RFC 803) Tracking issue for RFC 803, "Type ascription" May 3, 2019
@estebank
Copy link
Contributor

@estebank estebank commented Jul 20, 2019

@Centril #62791 and #62816 should cover all of the (common) type ascription typos (: -> ;, foo(x: bar), foo:bar::baz(1), etc.). With that I believe that "diagnostics being terrible" is no longer a valid reason not to continue with the current syntax.

@pksunkara
Copy link

@pksunkara pksunkara commented Feb 1, 2020

What are the things that needs to be done to make this stable?

@Centril
Copy link
Contributor

@Centril Centril commented Feb 2, 2020

It's stuck on finding consensus in rust-lang/rfcs#2522 plus making the necessary changes (+ writing a lot of tests for them) outlined here and there.

@ethindp

This comment has been hidden.

@charmander

This comment has been hidden.

@ethindp
Copy link

@ethindp ethindp commented Aug 16, 2020

@ijackson
Copy link
Contributor

@ijackson ijackson commented Nov 2, 2020

It's stuck on finding consensus in rust-lang/rfcs#2522 plus making the necessary changes (+ writing a lot of tests for them) outlined here and there.

RFC 2522 has been postponed. I think that means we should consider whether to stabilise type ascription for expressions as currently implemented. Looking through this issue I found only the following outstanding concerns/objections:

  • Is the precedence right? #23416 (comment)
  • interaction with the idea of optional/named arguments (which might also use :)

There was also the soundness question summarised here rust-lang/rfcs#803 (comment) . But I think having read #78248 that in fact this soundness issue does not arise because we do not support coercion in type ascription. Supporting coercion might be nice but I don't think it should be a blocker for stablising this feature.

@nikomatsakis
Copy link
Contributor Author

@nikomatsakis nikomatsakis commented Nov 6, 2020

I opened #78248 which describes how (I think...) we can support coercions in a relatively straightforward way. I do think that coercions are an important part of this feature. However, there are some other concerns about the syntax that have been raised. Last time I checked we definitely did not have full consensus on going forward here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.