Reputation:
It seems that ?
and catch
have been accepted into Rust, but I am not able to use it properly:
let x = catch {
1
}
I think this should give me Ok(1)
. Instead, I get the error:
error: expected identifier, found `1`
--> src/main.rs:15:9
|
15 | 1
| ^
Is this syntax not yet supported in Rust, or is there a problem with my code?
Upvotes: 2
Views: 6616
Reputation: 299880
TL;DR: The RFC is accepted, but your syntax is slightly off (unfortunately) and the feature is still gated.
See Alec's excellent answer on how to actually use catch
.
I encourage you to read the full error log:
error: expected identifier, found `1` --> <anon>:2:21 | 2 | let x = catch { 1 }; | ^ error[E0422]: cannot find struct, variant or union type `catch` in this scope --> <anon>:2:13 | 2 | let x = catch { 1 }; | ^^^^^ not found in this scope error: aborting due to 2 previous errors
The clue is in the second error message:
cannot find struct, variant or union type
catch
in this scope
which really lets us know that catch
is not recognized as a keyword by the compiler.
Since catch
looks like any regular word, what happens is that the compiler attempts to parse this as building a struct
or enum
. Indeed, the syntax for building a struct
or enum
is:
struct X { name: i32 }
let x = X { name: 1 };
Therefore, the compiler sees <identifier> {
and expects it to be followed by a list of <identifier>: <expression>
. It reads 1
, which is not an identifier, and reports the error that 1
is not an identifier.
Upvotes: 5
Reputation: 32309
This is going to sound very dumb, because it kind of is. You need to have
#![feature(catch_expr)]
fn main() {
let x = do catch {
1
};
}
Basically, catch
, like default
and union
, cannot be made a keyword without breaking backwards compatibility. Since Rust has tried to guarantee that any code on 1.x will still work on 1.y, introducing default
, union
and now catch
into the grammar has been all about figuring out the conflicts. For union
and default
, there are none - identifiers are never expected in those positions.
For catch
, catch { 1 }
can also be interpreted as a struct literal. Unless you require do
(a reserved keyword) occur before catch
- then there is no ambiguity. Yes, this is ugly, and everyone knows it.
Hopefully these nightmares go away when 2.0 comes around and we can break backwards compatibility. Quoted from the rust-internals discussion around the grammar woes of catch
:
There's a growing list of other syntax we would ultimately like to repurpose in this way, but we generally avoid breaking the ability to run code that worked on 1.x on 1.y where y > x except in cases where the code was exploiting a compiler bug or was just a terrifically rare construction. Our stability guarantees demand we wait until 2.0 for most of these.
Upvotes: 7