Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
2017be4e
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,发现更多精彩内容 >>
提交
2017be4e
编写于
6月 17, 2019
作者:
M
Mazdak Farrokhzad
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
let_chains: Remove ast_validation logic in favor of lowering with recovery.
上级
10234d28
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
49 addition
and
67 deletion
+49
-67
src/librustc/hir/lowering.rs
src/librustc/hir/lowering.rs
+40
-8
src/librustc_passes/ast_validation.rs
src/librustc_passes/ast_validation.rs
+9
-59
未找到文件。
src/librustc/hir/lowering.rs
浏览文件 @
2017be4e
...
...
@@ -4344,12 +4344,39 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
let
ohs
=
P
(
self
.lower_expr
(
ohs
));
hir
::
ExprKind
::
AddrOf
(
m
,
ohs
)
}
ExprKind
::
Let
(
..
)
=>
{
// This should have been caught `ast_validation`!
self
.sess
.span_err
(
e
.span
,
"`let` expressions only supported in `if`"
);
// ^-- FIXME(53667): Change to `delay_span_bug` when let_chains handled in lowering.
self
.sess
.abort_if_errors
();
hir
::
ExprKind
::
Err
ExprKind
::
Let
(
ref
pats
,
ref
scrutinee
)
=>
{
// If we got here, the `let` expression is not allowed.
self
.sess
.struct_span_err
(
e
.span
,
"`let` expressions are not supported here"
)
.note
(
"only supported directly in conditions of `if`- and `while`-expressions"
)
.note
(
"as well as when nested within `&&` and parenthesis in those conditions"
)
.emit
();
// For better recovery, we emit:
// ```
// match scrutinee { pats => true, _ => false }
// ```
// While this doesn't fully match the user's intent, it has key advantages:
// 1. We can avoid using `abort_if_errors`.
// 2. We can typeck both `pats` and `scrutinee`.
// 3. `pats` is allowed to be refutable.
// 4. The return type of the block is `bool` which seems like what the user wanted.
let
scrutinee
=
self
.lower_expr
(
scrutinee
);
let
then_arm
=
{
let
pats
=
pats
.iter
()
.map
(|
pat
|
self
.lower_pat
(
pat
))
.collect
();
let
expr
=
self
.expr_bool
(
e
.span
,
true
);
self
.arm
(
pats
,
P
(
expr
))
};
let
else_arm
=
{
let
pats
=
hir_vec!
[
self
.pat_wild
(
e
.span
)];
let
expr
=
self
.expr_bool
(
e
.span
,
false
);
self
.arm
(
pats
,
P
(
expr
))
};
hir
::
ExprKind
::
Match
(
P
(
scrutinee
),
vec!
[
then_arm
,
else_arm
]
.into
(),
hir
::
MatchSource
::
Normal
,
)
}
// FIXME(#53667): handle lowering of && and parens.
ExprKind
::
If
(
ref
cond
,
ref
then
,
ref
else_opt
)
=>
{
...
...
@@ -5431,10 +5458,15 @@ fn expr_unsafe(&mut self, expr: P<hir::Expr>) -> hir::Expr {
)
}
/// Constructs a `true` or `false` literal expression.
fn
expr_bool
(
&
mut
self
,
span
:
Span
,
val
:
bool
)
->
hir
::
Expr
{
let
lit
=
Spanned
{
span
,
node
:
LitKind
::
Bool
(
val
)
};
self
.expr
(
span
,
hir
::
ExprKind
::
Lit
(
lit
),
ThinVec
::
new
())
}
/// Constructs a `true` or `false` literal pattern.
fn
pat_bool
(
&
mut
self
,
span
:
Span
,
val
:
bool
)
->
P
<
hir
::
Pat
>
{
let
lit
=
Spanned
{
span
,
node
:
LitKind
::
Bool
(
val
)
};
let
expr
=
self
.expr
(
span
,
hir
::
ExprKind
::
Lit
(
lit
),
ThinVec
::
new
());
let
expr
=
self
.expr_bool
(
span
,
val
);
self
.pat
(
span
,
hir
::
PatKind
::
Lit
(
P
(
expr
)))
}
...
...
src/librustc_passes/ast_validation.rs
浏览文件 @
2017be4e
...
...
@@ -74,9 +74,6 @@ struct AstValidator<'a> {
/// these booleans.
warning_period_57979_didnt_record_next_impl_trait
:
bool
,
warning_period_57979_impl_trait_in_proj
:
bool
,
/// Used to ban `let` expressions in inappropriate places.
is_let_allowed
:
bool
,
}
/// With the `new` value in `store`,
...
...
@@ -114,12 +111,6 @@ fn with_impl_trait(&mut self, outer: Option<OuterImplTrait>, f: impl FnOnce(&mut
with
(
self
,
outer
,
|
this
|
&
mut
this
.outer_impl_trait
,
f
)
}
fn
with_let_allowed
(
&
mut
self
,
v
:
bool
,
f
:
impl
FnOnce
(
&
mut
Self
,
bool
))
{
let
old
=
mem
::
replace
(
&
mut
self
.is_let_allowed
,
v
);
f
(
self
,
old
);
self
.is_let_allowed
=
old
;
}
fn
visit_assoc_ty_constraint_from_generic_args
(
&
mut
self
,
constraint
:
&
'a
AssocTyConstraint
)
{
match
constraint
.kind
{
AssocTyConstraintKind
::
Equality
{
ref
ty
}
=>
{
...
...
@@ -335,15 +326,6 @@ fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
}
}
/// Emits an error banning the `let` expression provided.
fn
ban_let_expr
(
&
self
,
expr
:
&
'a
Expr
)
{
self
.err_handler
()
.struct_span_err
(
expr
.span
,
"`let` expressions are not supported here"
)
.note
(
"only supported directly in conditions of `if`- and `while`-expressions"
)
.note
(
"as well as when nested within `&&` and parenthesis in those conditions"
)
.emit
();
}
fn
check_fn_decl
(
&
self
,
fn_decl
:
&
FnDecl
)
{
fn_decl
.inputs
...
...
@@ -470,48 +452,17 @@ fn validate_generics_order<'a>(
impl
<
'a
>
Visitor
<
'a
>
for
AstValidator
<
'a
>
{
fn
visit_expr
(
&
mut
self
,
expr
:
&
'a
Expr
)
{
self
.with_let_allowed
(
false
,
|
this
,
let_allowed
|
{
match
&
expr
.node
{
ExprKind
::
Let
(
_
,
_
)
if
!
let_allowed
=>
{
this
.ban_let_expr
(
expr
);
}
// Assuming the context permits, `($expr)` does not impose additional constraints.
ExprKind
::
Paren
(
_
)
=>
{
this
.with_let_allowed
(
let_allowed
,
|
this
,
_
|
visit
::
walk_expr
(
this
,
expr
));
return
;
// We've already walked into `expr`.
}
// Assuming the context permits,
// l && r` allows decendants in `l` and `r` to be `let` expressions.
ExprKind
::
Binary
(
op
,
..
)
if
op
.node
==
BinOpKind
::
And
=>
{
this
.with_let_allowed
(
let_allowed
,
|
this
,
_
|
visit
::
walk_expr
(
this
,
expr
));
return
;
// We've already walked into `expr`.
}
// However, we do allow it in the condition of the `if` expression.
// We do not allow `let` in `then` and `opt_else` directly.
ExprKind
::
If
(
cond
,
then
,
opt_else
)
=>
{
this
.visit_block
(
then
);
walk_list!
(
this
,
visit_expr
,
opt_else
);
this
.with_let_allowed
(
true
,
|
this
,
_
|
this
.visit_expr
(
cond
));
return
;
// We've already walked into `expr`.
}
// The same logic applies to `While`.
ExprKind
::
While
(
cond
,
then
,
opt_label
)
=>
{
walk_list!
(
this
,
visit_label
,
opt_label
);
this
.visit_block
(
then
);
this
.with_let_allowed
(
true
,
|
this
,
_
|
this
.visit_expr
(
cond
));
return
;
// We've already walked into `expr`.
}
ExprKind
::
Closure
(
_
,
_
,
_
,
fn_decl
,
_
,
_
)
=>
{
this
.check_fn_decl
(
fn_decl
);
}
ExprKind
::
InlineAsm
(
..
)
if
!
this
.session.target.target.options.allow_asm
=>
{
span_err!
(
this
.session
,
expr
.span
,
E0472
,
"asm! is unsupported on this target"
);
}
_
=>
{}
match
&
expr
.node
{
ExprKind
::
Closure
(
_
,
_
,
_
,
fn_decl
,
_
,
_
)
=>
{
self
.check_fn_decl
(
fn_decl
);
}
ExprKind
::
InlineAsm
(
..
)
if
!
self
.session.target.target.options.allow_asm
=>
{
span_err!
(
self
.session
,
expr
.span
,
E0472
,
"asm! is unsupported on this target"
);
}
_
=>
{}
}
visit
::
walk_expr
(
this
,
expr
);
});
visit
::
walk_expr
(
self
,
expr
);
}
fn
visit_ty
(
&
mut
self
,
ty
:
&
'a
Ty
)
{
...
...
@@ -923,7 +874,6 @@ pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) {
is_assoc_ty_bound_banned
:
false
,
warning_period_57979_didnt_record_next_impl_trait
:
false
,
warning_period_57979_impl_trait_in_proj
:
false
,
is_let_allowed
:
false
,
};
visit
::
walk_crate
(
&
mut
validator
,
krate
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录