提交 9eb75613 编写于 作者: O Oliver Schneider

Generate `DefId`s for the impl trait of `async` functions

上级 2ec5eab3
......@@ -863,7 +863,7 @@ fn make_async_expr(
let capture_clause = self.lower_capture_clause(capture_clause);
let closure_hir_id = self.lower_node_id(closure_node_id).hir_id;
let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, false);
let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, None);
let generator = hir::Expr {
id: closure_node_id,
hir_id: closure_hir_id,
......@@ -1106,7 +1106,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
),
unsafety: this.lower_unsafety(f.unsafety),
abi: f.abi,
decl: this.lower_fn_decl(&f.decl, None, false, false),
decl: this.lower_fn_decl(&f.decl, None, false, None),
arg_names: this.lower_fn_args_to_names(&f.decl),
}))
},
......@@ -1176,7 +1176,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
|this| this.lower_param_bounds(bounds, itctx),
)
}
ImplTraitContext::Universal(def_id) => {
ImplTraitContext::Universal(_def_id) => {
self.lower_node_id(def_node_id);
// Add a definition for the in-band TyParam
let def_index = self
......@@ -1866,18 +1866,18 @@ fn lower_fn_args_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Spanned<Name>
// decl: the unlowered (ast) function declaration.
// fn_def_id: if `Some`, impl Trait arguments are lowered into generic parameters on the
// given DefId, otherwise impl Trait is disallowed. Must be `Some` if
// make_ret_async is true.
// make_ret_async is also `Some`.
// impl_trait_return_allow: determines whether impl Trait can be used in return position.
// This guards against trait declarations and implementations where impl Trait is
// disallowed.
// make_ret_async: if enabled, converts `-> T` into `-> impl Future<Output = T>` in the
// make_ret_async: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
// return type. This is used for `async fn` declarations.
fn lower_fn_decl(
&mut self,
decl: &FnDecl,
fn_def_id: Option<DefId>,
impl_trait_return_allow: bool,
make_ret_async: bool,
make_ret_async: Option<NodeId>,
) -> P<hir::FnDecl> {
let inputs = decl.inputs
.iter()
......@@ -1890,9 +1890,9 @@ fn lower_fn_decl(
})
.collect::<HirVec<_>>();
let output = if make_ret_async {
let output = if let Some(ret_id) = make_ret_async {
self.lower_async_fn_ret_ty(
&inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"))
&inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"), ret_id)
} else {
match decl.output {
FunctionRetTy::Ty(ref ty) => match fn_def_id {
......@@ -1928,6 +1928,7 @@ fn lower_async_fn_ret_ty(
inputs: &[P<hir::Ty>],
output: &FunctionRetTy,
fn_def_id: DefId,
return_impl_trait_id: NodeId,
) -> hir::FunctionRetTy {
// Get lifetimes used in the input arguments to the function. Our output type must also
// have the same lifetime. FIXME(cramertj) multiple different lifetimes are not allowed
......@@ -2079,7 +2080,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
};
let impl_trait_ty = self.lower_existential_impl_trait(
span, fn_def_id, |this| {
span, fn_def_id, return_impl_trait_id, |this| {
let output_ty = match output {
FunctionRetTy::Ty(ty) =>
this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)),
......@@ -2564,9 +2565,9 @@ fn lower_item_kind(
// only cares about the input argument patterns in the function
// declaration (decl), not the return types.
let body_id = this.lower_body(Some(decl), |this| {
if let IsAsync::Async(async_node_id) = header.asyncness {
if let IsAsync::Async { closure_id, .. } = header.asyncness {
let async_expr = this.make_async_expr(
CaptureBy::Value, async_node_id, None,
CaptureBy::Value, closure_id, None,
|this| {
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
......@@ -2578,12 +2579,17 @@ fn lower_item_kind(
}
});
let asyncness = match header.asyncness {
IsAsync::Async { return_impl_trait_id, .. } => Some(return_impl_trait_id),
IsAsync::NotAsync => None,
};
let (generics, fn_decl) = this.add_in_band_defs(
generics,
fn_def_id,
AnonymousLifetimeMode::PassThrough,
|this| this.lower_fn_decl(
decl, Some(fn_def_id), true, header.asyncness.is_async())
decl, Some(fn_def_id), true, asyncness)
);
hir::ItemFn(
......@@ -2906,7 +2912,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, false),
this.lower_method_sig(sig, trait_item_def_id, false, None),
hir::TraitMethod::Required(names),
)
},
......@@ -2924,7 +2930,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, false),
this.lower_method_sig(sig, trait_item_def_id, false, None),
hir::TraitMethod::Provided(body_id),
)
},
......@@ -2995,9 +3001,9 @@ 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| {
if let IsAsync::Async(async_node_id) = sig.header.asyncness {
if let IsAsync::Async { closure_id, .. } = sig.header.asyncness {
let async_expr = this.make_async_expr(
CaptureBy::Value, async_node_id, None,
CaptureBy::Value, closure_id, None,
|this| {
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
......@@ -3010,6 +3016,11 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
});
let impl_trait_return_allow = !self.is_in_trait_impl;
let asyncness = match sig.header.asyncness {
IsAsync::Async { return_impl_trait_id, .. } => Some(return_impl_trait_id),
IsAsync::NotAsync => None,
};
self.add_in_band_defs(
&i.generics,
impl_item_def_id,
......@@ -3020,7 +3031,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(),
asyncness,
),
body_id,
)
......@@ -3100,8 +3111,8 @@ fn visit_path_segment(
path_span: Span,
path_segment: &'v PathSegment,
) {
if let Some(ref p) = path_segment.parameters {
if let PathParameters::Parenthesized(..) = **p {
if let Some(ref p) = path_segment.args {
if let GenericArgs::Parenthesized(_) = **p {
return;
}
}
......@@ -3123,8 +3134,11 @@ fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
vec
}
ItemKind::MacroDef(..) => SmallVector::new(),
ItemKind::Fn(ref decl, ..) => {
ItemKind::Fn(ref decl, ref header, ..) => {
let mut ids = SmallVector::one(hir::ItemId { id: i.id });
if let IsAsync::Async { return_impl_trait_id, .. } = header.asyncness {
ids.push(hir::ItemId { id: return_impl_trait_id });
}
self.lower_impl_trait_ids(decl, &mut ids);
ids
},
......@@ -3132,6 +3146,9 @@ fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
let mut ids = SmallVector::one(hir::ItemId { id: i.id });
for item in items {
if let ImplItemKind::Method(ref sig, _) = item.node {
if let IsAsync::Async { return_impl_trait_id, .. } = sig.header.asyncness {
ids.push(hir::ItemId { id: return_impl_trait_id });
}
self.lower_impl_trait_ids(&sig.decl, &mut ids);
}
}
......@@ -3214,7 +3231,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
|this| {
(
// Disallow impl Trait in foreign items
this.lower_fn_decl(fdec, None, false, false),
this.lower_fn_decl(fdec, None, false, None),
this.lower_fn_args_to_names(fdec),
)
},
......@@ -3238,7 +3255,7 @@ fn lower_method_sig(
sig: &MethodSig,
fn_def_id: DefId,
impl_trait_return_allow: bool,
is_async: bool,
is_async: Option<NodeId>,
) -> hir::MethodSig {
hir::MethodSig {
header: self.lower_fn_header(sig.header),
......@@ -3278,7 +3295,7 @@ fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
match a {
IsAsync::Async(_) => hir::IsAsync::Async,
IsAsync::Async { .. } => hir::IsAsync::Async,
IsAsync::NotAsync => hir::IsAsync::NotAsync,
}
}
......@@ -3581,7 +3598,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
ExprKind::Closure(
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
) => {
if let IsAsync::Async(async_closure_node_id) = asyncness {
if let IsAsync::Async { async_closure_node_id, .. } = asyncness {
let outer_decl = FnDecl {
inputs: decl.inputs.clone(),
output: FunctionRetTy::Default(fn_decl_span),
......@@ -3590,7 +3607,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, false);
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
self.with_new_scopes(|this| {
// FIXME(cramertj) allow `async` non-`move` closures with
......@@ -3617,7 +3634,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
Some(&**ty)
} else { None };
let async_body = this.make_async_expr(
capture_clause, async_closure_node_id, async_ret_ty,
capture_clause, closure_id, async_ret_ty,
|this| {
this.with_new_scopes(|this| this.lower_expr(body))
});
......@@ -3633,7 +3650,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
})
} else {
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = self.lower_fn_decl(decl, None, false, false);
let fn_decl = self.lower_fn_decl(decl, None, false, None);
self.with_new_scopes(|this| {
let mut is_generator = false;
......
......@@ -77,6 +77,7 @@ fn visit_async_fn(
&mut self,
id: NodeId,
async_node_id: NodeId,
return_impl_trait_id: NodeId,
name: Name,
span: Span,
visit_fn: impl FnOnce(&mut DefCollector<'a>)
......@@ -86,6 +87,7 @@ fn visit_async_fn(
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| {
this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
let closure_def = this.create_def(async_node_id,
DefPathData::ClosureExpr,
REGULAR_SPACE,
......@@ -120,10 +122,14 @@ fn visit_item(&mut self, i: &'a Item) {
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
return visit::walk_item(self, i);
}
ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..) => {
ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async {
closure_id,
return_impl_trait_id,
}, .. }, ..) => {
return self.visit_async_fn(
i.id,
async_node_id,
closure_id,
return_impl_trait_id,
i.ident.name,
i.span,
|this| visit::walk_item(this, i)
......@@ -228,11 +234,15 @@ 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), .. }, ..
header: FnHeader { asyncness: IsAsync::Async {
closure_id,
return_impl_trait_id,
}, .. }, ..
}, ..) => {
return self.visit_async_fn(
ii.id,
async_node_id,
closure_id,
return_impl_trait_id,
ii.ident.name,
ii.span,
|this| visit::walk_impl_item(this, ii)
......@@ -277,8 +287,8 @@ fn visit_expr(&mut self, expr: &'a Expr) {
// Async closures desugar to closures inside of closures, so
// we must create two defs.
if let IsAsync::Async(async_id) = asyncness {
let async_def = self.create_def(async_id,
if let IsAsync::Async { closure_id, .. } = asyncness {
let async_def = self.create_def(closure_id,
DefPathData::ClosureExpr,
REGULAR_SPACE,
expr.span);
......
......@@ -777,8 +777,8 @@ fn visit_fn(&mut self,
visit::walk_fn_ret_ty(self, &declaration.output);
// 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);
if let IsAsync::Async { closure_id, .. } = asyncness {
let rib_kind = ClosureRibKind(closure_id);
self.ribs[ValueNS].push(Rib::new(rib_kind));
self.label_ribs.push(Rib::new(rib_kind));
}
......@@ -3935,8 +3935,9 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
// resolve the arguments within the proper scopes so that usages of them inside the
// closure are detected as upvars rather than normal closure arg usages.
ExprKind::Closure(
_, IsAsync::Async(inner_closure_id), _, ref fn_decl, ref body, _span) =>
{
_, IsAsync::Async { closure_id: inner_closure_id, .. }, _,
ref fn_decl, ref body, _span,
) => {
let rib_kind = ClosureRibKind(expr.id);
self.ribs[ValueNS].push(Rib::new(rib_kind));
self.label_ribs.push(Rib::new(rib_kind));
......
......@@ -1722,13 +1722,16 @@ pub enum Unsafety {
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum IsAsync {
Async(NodeId),
Async {
closure_id: NodeId,
return_impl_trait_id: NodeId,
},
NotAsync,
}
impl IsAsync {
pub fn is_async(self) -> bool {
if let IsAsync::Async(_) = self {
if let IsAsync::Async { .. } = self {
true
} else {
false
......
......@@ -1726,7 +1726,7 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
"labels on blocks are unstable");
}
}
ast::ExprKind::Closure(_, ast::IsAsync::Async(_), ..) => {
ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
}
ast::ExprKind::Async(..) => {
......
......@@ -100,6 +100,10 @@ fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> {
noop_fold_fn_decl(d, self)
}
fn fold_asyncness(&mut self, a: IsAsync) -> IsAsync {
noop_fold_asyncness(a, self)
}
fn fold_block(&mut self, b: P<Block>) -> P<Block> {
noop_fold_block(b, self)
}
......@@ -669,6 +673,16 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
}
}
pub fn noop_fold_asyncness<T: Folder>(asyncness: IsAsync, fld: &mut T) -> IsAsync {
match asyncness {
IsAsync::Async { closure_id, return_impl_trait_id } => IsAsync::Async {
closure_id: fld.new_id(closure_id),
return_impl_trait_id: fld.new_id(return_impl_trait_id),
},
IsAsync::NotAsync => IsAsync::NotAsync,
}
}
pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
decl.map(|FnDecl {inputs, output, variadic}| FnDecl {
inputs: inputs.move_map(|x| fld.fold_arg(x)),
......@@ -996,10 +1010,7 @@ pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
}
pub fn noop_fold_fn_header<T: Folder>(mut header: FnHeader, folder: &mut T) -> FnHeader {
header.asyncness = match header.asyncness {
IsAsync::Async(node_id) => IsAsync::Async(folder.new_id(node_id)),
IsAsync::NotAsync => IsAsync::NotAsync,
};
header.asyncness = folder.fold_asyncness(header.asyncness);
header
}
......@@ -1249,12 +1260,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
arms.move_map(|x| folder.fold_arm(x)))
}
ExprKind::Closure(capture_clause, asyncness, movability, decl, body, span) => {
let asyncness = match asyncness {
IsAsync::Async(node_id) => IsAsync::Async(folder.new_id(node_id)),
IsAsync::NotAsync => IsAsync::NotAsync,
};
ExprKind::Closure(capture_clause,
asyncness,
folder.fold_asyncness(asyncness),
movability,
folder.fold_fn_decl(decl),
folder.fold_expr(body),
......@@ -1265,7 +1272,11 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
opt_label.map(|label| folder.fold_label(label)))
}
ExprKind::Async(capture_clause, node_id, body) => {
ExprKind::Async(capture_clause, folder.new_id(node_id), folder.fold_block(body))
ExprKind::Async(
capture_clause,
folder.new_id(node_id),
folder.fold_block(body),
)
}
ExprKind::Assign(el, er) => {
ExprKind::Assign(folder.fold_expr(el), folder.fold_expr(er))
......
......@@ -1299,7 +1299,10 @@ 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)
IsAsync::Async {
closure_id: ast::DUMMY_NODE_ID,
return_impl_trait_id: ast::DUMMY_NODE_ID,
}
} else {
IsAsync::NotAsync
}
......@@ -3279,10 +3282,8 @@ fn parse_lambda_expr(&mut self,
} else {
Movability::Movable
};
let asyncness = if self.span.edition() >= Edition::Edition2018
&& self.eat_keyword(keywords::Async)
{
IsAsync::Async(ast::DUMMY_NODE_ID)
let asyncness = if self.span.edition() >= Edition::Edition2018 {
self.parse_asyncness()
} else {
IsAsync::NotAsync
};
......@@ -6798,7 +6799,10 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
let fn_span = self.prev_span;
let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafety,
IsAsync::Async(ast::DUMMY_NODE_ID),
IsAsync::Async {
closure_id: ast::DUMMY_NODE_ID,
return_impl_trait_id: ast::DUMMY_NODE_ID,
},
respan(fn_span, Constness::NotConst),
Abi::Rust)?;
let prev_span = self.prev_span;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册