-
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
RFC: Reserve try
for try { .. }
block expressions
#2388
Conversation
text/0000-try-expr.md
Outdated
- **Used as crate?** *No*, as above. | ||
- **Usage (sourcegraph):** **0** regex: N/A | ||
7. **Consistency with old learning material:** Untaught | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're missing an alternative here -- a completely new keyword. Could be result
. That has a higher chance of breakage but it's edition'd so maybe not an issue? I prefer catch over try but I strongly prefer something new over both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see trap, fallible, collect, capture, etc all being considered later in the RFC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've now added a review of the result
keyword below trap
.
In the current RFC text I see a dozen different keywords being evaluated against the same set of criteria, but there's just so much text that it would take a lot of careful rereads to get an overall feel for how that set of criteria judges all the various options, much less decide if the criteria are persuasive or not. Could we try organizing most of the comparative information in a table so that it's easier to see how all the options compare? |
I hear you ;) There's certainly a lot of text!
These are lifted mostly from the
Hmm... That would be helpful, but it's not very easy to do this in markdown; at least for me -- and it's quite a lot of busy work. A PR adding a table would be welcome though. I'll see if I have time to summarize it myself otherwise. |
I still like Also, nested catch makes sense to me because it has nested layers of "catching" errors, whereas nested "trying" doesn't really feel that way. I'd also like to point out that having Also⦠I'd like to point out that the trait being |
Also I think that the
which would by sugar for type ascription (which, would end up ascribing after the If we did this with This also lends very, very nicely to an |
My view is that this might work in isolation, but not if we consider the established meaning of
Allowing
We can change the name of the trait, but we should not imo. People already call
We can equally write: let first_two = try : Option<_> {
let (first, rest) = self.split_first()?;
let (second, rest) = rest.split_first()?;
(first, second, rest)
}; The colon makes it much more clear that this is type ascription at play, but in this case, writing: let first_two: Option<_> = try {
let (first, rest) = self.split_first()?;
let (second, rest) = rest.split_first()?;
(first, second, rest)
}; seems the simpler solution.
Equally possible as one of: try fn f(...) -> Result<T, E> { ... }
fn f(...) -> try Result<T, E> { ... }
fn f(...) -> Result<T, E> = try { ... } Here, my personal favorite is the last version ( |
IMO this is an argument against |
I'm in favor of
To expand on the first point, let me copy and paste some text from my post on the internals thread.
|
I think Being able to search for |
@clarcharr
This is actually a good point. I think we probably do want the ability to specify the type that will be caught -- in fact, I almost would go so far as to say we want to make it mandatory to specify that type. The problem is that if you don't specify it, and it winds up not being constrained from somewhere else, then you get errors because we don't know what to coerce I suppose In practice I usually write this today:
While I'm generally against reserving more than we need, maybe we should reserve both try/catch to be safe :) |
Let's keep it at almost ;) forcing people to always write out the type will make
Would that be semantically different than say |
Actually, given that ( |
With |
Thank you @Centril for responding so quickly! I definitely agree with your points and will probably respond more in-depth later when I'm not super tired. Regarding requiring a type for Regarding @scottmcm's comment on downcasting, I personally feel like encouraging downcasting at the language level is really not the best idea; I actually have a lot of more specific feelings about the |
Does it need to be part of the
and if we can't infer the type of a try block, the error message should explicitly suggest putting |
I would not do that for a few reasons:
@clarcharr
Continuing the side-discussion (purely because it is interesting), I would feel comfortable with some form of downcast-pattern-match if it was syntactically legible and also programmable: trait Downcast<Target> {
fn downcast(Self) -> Result<Target, Self>;
}
// Here be dragons, wild speculation ahead:
try { .. } catch {
downcast (e : io::Error) => { .. }
β (e : io::Error) => { .. } // darn it, why can't ASCII be nicer?
// or infix:
e β io::Error => { .. }
e downcast io::Error => { .. }
e _> io::Error => { .. } // underscore (down) arrow (cast)
} PS: Let's perhaps continue this speculation on internals?
To me it is more of a "can" than "need" proposition, in the sense that you might want type ascription as part of your super powered toolbox instead of typing judgements on the Tho the type ascription / not discussion seems somewhat orthogonal to the keyword discussion at hand ;) |
Honestly I don't see this as being very likely. I'm wary of changing decisions based on very-far-future concerns.
I don't think this is a big deal at all. It's as long as
We could go either way, and I'm fine with breaking precedent here, there's no pressing reason to that precedent. If "we haven't done it before" was an argument that could be made then Rust would never have happened πΊ ; in and of itself "we haven't done it before" doesn't help. |
Actually, thinking about it more, we could totally reserve both I still prefer |
That depends on what you mean by "very-far-future". For me, that is 10 years perhaps, but 2 years is not that far if you want a robust design that ages well.
I think it will see more use than
Breaking precedent should not be done lightheartedly but only if there are significant reasons to, and there are certainly very significant reasons for Rust's raison d'Γͺtre. But I don't think there are for breaking rank on
I think it is technically sufficient to only reserve |
IMO it's the opposite, if there is no reason for a precedent aside from happenstance we should not worry about breaking precedence. Otherwise any proposal is "breaking precedence". This is why I said "in and of itself" -- there's no actual reason we haven't had keywords like this before. One can argue that they're unwieldy/long, but that's already a point under discussion and talking about precedence doesn't bolster it. |
Mine was not an argument for "TRADITION!" (Fiddler on the roof). |
I don't see two-word keywords as "unfamiliar", really. Yes, you don't see them often, but you also don't see keywords starting with a q often (i.e. it's as unfamiliar/inconsistent as a keyword starting with a q would be -- superficially so but not in any meaningful way). Your comment above mentions "unfamiliar lexical syntax", so it seems you're addressing familiarity in a more general sense than just for the unfamiliarity of a two-word keyword. In that context:
You're right that it's still unfamiliar, but we basically have a tradeoff between familiarity false positives (people misunderstanding what try/catch mean because they expect something else) and unfamiliarity false negatives (people not understanding what trycatch is because it's clearly a new construct, even if the name strongly hints a meaning). The familiarity angle isn't a clear win for (IMO the false negatives will be less likely than the false positives, but that's me.) |
I don't like the idea of try being used to scope result returns. it seems me that it would definitely be easily confused with the "try" macro or nightly try trait in std lib. catch or do catch seems reasonable. the only real problem with catch is that it conflicts other languages usage of the word. it certainly doesn't interact the same way many exception based languages work |
Although I'm a fan of |
You shouldn't presume that we'll end up adding Personally I think it is unlikely given (at least that is my hypothesis) that |
I have to. It feels like a natural evolution. And it'll be bad if it goes your way. I would love the ability to use it with loops. Perhaps also |
@SoniEx2 you've been providing a lot of answers saying "Don't do this" without really good reasons as to why and making a lot of assumptions as to what would be added. I suggest that if you are going to make detracting statements that you should write out a fleshed out reason as to why not that addresses the arguments made for this feature, which is just reserving the key word. Not actually using it. That will require a whole separate RFC. |
Per @Centril's on April 10th:
If I understand the process correctly, reserving the keyword gives downstream consumers an opportunity to convert their code before the feature stabilizes. Only one keyword will be reserved, and unless a compelling alternative appears, that keyword is |
it increases language complexity. is that not a good reason? we could use labels and avoid the issue, but instead we do this, that's what I have an issue with. |
The final comment period, with a disposition to merge, as per the review above, is now complete. |
Huzzah! This RFC is now merged! Tracking issue: rust-lang/rust#50412 |
This comment has been minimized.
This comment has been minimized.
Rust 2018 removes the `try!()` macro and makes `try` a reserved keyword in accordance with RFC 2388: rust-lang/rfcs#2388. On the other hand, the `?` operator was introduced way back in Rust 1.13 and is now stable. Without the change, rustc will refuse to compile the generated code starting with the 2018 edition. While this project itself is free to use `try!()` and not switch to Rust 2018, its output files - preferably - should be compatible with both editions. rust-lang/rust#31436
Rust 2018 removes the `try!()` macro and makes `try` a reserved keyword in accordance with RFC 2388: rust-lang/rfcs#2388. On the other hand, the `?` operator was introduced way back in Rust 1.13 and is now stable. Without the change, rustc will refuse to compile the generated code starting with the 2018 edition. While this project itself is free to use `try!()` and not switch to Rust 2018, its output files - preferably - should be compatible with both editions. rust-lang/rust#31436
πΌοΈ Rendered
β Tracking issue
π Summary
This RFC reserves
try
as a keyword in edition 2018 for expressions of the formtry { .. }
.π Thanks
To @scottmcm, @Manishearth, for discussions and to everyone who participated in the internals thread