Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
47f92a58
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
未验证
提交
47f92a58
编写于
1月 29, 2022
作者:
D
David Tolnay
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Accommodate yield points in the format_args expansion
上级
1dd02e32
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
49 addition
and
4 deletion
+49
-4
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/format.rs
+49
-4
未找到文件。
compiler/rustc_builtin_macros/src/format.rs
浏览文件 @
47f92a58
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
use
rustc_ast
as
ast
;
use
rustc_ast
as
ast
;
use
rustc_ast
::
ptr
::
P
;
use
rustc_ast
::
ptr
::
P
;
use
rustc_ast
::
tokenstream
::
TokenStream
;
use
rustc_ast
::
tokenstream
::
TokenStream
;
use
rustc_ast
::
visit
::{
self
,
Visitor
};
use
rustc_ast
::{
token
,
BlockCheckMode
,
UnsafeSource
};
use
rustc_ast
::{
token
,
BlockCheckMode
,
UnsafeSource
};
use
rustc_data_structures
::
fx
::{
FxHashMap
,
FxHashSet
};
use
rustc_data_structures
::
fx
::{
FxHashMap
,
FxHashSet
};
use
rustc_errors
::{
pluralize
,
Applicability
,
DiagnosticBuilder
};
use
rustc_errors
::{
pluralize
,
Applicability
,
DiagnosticBuilder
};
...
@@ -788,17 +789,31 @@ fn into_expr(self) -> P<ast::Expr> {
...
@@ -788,17 +789,31 @@ fn into_expr(self) -> P<ast::Expr> {
// the order provided to fmt::Arguments. When arguments are repeated, we
// the order provided to fmt::Arguments. When arguments are repeated, we
// want the expression evaluated only once.
// want the expression evaluated only once.
//
//
// Thus in the not nicely ordered case we emit the following instead:
// Further, if any arg _after the first one_ contains a yield point such
// as `await` or `yield`, the above short form is inconvenient for the
// caller because it would keep a temporary of type ArgumentV1 alive
// across the yield point. ArgumentV1 can't implement Send since it
// holds a type-erased arbitrary type.
//
// Thus in the not nicely ordered case, and in the yielding case, we
// emit the following instead:
//
//
// match (&$arg0, &$arg1, …) {
// match (&$arg0, &$arg1, …) {
// args => [ArgumentV1::new(args.$i, …), ArgumentV1::new(args.$j, …), …]
// args => [ArgumentV1::new(args.$i, …), ArgumentV1::new(args.$j, …), …]
// }
// }
//
//
// for the sequence of indices $i, $j, … governed by fmt_arg_index_and_ty.
// for the sequence of indices $i, $j, … governed by fmt_arg_index_and_ty.
// This more verbose representation ensures that all arguments are
// evaluated a single time each, in the order written by the programmer,
// and that the surrounding future/generator (if any) is Send whenever
// possible.
let
no_need_for_match
=
nicely_ordered
&&
!
original_args
.iter
()
.skip
(
1
)
.any
(|
e
|
may_contain_yield_point
(
e
));
for
(
arg_index
,
arg_ty
)
in
fmt_arg_index_and_ty
{
for
(
arg_index
,
arg_ty
)
in
fmt_arg_index_and_ty
{
let
e
=
&
mut
original_args
[
arg_index
];
let
e
=
&
mut
original_args
[
arg_index
];
let
span
=
e
.span
;
let
span
=
e
.span
;
let
arg
=
if
n
icely_ordered
{
let
arg
=
if
n
o_need_for_match
{
let
expansion_span
=
e
.span
.with_ctxt
(
self
.macsp
.ctxt
());
let
expansion_span
=
e
.span
.with_ctxt
(
self
.macsp
.ctxt
());
// The indices are strictly ordered so e has not been taken yet.
// The indices are strictly ordered so e has not been taken yet.
self
.ecx
.expr_addr_of
(
expansion_span
,
P
(
e
.take
()))
self
.ecx
.expr_addr_of
(
expansion_span
,
P
(
e
.take
()))
...
@@ -814,10 +829,10 @@ fn into_expr(self) -> P<ast::Expr> {
...
@@ -814,10 +829,10 @@ fn into_expr(self) -> P<ast::Expr> {
let
args_array
=
self
.ecx
.expr_vec
(
self
.macsp
,
fmt_args
);
let
args_array
=
self
.ecx
.expr_vec
(
self
.macsp
,
fmt_args
);
let
args_slice
=
self
.ecx
.expr_addr_of
(
let
args_slice
=
self
.ecx
.expr_addr_of
(
self
.macsp
,
self
.macsp
,
if
n
icely_ordered
{
if
n
o_need_for_match
{
args_array
args_array
}
else
{
}
else
{
// In the !n
icely_ordered
case, none of the exprs were moved
// In the !n
o_need_for_match
case, none of the exprs were moved
// away in the previous loop.
// away in the previous loop.
//
//
// This uses the arg span for `&arg` so that borrowck errors
// This uses the arg span for `&arg` so that borrowck errors
...
@@ -1216,3 +1231,33 @@ pub fn expand_preparsed_format_args(
...
@@ -1216,3 +1231,33 @@ pub fn expand_preparsed_format_args(
cx
.into_expr
()
cx
.into_expr
()
}
}
fn
may_contain_yield_point
(
e
:
&
ast
::
Expr
)
->
bool
{
struct
MayContainYieldPoint
(
bool
);
impl
Visitor
<
'_
>
for
MayContainYieldPoint
{
fn
visit_expr
(
&
mut
self
,
e
:
&
ast
::
Expr
)
{
if
let
ast
::
ExprKind
::
Await
(
_
)
|
ast
::
ExprKind
::
Yield
(
_
)
|
ast
::
ExprKind
::
MacCall
(
_
)
=
e
.kind
{
self
.0
=
true
;
}
else
{
visit
::
walk_expr
(
self
,
e
);
}
}
fn
visit_attribute
(
&
mut
self
,
_
:
&
ast
::
Attribute
)
{
// Conservatively assume this may be a proc macro attribute in
// expression position.
self
.0
=
true
;
}
fn
visit_item
(
&
mut
self
,
_
:
&
ast
::
Item
)
{
// Do not recurse into nested items.
}
}
let
mut
visitor
=
MayContainYieldPoint
(
false
);
visitor
.visit_expr
(
e
);
visitor
.0
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录