Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d64e577f
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,发现更多精彩内容 >>
提交
d64e577f
编写于
6月 18, 2018
作者:
T
Taylor Cramer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Async methods
上级
d02631d3
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
122 addition
and
79 deletion
+122
-79
src/librustc/hir/lowering.rs
src/librustc/hir/lowering.rs
+17
-5
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/def_collector.rs
+39
-13
src/librustc_passes/ast_validation.rs
src/librustc_passes/ast_validation.rs
+8
-0
src/librustc_passes/diagnostics.rs
src/librustc_passes/diagnostics.rs
+1
-0
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+25
-52
src/libsyntax/parse/parser.rs
src/libsyntax/parse/parser.rs
+23
-6
src/test/run-pass/async-await.rs
src/test/run-pass/async-await.rs
+8
-2
src/test/ui/async-fn-multiple-lifetimes.stderr
src/test/ui/async-fn-multiple-lifetimes.stderr
+1
-1
未找到文件。
src/librustc/hir/lowering.rs
浏览文件 @
d64e577f
...
...
@@ -2932,7 +2932,7 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
AnonymousLifetimeMode
::
PassThrough
,
|
this
|
{
hir
::
TraitItemKind
::
Method
(
this
.lower_method_sig
(
sig
,
trait_item_def_id
,
false
),
this
.lower_method_sig
(
sig
,
trait_item_def_id
,
false
,
false
),
hir
::
TraitMethod
::
Required
(
names
),
)
},
...
...
@@ -2950,7 +2950,7 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
AnonymousLifetimeMode
::
PassThrough
,
|
this
|
{
hir
::
TraitItemKind
::
Method
(
this
.lower_method_sig
(
sig
,
trait_item_def_id
,
false
),
this
.lower_method_sig
(
sig
,
trait_item_def_id
,
false
,
false
),
hir
::
TraitMethod
::
Provided
(
body_id
),
)
},
...
...
@@ -3021,8 +3021,18 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
}
ImplItemKind
::
Method
(
ref
sig
,
ref
body
)
=>
{
let
body_id
=
self
.lower_body
(
Some
(
&
sig
.decl
),
|
this
|
{
let
body
=
this
.lower_block
(
body
,
false
);
this
.expr_block
(
body
,
ThinVec
::
new
())
if
let
IsAsync
::
Async
(
async_node_id
)
=
sig
.header.asyncness
{
let
async_expr
=
this
.make_async_expr
(
CaptureBy
::
Value
,
async_node_id
,
None
,
|
this
|
{
let
body
=
this
.lower_block
(
body
,
false
);
this
.expr_block
(
body
,
ThinVec
::
new
())
});
this
.expr
(
body
.span
,
async_expr
,
ThinVec
::
new
())
}
else
{
let
body
=
this
.lower_block
(
body
,
false
);
this
.expr_block
(
body
,
ThinVec
::
new
())
}
});
let
impl_trait_return_allow
=
!
self
.is_in_trait_impl
;
...
...
@@ -3036,6 +3046,7 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
sig
,
impl_item_def_id
,
impl_trait_return_allow
,
sig
.header.asyncness
.is_async
(),
),
body_id
,
)
...
...
@@ -3201,10 +3212,11 @@ fn lower_method_sig(
sig
:
&
MethodSig
,
fn_def_id
:
DefId
,
impl_trait_return_allow
:
bool
,
is_async
:
bool
,
)
->
hir
::
MethodSig
{
hir
::
MethodSig
{
header
:
self
.lower_fn_header
(
sig
.header
),
decl
:
self
.lower_fn_decl
(
&
sig
.decl
,
Some
(
fn_def_id
),
impl_trait_return_allow
,
false
),
decl
:
self
.lower_fn_decl
(
&
sig
.decl
,
Some
(
fn_def_id
),
impl_trait_return_allow
,
is_async
),
}
}
...
...
src/librustc/hir/map/def_collector.rs
浏览文件 @
d64e577f
...
...
@@ -73,6 +73,27 @@ pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F)
self
.parent_def
=
parent
;
}
fn
visit_async_fn
(
&
mut
self
,
id
:
NodeId
,
async_node_id
:
NodeId
,
name
:
Name
,
span
:
Span
,
visit_fn
:
impl
FnOnce
(
&
mut
DefCollector
<
'a
>
)
)
{
// For async functions, we need to create their inner defs inside of a
// closure to match their desugared representation.
let
fn_def_data
=
DefPathData
::
ValueNs
(
name
.as_interned_str
());
let
fn_def
=
self
.create_def
(
id
,
fn_def_data
,
ITEM_LIKE_SPACE
,
span
);
return
self
.with_parent
(
fn_def
,
|
this
|
{
let
closure_def
=
this
.create_def
(
async_node_id
,
DefPathData
::
ClosureExpr
,
REGULAR_SPACE
,
span
);
this
.with_parent
(
closure_def
,
visit_fn
)
})
}
fn
visit_macro_invoc
(
&
mut
self
,
id
:
NodeId
)
{
if
let
Some
(
ref
mut
visit
)
=
self
.visit_macro_invoc
{
visit
(
MacroInvocationData
{
...
...
@@ -100,19 +121,13 @@ fn visit_item(&mut self, i: &'a Item) {
return
visit
::
walk_item
(
self
,
i
);
}
ItemKind
::
Fn
(
_
,
FnHeader
{
asyncness
:
IsAsync
::
Async
(
async_node_id
),
..
},
..
)
=>
{
// For async functions, we need to create their inner defs inside of a
// closure to match their desugared representation.
let
fn_def_data
=
DefPathData
::
ValueNs
(
i
.ident.name
.as_interned_str
());
let
fn_def
=
self
.create_def
(
i
.id
,
fn_def_data
,
ITEM_LIKE_SPACE
,
i
.span
);
return
self
.with_parent
(
fn_def
,
|
this
|
{
let
closure_def
=
this
.create_def
(
async_node_id
,
DefPathData
::
ClosureExpr
,
REGULAR_SPACE
,
i
.span
);
this
.with_parent
(
closure_def
,
|
this
|
{
visit
::
walk_item
(
this
,
i
);
})
});
return
self
.visit_async_fn
(
i
.id
,
async_node_id
,
i
.ident.name
,
i
.span
,
|
this
|
visit
::
walk_item
(
this
,
i
)
)
}
ItemKind
::
Mod
(
..
)
=>
DefPathData
::
Module
(
i
.ident.name
.as_interned_str
()),
ItemKind
::
Static
(
..
)
|
ItemKind
::
Const
(
..
)
|
ItemKind
::
Fn
(
..
)
=>
...
...
@@ -212,6 +227,17 @@ fn visit_trait_item(&mut self, ti: &'a TraitItem) {
fn
visit_impl_item
(
&
mut
self
,
ii
:
&
'a
ImplItem
)
{
let
def_data
=
match
ii
.node
{
ImplItemKind
::
Method
(
MethodSig
{
header
:
FnHeader
{
asyncness
:
IsAsync
::
Async
(
async_node_id
),
..
},
..
},
..
)
=>
{
return
self
.visit_async_fn
(
ii
.id
,
async_node_id
,
ii
.ident.name
,
ii
.span
,
|
this
|
visit
::
walk_impl_item
(
this
,
ii
)
)
}
ImplItemKind
::
Method
(
..
)
|
ImplItemKind
::
Const
(
..
)
=>
DefPathData
::
ValueNs
(
ii
.ident.name
.as_interned_str
()),
ImplItemKind
::
Type
(
..
)
=>
DefPathData
::
AssocTypeInImpl
(
ii
.ident.name
.as_interned_str
()),
...
...
src/librustc_passes/ast_validation.rs
浏览文件 @
d64e577f
...
...
@@ -87,6 +87,13 @@ fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&self, decl: &FnDecl, report_err:
}
}
fn
check_trait_fn_not_async
(
&
self
,
span
:
Span
,
asyncness
:
IsAsync
)
{
if
asyncness
.is_async
()
{
struct_span_err!
(
self
.session
,
span
,
E0706
,
"trait fns cannot be declared `async`"
)
.emit
()
}
}
fn
check_trait_fn_not_const
(
&
self
,
constness
:
Spanned
<
Constness
>
)
{
match
constness
.node
{
Constness
::
Const
=>
{
...
...
@@ -309,6 +316,7 @@ fn visit_item(&mut self, item: &'a Item) {
self
.no_questions_in_bounds
(
bounds
,
"supertraits"
,
true
);
for
trait_item
in
trait_items
{
if
let
TraitItemKind
::
Method
(
ref
sig
,
ref
block
)
=
trait_item
.node
{
self
.check_trait_fn_not_async
(
trait_item
.span
,
sig
.header.asyncness
);
self
.check_trait_fn_not_const
(
sig
.header.constness
);
if
block
.is_none
()
{
self
.check_decl_no_pat
(
&
sig
.decl
,
|
span
,
mut_ident
|
{
...
...
src/librustc_passes/diagnostics.rs
浏览文件 @
d64e577f
...
...
@@ -310,4 +310,5 @@ fn foo() {}
E0666
,
// nested `impl Trait` is illegal
E0667
,
// `impl Trait` in projections
E0696
,
// `continue` pointing to a labeled block
E0706
,
// `async fn` in trait
}
src/librustc_resolve/lib.rs
浏览文件 @
d64e577f
...
...
@@ -746,15 +746,17 @@ fn visit_fn(&mut self,
function_kind
:
FnKind
<
'tcx
>
,
declaration
:
&
'tcx
FnDecl
,
_
:
Span
,
node_id
:
NodeId
)
{
let
rib_kind
=
match
function_kind
{
FnKind
::
ItemFn
(
..
)
=>
{
ItemRibKind
}
FnKind
::
Method
(
_
,
_
,
_
,
_
)
=>
{
TraitOrImplItemRibKind
}
FnKind
::
Closure
(
_
)
=>
ClosureRibKind
(
node_id
),
node_id
:
NodeId
)
{
let
(
rib_kind
,
asyncness
)
=
match
function_kind
{
FnKind
::
ItemFn
(
_
,
ref
header
,
..
)
=>
(
ItemRibKind
,
header
.asyncness
),
FnKind
::
Method
(
_
,
ref
sig
,
_
,
_
)
=>
(
TraitOrImplItemRibKind
,
sig
.header.asyncness
),
FnKind
::
Closure
(
_
)
=>
// Async closures aren't resolved through `visit_fn`-- they're
// processed separately
(
ClosureRibKind
(
node_id
),
IsAsync
::
NotAsync
),
};
// Create a value rib for the function.
...
...
@@ -774,7 +776,13 @@ fn visit_fn(&mut self,
}
visit
::
walk_fn_ret_ty
(
self
,
&
declaration
.output
);
// Resolve the function body.
// Resolve the function body, potentially inside the body of an async closure
if
let
IsAsync
::
Async
(
async_closure_id
)
=
asyncness
{
let
rib_kind
=
ClosureRibKind
(
async_closure_id
);
self
.ribs
[
ValueNS
]
.push
(
Rib
::
new
(
rib_kind
));
self
.label_ribs
.push
(
Rib
::
new
(
rib_kind
));
}
match
function_kind
{
FnKind
::
ItemFn
(
..
,
body
)
|
FnKind
::
Method
(
..
,
body
)
=>
{
...
...
@@ -785,6 +793,12 @@ fn visit_fn(&mut self,
}
};
// Leave the body of the async closure
if
asyncness
.is_async
()
{
self
.label_ribs
.pop
();
self
.ribs
[
ValueNS
]
.pop
();
}
debug!
(
"(resolving function) leaving function"
);
self
.label_ribs
.pop
();
...
...
@@ -2054,47 +2068,6 @@ fn resolve_item(&mut self, item: &Item) {
self
.check_proc_macro_attrs
(
&
item
.attrs
);
match
item
.node
{
ItemKind
::
Fn
(
ref
declaration
,
FnHeader
{
asyncness
:
IsAsync
::
Async
(
async_closure_id
),
..
},
ref
generics
,
ref
body
)
=>
{
// Async functions are desugared from `async fn foo() { .. }`
// to `fn foo() { future_from_generator(move || ... ) }`,
// so we have to visit the body inside the closure scope
self
.with_type_parameter_rib
(
HasTypeParameters
(
generics
,
ItemRibKind
),
|
this
|
{
this
.visit_vis
(
&
item
.vis
);
this
.visit_ident
(
item
.ident
);
this
.visit_generics
(
generics
);
let
rib_kind
=
ItemRibKind
;
this
.ribs
[
ValueNS
]
.push
(
Rib
::
new
(
rib_kind
));
this
.label_ribs
.push
(
Rib
::
new
(
rib_kind
));
let
mut
bindings_list
=
FxHashMap
();
for
argument
in
&
declaration
.inputs
{
this
.resolve_pattern
(
&
argument
.pat
,
PatternSource
::
FnParam
,
&
mut
bindings_list
);
this
.visit_ty
(
&*
argument
.ty
);
}
visit
::
walk_fn_ret_ty
(
this
,
&
declaration
.output
);
// Now resolve the inner closure
{
let
rib_kind
=
ClosureRibKind
(
async_closure_id
);
this
.ribs
[
ValueNS
]
.push
(
Rib
::
new
(
rib_kind
));
this
.label_ribs
.push
(
Rib
::
new
(
rib_kind
));
// No need to resolve either arguments nor return type,
// as this closure has neither
// Resolve the body
this
.visit_block
(
body
);
this
.label_ribs
.pop
();
this
.ribs
[
ValueNS
]
.pop
();
}
this
.label_ribs
.pop
();
this
.ribs
[
ValueNS
]
.pop
();
walk_list!
(
this
,
visit_attribute
,
&
item
.attrs
);
})
}
ItemKind
::
Enum
(
_
,
ref
generics
)
|
ItemKind
::
Ty
(
_
,
ref
generics
)
|
ItemKind
::
Struct
(
_
,
ref
generics
)
|
...
...
@@ -2415,7 +2388,7 @@ fn resolve_implementation(&mut self,
visit
::
walk_impl_item
(
this
,
impl_item
)
);
}
ImplItemKind
::
Method
(
_
,
_
)
=>
{
ImplItemKind
::
Method
(
..
)
=>
{
// If this is a trait impl, ensure the method
// exists in trait
this
.check_trait_item
(
impl_item
.ident
,
...
...
src/libsyntax/parse/parser.rs
浏览文件 @
d64e577f
...
...
@@ -1293,6 +1293,15 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a,
})))
}
/// Parse asyncness: `async` or nothing
fn
parse_asyncness
(
&
mut
self
)
->
IsAsync
{
if
self
.eat_keyword
(
keywords
::
Async
)
{
IsAsync
::
Async
(
ast
::
DUMMY_NODE_ID
)
}
else
{
IsAsync
::
NotAsync
}
}
/// Parse unsafety: `unsafe` or nothing.
fn
parse_unsafety
(
&
mut
self
)
->
Unsafety
{
if
self
.eat_keyword
(
keywords
::
Unsafe
)
{
...
...
@@ -1342,7 +1351,7 @@ fn parse_trait_item_(&mut self,
// trait item macro.
(
keywords
::
Invalid
.ident
(),
ast
::
TraitItemKind
::
Macro
(
mac
),
ast
::
Generics
::
default
())
}
else
{
let
(
constness
,
unsafety
,
abi
)
=
self
.parse_fn_front_matter
()
?
;
let
(
constness
,
unsafety
,
a
syncness
,
a
bi
)
=
self
.parse_fn_front_matter
()
?
;
let
ident
=
self
.parse_ident
()
?
;
let
mut
generics
=
self
.parse_generics
()
?
;
...
...
@@ -1360,7 +1369,7 @@ fn parse_trait_item_(&mut self,
unsafety
,
constness
,
abi
,
asyncness
:
IsAsync
::
NotAsync
,
asyncness
,
},
decl
:
d
,
};
...
...
@@ -5425,10 +5434,18 @@ fn is_const_item(&mut self) -> bool {
/// - `const unsafe fn`
/// - `extern fn`
/// - etc
fn
parse_fn_front_matter
(
&
mut
self
)
->
PResult
<
'a
,
(
Spanned
<
Constness
>
,
Unsafety
,
Abi
)
>
{
fn
parse_fn_front_matter
(
&
mut
self
)
->
PResult
<
'a
,
(
Spanned
<
Constness
>
,
Unsafety
,
IsAsync
,
Abi
)
>
{
let
is_const_fn
=
self
.eat_keyword
(
keywords
::
Const
);
let
const_span
=
self
.prev_span
;
let
unsafety
=
self
.parse_unsafety
();
let
asyncness
=
self
.parse_asyncness
();
let
(
constness
,
unsafety
,
abi
)
=
if
is_const_fn
{
(
respan
(
const_span
,
Constness
::
Const
),
unsafety
,
Abi
::
Rust
)
}
else
{
...
...
@@ -5440,7 +5457,7 @@ fn parse_fn_front_matter(&mut self) -> PResult<'a, (Spanned<Constness>, Unsafety
(
respan
(
self
.prev_span
,
Constness
::
NotConst
),
unsafety
,
abi
)
};
self
.expect_keyword
(
keywords
::
Fn
)
?
;
Ok
((
constness
,
unsafety
,
abi
))
Ok
((
constness
,
unsafety
,
a
syncness
,
a
bi
))
}
/// Parse an impl item.
...
...
@@ -5575,14 +5592,14 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
Ok
((
keywords
::
Invalid
.ident
(),
vec!
[],
ast
::
Generics
::
default
(),
ast
::
ImplItemKind
::
Macro
(
mac
)))
}
else
{
let
(
constness
,
unsafety
,
abi
)
=
self
.parse_fn_front_matter
()
?
;
let
(
constness
,
unsafety
,
a
syncness
,
a
bi
)
=
self
.parse_fn_front_matter
()
?
;
let
ident
=
self
.parse_ident
()
?
;
let
mut
generics
=
self
.parse_generics
()
?
;
let
decl
=
self
.parse_fn_decl_with_self
(|
p
|
p
.parse_arg
())
?
;
generics
.where_clause
=
self
.parse_where_clause
()
?
;
*
at_end
=
true
;
let
(
inner_attrs
,
body
)
=
self
.parse_inner_attrs_and_block
()
?
;
let
header
=
ast
::
FnHeader
{
abi
,
unsafety
,
constness
,
asyncness
:
IsAsync
::
NotAsync
};
let
header
=
ast
::
FnHeader
{
abi
,
unsafety
,
constness
,
asyncness
};
Ok
((
ident
,
inner_attrs
,
generics
,
ast
::
ImplItemKind
::
Method
(
ast
::
MethodSig
{
header
,
decl
},
body
...
...
src/test/run-pass/async-await.rs
浏览文件 @
d64e577f
...
...
@@ -104,10 +104,16 @@ fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
x
}
struct
Foo
{
struct
Foo
;
trait
Bar
{
fn
foo
()
{}
}
impl
Foo
{
async
fn
async_method
(
x
:
u8
)
->
u8
{
unsafe
{
await
!
(
unsafe_async_fn
())
await
!
(
unsafe_async_fn
(
x
))
}
}
}
...
...
src/test/ui/async-fn-multiple-lifetimes.stderr
浏览文件 @
d64e577f
...
...
@@ -6,7 +6,7 @@ LL | async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
| |
| first lifetime here
|
= help: `async fn` can only accept borrowed values identical lifetimes
= help: `async fn` can only accept borrowed values
with
identical lifetimes
error[E0704]: multiple elided lifetimes used in arguments of `async fn`
--> $DIR/async-fn-multiple-lifetimes.rs:26:39
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录