Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d95c5437
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d95c5437
编写于
2月 17, 2017
作者:
T
Taylor Cramer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add catch expr to AST and disallow catch as a struct name
上级
1b19284a
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
196 addition
and
5 deletion
+196
-5
src/librustc/hir/lowering.rs
src/librustc/hir/lowering.rs
+33
-4
src/libsyntax/ast.rs
src/libsyntax/ast.rs
+2
-0
src/libsyntax/feature_gate.rs
src/libsyntax/feature_gate.rs
+6
-0
src/libsyntax/fold.rs
src/libsyntax/fold.rs
+1
-0
src/libsyntax/parse/parser.rs
src/libsyntax/parse/parser.rs
+35
-0
src/libsyntax/print/pprust.rs
src/libsyntax/print/pprust.rs
+5
-0
src/libsyntax/symbol.rs
src/libsyntax/symbol.rs
+2
-1
src/libsyntax/visit.rs
src/libsyntax/visit.rs
+3
-0
src/test/compile-fail/catch-empty-struct-name.rs
src/test/compile-fail/catch-empty-struct-name.rs
+15
-0
src/test/compile-fail/catch-enum-variant.rs
src/test/compile-fail/catch-enum-variant.rs
+17
-0
src/test/compile-fail/catch-struct-name.rs
src/test/compile-fail/catch-struct-name.rs
+15
-0
src/test/compile-fail/catch-tuple-struct-name.rs
src/test/compile-fail/catch-tuple-struct-name.rs
+15
-0
src/test/compile-fail/feature-gate-catch_expr.rs
src/test/compile-fail/feature-gate-catch_expr.rs
+17
-0
src/test/run-pass/catch-expr.rs
src/test/run-pass/catch-expr.rs
+30
-0
未找到文件。
src/librustc/hir/lowering.rs
浏览文件 @
d95c5437
...
...
@@ -84,6 +84,7 @@ pub struct LoweringContext<'a> {
trait_impls
:
BTreeMap
<
DefId
,
Vec
<
NodeId
>>
,
trait_default_impl
:
BTreeMap
<
DefId
,
NodeId
>
,
catch_scopes
:
Vec
<
NodeId
>
,
loop_scopes
:
Vec
<
NodeId
>
,
is_in_loop_condition
:
bool
,
...
...
@@ -123,6 +124,7 @@ pub fn lower_crate(sess: &Session,
trait_impls
:
BTreeMap
::
new
(),
trait_default_impl
:
BTreeMap
::
new
(),
exported_macros
:
Vec
::
new
(),
catch_scopes
:
Vec
::
new
(),
loop_scopes
:
Vec
::
new
(),
is_in_loop_condition
:
false
,
type_def_lifetime_params
:
DefIdMap
(),
...
...
@@ -261,6 +263,21 @@ fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span
span
}
fn
with_catch_scope
<
T
,
F
>
(
&
mut
self
,
catch_id
:
NodeId
,
f
:
F
)
->
T
where
F
:
FnOnce
(
&
mut
LoweringContext
)
->
T
{
let
len
=
self
.catch_scopes
.len
();
self
.catch_scopes
.push
(
catch_id
);
let
result
=
f
(
self
);
assert_eq!
(
len
+
1
,
self
.catch_scopes
.len
(),
"catch scopes should be added and removed in stack order"
);
self
.catch_scopes
.pop
()
.unwrap
();
result
}
fn
with_loop_scope
<
T
,
F
>
(
&
mut
self
,
loop_id
:
NodeId
,
f
:
F
)
->
T
where
F
:
FnOnce
(
&
mut
LoweringContext
)
->
T
{
...
...
@@ -295,15 +312,17 @@ fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
result
}
fn
with_new_
loop_
scopes
<
T
,
F
>
(
&
mut
self
,
f
:
F
)
->
T
fn
with_new_scopes
<
T
,
F
>
(
&
mut
self
,
f
:
F
)
->
T
where
F
:
FnOnce
(
&
mut
LoweringContext
)
->
T
{
let
was_in_loop_condition
=
self
.is_in_loop_condition
;
self
.is_in_loop_condition
=
false
;
let
catch_scopes
=
mem
::
replace
(
&
mut
self
.catch_scopes
,
Vec
::
new
());
let
loop_scopes
=
mem
::
replace
(
&
mut
self
.loop_scopes
,
Vec
::
new
());
let
result
=
f
(
self
);
mem
::
replace
(
&
mut
self
.loop_scopes
,
loop_scopes
);
self
.catch_scopes
=
catch_scopes
;
self
.loop_scopes
=
loop_scopes
;
self
.is_in_loop_condition
=
was_in_loop_condition
;
...
...
@@ -1065,7 +1084,7 @@ fn lower_item_kind(&mut self,
self
.record_body
(
value
,
None
))
}
ItemKind
::
Fn
(
ref
decl
,
unsafety
,
constness
,
abi
,
ref
generics
,
ref
body
)
=>
{
self
.with_new_
loop_
scopes
(|
this
|
{
self
.with_new_scopes
(|
this
|
{
let
body
=
this
.lower_block
(
body
);
let
body
=
this
.expr_block
(
body
,
ThinVec
::
new
());
let
body_id
=
this
.record_body
(
body
,
Some
(
decl
));
...
...
@@ -1665,13 +1684,17 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
this
.lower_opt_sp_ident
(
opt_ident
),
hir
::
LoopSource
::
Loop
))
}
ExprKind
::
Catch
(
ref
body
)
=>
{
// FIXME(cramertj): Add catch to HIR
self
.with_catch_scope
(
e
.id
,
|
this
|
hir
::
ExprBlock
(
this
.lower_block
(
body
)))
}
ExprKind
::
Match
(
ref
expr
,
ref
arms
)
=>
{
hir
::
ExprMatch
(
P
(
self
.lower_expr
(
expr
)),
arms
.iter
()
.map
(|
x
|
self
.lower_arm
(
x
))
.collect
(),
hir
::
MatchSource
::
Normal
)
}
ExprKind
::
Closure
(
capture_clause
,
ref
decl
,
ref
body
,
fn_decl_span
)
=>
{
self
.with_new_
loop_
scopes
(|
this
|
{
self
.with_new_scopes
(|
this
|
{
this
.with_parent_def
(
e
.id
,
|
this
|
{
let
expr
=
this
.lower_expr
(
body
);
hir
::
ExprClosure
(
this
.lower_capture_clause
(
capture_clause
),
...
...
@@ -2069,6 +2092,12 @@ fn make_struct(this: &mut LoweringContext,
// Err(err) => #[allow(unreachable_code)]
// return Carrier::from_error(From::from(err)),
// }
// FIXME(cramertj): implement breaking to catch
if
!
self
.catch_scopes
.is_empty
()
{
bug!
(
"`?` in catch scopes is unimplemented"
)
}
let
unstable_span
=
self
.allow_internal_unstable
(
"?"
,
e
.span
);
// Carrier::translate(<expr>)
...
...
src/libsyntax/ast.rs
浏览文件 @
d95c5437
...
...
@@ -935,6 +935,8 @@ pub enum ExprKind {
Closure
(
CaptureBy
,
P
<
FnDecl
>
,
P
<
Expr
>
,
Span
),
/// A block (`{ ... }`)
Block
(
P
<
Block
>
),
/// A catch block (`catch { ... }`)
Catch
(
P
<
Block
>
),
/// An assignment (`a = foo()`)
Assign
(
P
<
Expr
>
,
P
<
Expr
>
),
...
...
src/libsyntax/feature_gate.rs
浏览文件 @
d95c5437
...
...
@@ -339,6 +339,9 @@ pub fn new() -> Features {
// `extern "x86-interrupt" fn()`
(
active
,
abi_x86_interrupt
,
"1.17.0"
,
Some
(
40180
)),
// Allows the `catch {...}` expression
(
active
,
catch_expr
,
"1.17.0"
,
Some
(
31436
)),
);
declare_features!
(
...
...
@@ -1287,6 +1290,9 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
}
}
}
ast
::
ExprKind
::
Catch
(
_
)
=>
{
gate_feature_post!
(
&
self
,
catch_expr
,
e
.span
,
"`catch` expression is experimental"
);
}
_
=>
{}
}
visit
::
walk_expr
(
self
,
e
);
...
...
src/libsyntax/fold.rs
浏览文件 @
d95c5437
...
...
@@ -1268,6 +1268,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
};
}
ExprKind
::
Try
(
ex
)
=>
ExprKind
::
Try
(
folder
.fold_expr
(
ex
)),
ExprKind
::
Catch
(
body
)
=>
ExprKind
::
Catch
(
folder
.fold_block
(
body
)),
},
id
:
folder
.new_id
(
id
),
span
:
folder
.new_span
(
span
),
...
...
src/libsyntax/parse/parser.rs
浏览文件 @
d95c5437
...
...
@@ -602,6 +602,12 @@ pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
}
}
pub
fn
error_if_typename_is_catch
(
&
mut
self
,
ident
:
ast
::
Ident
)
{
if
ident
.name
==
keywords
::
Catch
.name
()
{
self
.span_err
(
self
.span
,
"cannot use `catch` as the name of a type"
);
}
}
/// Check if the next token is `tok`, and return `true` if so.
///
/// This method will automatically add `tok` to `expected_tokens` if `tok` is not
...
...
@@ -2273,6 +2279,11 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
BlockCheckMode
::
Unsafe
(
ast
::
UserProvided
),
attrs
);
}
if
self
.is_catch_expr
()
{
assert
!
(
self
.eat_keyword
(
keywords
::
Catch
));
let
lo
=
self
.prev_span.lo
;
return
self
.parse_catch_expr
(
lo
,
attrs
);
}
if
self
.eat_keyword
(
keywords
::
Return
)
{
if
self
.token
.can_begin_expr
()
{
let
e
=
self
.parse_expr
()
?
;
...
...
@@ -3092,6 +3103,16 @@ pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
Ok
(
self
.mk_expr
(
span_lo
,
hi
,
ExprKind
::
Loop
(
body
,
opt_ident
),
attrs
))
}
/// Parse a `catch {...}` expression (`catch` token already eaten)
pub
fn
parse_catch_expr
(
&
mut
self
,
span_lo
:
BytePos
,
mut
attrs
:
ThinVec
<
Attribute
>
)
->
PResult
<
'a
,
P
<
Expr
>>
{
let
(
iattrs
,
body
)
=
self
.parse_inner_attrs_and_block
()
?
;
attrs
.extend
(
iattrs
);
let
hi
=
body
.span.hi
;
Ok
(
self
.mk_expr
(
span_lo
,
hi
,
ExprKind
::
Catch
(
body
),
attrs
))
}
// `match` token already eaten
fn
parse_match_expr
(
&
mut
self
,
mut
attrs
:
ThinVec
<
Attribute
>
)
->
PResult
<
'a
,
P
<
Expr
>>
{
let
match_span
=
self
.prev_span
;
...
...
@@ -3699,6 +3720,14 @@ fn parse_stmt_(&mut self, macro_legacy_warnings: bool) -> Option<Stmt> {
})
}
fn
is_catch_expr
(
&
mut
self
)
->
bool
{
self
.token
.is_keyword
(
keywords
::
Catch
)
&&
self
.look_ahead
(
1
,
|
t
|
*
t
==
token
::
OpenDelim
(
token
::
Brace
))
&&
// prevent `while catch {} {}`, `if catch {} {} else {}`, etc.
!
self
.restrictions
.contains
(
Restrictions
::
RESTRICTION_NO_STRUCT_LITERAL
)
}
fn
is_union_item
(
&
self
)
->
bool
{
self
.token
.is_keyword
(
keywords
::
Union
)
&&
self
.look_ahead
(
1
,
|
t
|
t
.is_ident
()
&&
!
t
.is_any_keyword
())
...
...
@@ -4875,6 +4904,8 @@ fn parse_poly_trait_ref(&mut self) -> PResult<'a, PolyTraitRef> {
/// Parse struct Foo { ... }
fn
parse_item_struct
(
&
mut
self
)
->
PResult
<
'a
,
ItemInfo
>
{
let
class_name
=
self
.parse_ident
()
?
;
self
.error_if_typename_is_catch
(
class_name
);
let
mut
generics
=
self
.parse_generics
()
?
;
// There is a special case worth noting here, as reported in issue #17904.
...
...
@@ -4924,6 +4955,8 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
/// Parse union Foo { ... }
fn
parse_item_union
(
&
mut
self
)
->
PResult
<
'a
,
ItemInfo
>
{
let
class_name
=
self
.parse_ident
()
?
;
self
.error_if_typename_is_catch
(
class_name
);
let
mut
generics
=
self
.parse_generics
()
?
;
let
vdata
=
if
self
.token
.is_keyword
(
keywords
::
Where
)
{
...
...
@@ -5440,6 +5473,7 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef>
let
struct_def
;
let
mut
disr_expr
=
None
;
let
ident
=
self
.parse_ident
()
?
;
self
.error_if_typename_is_catch
(
ident
);
if
self
.check
(
&
token
::
OpenDelim
(
token
::
Brace
))
{
// Parse a struct variant.
all_nullary
=
false
;
...
...
@@ -5481,6 +5515,7 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef>
/// Parse an "enum" declaration
fn
parse_item_enum
(
&
mut
self
)
->
PResult
<
'a
,
ItemInfo
>
{
let
id
=
self
.parse_ident
()
?
;
self
.error_if_typename_is_catch
(
id
);
let
mut
generics
=
self
.parse_generics
()
?
;
generics
.where_clause
=
self
.parse_where_clause
()
?
;
self
.expect
(
&
token
::
OpenDelim
(
token
::
Brace
))
?
;
...
...
src/libsyntax/print/pprust.rs
浏览文件 @
d95c5437
...
...
@@ -2279,6 +2279,11 @@ fn print_expr_outer_attr_style(&mut self,
self
.print_expr
(
e
)
?
;
word
(
&
mut
self
.s
,
"?"
)
?
}
ast
::
ExprKind
::
Catch
(
ref
blk
)
=>
{
self
.head
(
"catch"
)
?
;
space
(
&
mut
self
.s
)
?
;
self
.print_block_with_attrs
(
&
blk
,
attrs
)
?
}
}
self
.ann
.post
(
self
,
NodeExpr
(
expr
))
?
;
self
.end
()
...
...
src/libsyntax/symbol.rs
浏览文件 @
d95c5437
...
...
@@ -221,9 +221,10 @@ fn fresh() -> Self {
(
53
,
Default
,
"default"
)
(
54
,
StaticLifetime
,
"'static"
)
(
55
,
Union
,
"union"
)
(
56
,
Catch
,
"catch"
)
// A virtual keyword that resolves to the crate root when used in a lexical scope.
(
5
6
,
CrateRoot
,
"{{root}}"
)
(
5
7
,
CrateRoot
,
"{{root}}"
)
}
// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
...
...
src/libsyntax/visit.rs
浏览文件 @
d95c5437
...
...
@@ -779,6 +779,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind
::
Try
(
ref
subexpression
)
=>
{
visitor
.visit_expr
(
subexpression
)
}
ExprKind
::
Catch
(
ref
body
)
=>
{
visitor
.visit_block
(
body
)
}
}
visitor
.visit_expr_post
(
expression
)
...
...
src/test/compile-fail/catch-empty-struct-name.rs
0 → 100644
浏览文件 @
d95c5437
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![feature(catch_expr)]
struct
catch
;
//~ ERROR cannot use `catch` as the name of a type
src/test/compile-fail/catch-enum-variant.rs
0 → 100644
浏览文件 @
d95c5437
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![feature(catch_expr)]
enum
Enum
{
catch
{}
//~ ERROR cannot use `catch` as the name of a type
}
src/test/compile-fail/catch-struct-name.rs
0 → 100644
浏览文件 @
d95c5437
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![feature(catch_expr)]
struct
catch
{}
//~ ERROR cannot use `catch` as the name of a type
\ No newline at end of file
src/test/compile-fail/catch-tuple-struct-name.rs
0 → 100644
浏览文件 @
d95c5437
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![feature(catch_expr)]
struct
catch
();
//~ ERROR cannot use `catch` as the name of a type
src/test/compile-fail/feature-gate-catch_expr.rs
0 → 100644
浏览文件 @
d95c5437
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub
fn
main
()
{
let
catch_result
=
catch
{
//~ ERROR `catch` expression is experimental
let
x
=
5
;
x
};
assert_eq!
(
catch_result
,
5
);
}
src/test/run-pass/catch-expr.rs
0 → 100644
浏览文件 @
d95c5437
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(catch_expr)]
pub
fn
main
()
{
let
catch_result
=
catch
{
let
x
=
5
;
x
};
assert_eq!
(
catch_result
,
5
);
let
mut
catch
=
true
;
while
catch
{
catch
=
false
;
}
assert_eq!
(
catch
,
false
);
catch
=
if
catch
{
false
}
else
{
true
};
assert_eq!
(
catch
,
true
);
match
catch
{
_
=>
{}
};
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录