Deny async fn
in 2015 edition
Fix style issues and update diagnostic messages Update src/librustc_passes/diagnostics.rs Co-Authored-By: doctorn <me@nathancorbyn.com> Deny nested `async fn` in Rust 2015 edition Deny nested `async fn` in Rust 2015 edition Deny nested `async fn` in Rust 2015 edition
This commit is contained in:
parent
7f19f161f2
commit
8300f51936
22 changed files with 215 additions and 62 deletions
|
@ -2906,7 +2906,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
// `impl Future<Output = T>` here because lower_body
|
// `impl Future<Output = T>` here because lower_body
|
||||||
// only cares about the input argument patterns in the function
|
// only cares about the input argument patterns in the function
|
||||||
// declaration (decl), not the return types.
|
// declaration (decl), not the return types.
|
||||||
let body_id = this.lower_async_body(decl, header.asyncness, body);
|
let body_id = this.lower_async_body(decl, header.asyncness.node, body);
|
||||||
|
|
||||||
let (generics, fn_decl) = this.add_in_band_defs(
|
let (generics, fn_decl) = this.add_in_band_defs(
|
||||||
generics,
|
generics,
|
||||||
|
@ -2916,7 +2916,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
decl,
|
decl,
|
||||||
Some((fn_def_id, idty)),
|
Some((fn_def_id, idty)),
|
||||||
true,
|
true,
|
||||||
header.asyncness.opt_return_id()
|
header.asyncness.node.opt_return_id()
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -3410,14 +3410,14 @@ impl<'a> LoweringContext<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ImplItemKind::Method(ref sig, ref body) => {
|
ImplItemKind::Method(ref sig, ref body) => {
|
||||||
let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness, body);
|
let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body);
|
||||||
let impl_trait_return_allow = !self.is_in_trait_impl;
|
let impl_trait_return_allow = !self.is_in_trait_impl;
|
||||||
let (generics, sig) = self.lower_method_sig(
|
let (generics, sig) = self.lower_method_sig(
|
||||||
&i.generics,
|
&i.generics,
|
||||||
sig,
|
sig,
|
||||||
impl_item_def_id,
|
impl_item_def_id,
|
||||||
impl_trait_return_allow,
|
impl_trait_return_allow,
|
||||||
sig.header.asyncness.opt_return_id(),
|
sig.header.asyncness.node.opt_return_id(),
|
||||||
);
|
);
|
||||||
(generics, hir::ImplItemKind::Method(sig, body_id))
|
(generics, hir::ImplItemKind::Method(sig, body_id))
|
||||||
}
|
}
|
||||||
|
@ -3637,7 +3637,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
|
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
|
||||||
hir::FnHeader {
|
hir::FnHeader {
|
||||||
unsafety: self.lower_unsafety(h.unsafety),
|
unsafety: self.lower_unsafety(h.unsafety),
|
||||||
asyncness: self.lower_asyncness(h.asyncness),
|
asyncness: self.lower_asyncness(h.asyncness.node),
|
||||||
constness: self.lower_constness(h.constness),
|
constness: self.lower_constness(h.constness),
|
||||||
abi: h.abi,
|
abi: h.abi,
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ impl<'a> DefCollector<'a> {
|
||||||
decl: &'a FnDecl,
|
decl: &'a FnDecl,
|
||||||
body: &'a Block,
|
body: &'a Block,
|
||||||
) {
|
) {
|
||||||
let (closure_id, return_impl_trait_id) = match header.asyncness {
|
let (closure_id, return_impl_trait_id) = match header.asyncness.node {
|
||||||
IsAsync::Async {
|
IsAsync::Async {
|
||||||
closure_id,
|
closure_id,
|
||||||
return_impl_trait_id,
|
return_impl_trait_id,
|
||||||
|
@ -129,10 +129,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
}
|
}
|
||||||
ItemKind::Fn(
|
ItemKind::Fn(
|
||||||
ref decl,
|
ref decl,
|
||||||
ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
|
ref header,
|
||||||
ref generics,
|
ref generics,
|
||||||
ref body,
|
ref body,
|
||||||
) => {
|
) if header.asyncness.node.is_async() => {
|
||||||
return self.visit_async_fn(
|
return self.visit_async_fn(
|
||||||
i.id,
|
i.id,
|
||||||
i.ident.name,
|
i.ident.name,
|
||||||
|
@ -242,9 +242,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
||||||
let def_data = match ii.node {
|
let def_data = match ii.node {
|
||||||
ImplItemKind::Method(MethodSig {
|
ImplItemKind::Method(MethodSig {
|
||||||
header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
|
ref header,
|
||||||
ref decl,
|
ref decl,
|
||||||
}, ref body) => {
|
}, ref body) if header.asyncness.node.is_async() => {
|
||||||
return self.visit_async_fn(
|
return self.visit_async_fn(
|
||||||
ii.id,
|
ii.id,
|
||||||
ii.ident.name,
|
ii.ident.name,
|
||||||
|
|
|
@ -463,7 +463,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
self.invalid_visibility(&impl_item.vis, None);
|
self.invalid_visibility(&impl_item.vis, None);
|
||||||
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
|
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||||
self.check_trait_fn_not_const(sig.header.constness);
|
self.check_trait_fn_not_const(sig.header.constness);
|
||||||
self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness);
|
self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,9 +482,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
.note("only trait implementations may be annotated with default").emit();
|
.note("only trait implementations may be annotated with default").emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Fn(_, header, ref generics, _) => {
|
ItemKind::Fn(_, ref header, ref generics, _) => {
|
||||||
// We currently do not permit const generics in `const fn`, as
|
// We currently do not permit const generics in `const fn`, as
|
||||||
// this is tantamount to allowing compile-time dependent typing.
|
// this is tantamount to allowing compile-time dependent typing.
|
||||||
|
self.visit_fn_header(header);
|
||||||
if header.constness.node == Constness::Const {
|
if header.constness.node == Constness::Const {
|
||||||
// Look for const generics and error if we find any.
|
// Look for const generics and error if we find any.
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
|
@ -535,7 +536,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
self.no_questions_in_bounds(bounds, "supertraits", true);
|
self.no_questions_in_bounds(bounds, "supertraits", true);
|
||||||
for trait_item in trait_items {
|
for trait_item in trait_items {
|
||||||
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
|
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_async(trait_item.span, sig.header.asyncness.node);
|
||||||
self.check_trait_fn_not_const(sig.header.constness);
|
self.check_trait_fn_not_const(sig.header.constness);
|
||||||
if block.is_none() {
|
if block.is_none() {
|
||||||
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||||
|
@ -702,6 +703,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
.span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
|
.span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
|
||||||
the relevant `fold_*()` method in `PlaceholderExpander`?");
|
the relevant `fold_*()` method in `PlaceholderExpander`?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_fn_header(&mut self, header: &'a FnHeader) {
|
||||||
|
if header.asyncness.node.is_async() && self.session.rust_2015() {
|
||||||
|
struct_span_err!(self.session, header.asyncness.span, E0670,
|
||||||
|
"`async fn` is not permitted in the 2015 edition").emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) {
|
pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) {
|
||||||
|
|
|
@ -310,6 +310,18 @@ loop {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
|
E0670: r##"
|
||||||
|
Rust 2015 does not permit the use of `async fn`.
|
||||||
|
|
||||||
|
Example of erroneous code:
|
||||||
|
|
||||||
|
```compile_fail,E0670
|
||||||
|
async fn foo() {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Switch to the Rust 2018 edition to use `async fn`.
|
||||||
"##
|
"##
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -806,9 +806,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
||||||
debug!("(resolving function) entering function");
|
debug!("(resolving function) entering function");
|
||||||
let (rib_kind, asyncness) = match function_kind {
|
let (rib_kind, asyncness) = match function_kind {
|
||||||
FnKind::ItemFn(_, ref header, ..) =>
|
FnKind::ItemFn(_, ref header, ..) =>
|
||||||
(ItemRibKind, header.asyncness),
|
(ItemRibKind, header.asyncness.node),
|
||||||
FnKind::Method(_, ref sig, _, _) =>
|
FnKind::Method(_, ref sig, _, _) =>
|
||||||
(TraitOrImplItemRibKind, sig.header.asyncness),
|
(TraitOrImplItemRibKind, sig.header.asyncness.node),
|
||||||
FnKind::Closure(_) =>
|
FnKind::Closure(_) =>
|
||||||
// Async closures aren't resolved through `visit_fn`-- they're
|
// Async closures aren't resolved through `visit_fn`-- they're
|
||||||
// processed separately
|
// processed separately
|
||||||
|
|
|
@ -378,7 +378,7 @@ impl Sig for ast::Item {
|
||||||
if header.constness.node == ast::Constness::Const {
|
if header.constness.node == ast::Constness::Const {
|
||||||
text.push_str("const ");
|
text.push_str("const ");
|
||||||
}
|
}
|
||||||
if header.asyncness.is_async() {
|
if header.asyncness.node.is_async() {
|
||||||
text.push_str("async ");
|
text.push_str("async ");
|
||||||
}
|
}
|
||||||
if header.unsafety == ast::Unsafety::Unsafe {
|
if header.unsafety == ast::Unsafety::Unsafe {
|
||||||
|
@ -936,7 +936,7 @@ fn make_method_signature(
|
||||||
if m.header.constness.node == ast::Constness::Const {
|
if m.header.constness.node == ast::Constness::Const {
|
||||||
text.push_str("const ");
|
text.push_str("const ");
|
||||||
}
|
}
|
||||||
if m.header.asyncness.is_async() {
|
if m.header.asyncness.node.is_async() {
|
||||||
text.push_str("async ");
|
text.push_str("async ");
|
||||||
}
|
}
|
||||||
if m.header.unsafety == ast::Unsafety::Unsafe {
|
if m.header.unsafety == ast::Unsafety::Unsafe {
|
||||||
|
|
|
@ -2216,7 +2216,7 @@ impl Item {
|
||||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct FnHeader {
|
pub struct FnHeader {
|
||||||
pub unsafety: Unsafety,
|
pub unsafety: Unsafety,
|
||||||
pub asyncness: IsAsync,
|
pub asyncness: Spanned<IsAsync>,
|
||||||
pub constness: Spanned<Constness>,
|
pub constness: Spanned<Constness>,
|
||||||
pub abi: Abi,
|
pub abi: Abi,
|
||||||
}
|
}
|
||||||
|
@ -2225,7 +2225,7 @@ impl Default for FnHeader {
|
||||||
fn default() -> FnHeader {
|
fn default() -> FnHeader {
|
||||||
FnHeader {
|
FnHeader {
|
||||||
unsafety: Unsafety::Normal,
|
unsafety: Unsafety::Normal,
|
||||||
asyncness: IsAsync::NotAsync,
|
asyncness: dummy_spanned(IsAsync::NotAsync),
|
||||||
constness: dummy_spanned(Constness::NotConst),
|
constness: dummy_spanned(Constness::NotConst),
|
||||||
abi: Abi::Rust,
|
abi: Abi::Rust,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1017,7 +1017,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)),
|
ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)),
|
||||||
ast::FnHeader {
|
ast::FnHeader {
|
||||||
unsafety: ast::Unsafety::Normal,
|
unsafety: ast::Unsafety::Normal,
|
||||||
asyncness: ast::IsAsync::NotAsync,
|
asyncness: dummy_spanned(ast::IsAsync::NotAsync),
|
||||||
constness: dummy_spanned(ast::Constness::NotConst),
|
constness: dummy_spanned(ast::Constness::NotConst),
|
||||||
abi: Abi::Rust,
|
abi: Abi::Rust,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1894,7 +1894,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
match fn_kind {
|
match fn_kind {
|
||||||
FnKind::ItemFn(_, header, _, _) => {
|
FnKind::ItemFn(_, header, _, _) => {
|
||||||
// Check for const fn and async fn declarations.
|
// Check for const fn and async fn declarations.
|
||||||
if header.asyncness.is_async() {
|
if header.asyncness.node.is_async() {
|
||||||
gate_feature_post!(&self, async_await, span, "async fn is unstable");
|
gate_feature_post!(&self, async_await, span, "async fn is unstable");
|
||||||
}
|
}
|
||||||
// Stability of const fn methods are covered in
|
// Stability of const fn methods are covered in
|
||||||
|
|
|
@ -926,7 +926,7 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
|
||||||
|
|
||||||
pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
|
pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
|
||||||
let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header;
|
let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header;
|
||||||
vis.visit_asyncness(asyncness);
|
vis.visit_asyncness(&mut asyncness.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_mod<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) {
|
pub fn noop_visit_mod<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) {
|
||||||
|
|
|
@ -5001,6 +5001,11 @@ impl<'a> Parser<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_async_fn(&mut self) -> bool {
|
||||||
|
self.token.is_keyword(keywords::Async) &&
|
||||||
|
self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
|
||||||
|
}
|
||||||
|
|
||||||
fn is_do_catch_block(&mut self) -> bool {
|
fn is_do_catch_block(&mut self) -> bool {
|
||||||
self.token.is_keyword(keywords::Do) &&
|
self.token.is_keyword(keywords::Do) &&
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
|
self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
|
||||||
|
@ -5133,7 +5138,8 @@ impl<'a> Parser<'a> {
|
||||||
!self.is_union_item() &&
|
!self.is_union_item() &&
|
||||||
!self.is_crate_vis() &&
|
!self.is_crate_vis() &&
|
||||||
!self.is_existential_type_decl() &&
|
!self.is_existential_type_decl() &&
|
||||||
!self.is_auto_trait_item() {
|
!self.is_auto_trait_item() &&
|
||||||
|
!self.is_async_fn() {
|
||||||
let pth = self.parse_path(PathStyle::Expr)?;
|
let pth = self.parse_path(PathStyle::Expr)?;
|
||||||
|
|
||||||
if !self.eat(&token::Not) {
|
if !self.eat(&token::Not) {
|
||||||
|
@ -6346,7 +6352,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses an item-position function declaration.
|
/// Parses an item-position function declaration.
|
||||||
fn parse_item_fn(&mut self,
|
fn parse_item_fn(&mut self,
|
||||||
unsafety: Unsafety,
|
unsafety: Unsafety,
|
||||||
asyncness: IsAsync,
|
asyncness: Spanned<IsAsync>,
|
||||||
constness: Spanned<Constness>,
|
constness: Spanned<Constness>,
|
||||||
abi: Abi)
|
abi: Abi)
|
||||||
-> PResult<'a, ItemInfo> {
|
-> PResult<'a, ItemInfo> {
|
||||||
|
@ -6378,7 +6384,7 @@ impl<'a> Parser<'a> {
|
||||||
-> PResult<'a, (
|
-> PResult<'a, (
|
||||||
Spanned<Constness>,
|
Spanned<Constness>,
|
||||||
Unsafety,
|
Unsafety,
|
||||||
IsAsync,
|
Spanned<IsAsync>,
|
||||||
Abi
|
Abi
|
||||||
)>
|
)>
|
||||||
{
|
{
|
||||||
|
@ -6386,6 +6392,7 @@ impl<'a> Parser<'a> {
|
||||||
let const_span = self.prev_span;
|
let const_span = self.prev_span;
|
||||||
let unsafety = self.parse_unsafety();
|
let unsafety = self.parse_unsafety();
|
||||||
let asyncness = self.parse_asyncness();
|
let asyncness = self.parse_asyncness();
|
||||||
|
let asyncness = respan(self.prev_span, asyncness);
|
||||||
let (constness, unsafety, abi) = if is_const_fn {
|
let (constness, unsafety, abi) = if is_const_fn {
|
||||||
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
|
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
|
||||||
} else {
|
} else {
|
||||||
|
@ -7796,7 +7803,7 @@ impl<'a> Parser<'a> {
|
||||||
let abi = opt_abi.unwrap_or(Abi::C);
|
let abi = opt_abi.unwrap_or(Abi::C);
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_fn(Unsafety::Normal,
|
self.parse_item_fn(Unsafety::Normal,
|
||||||
IsAsync::NotAsync,
|
respan(fn_span, IsAsync::NotAsync),
|
||||||
respan(fn_span, Constness::NotConst),
|
respan(fn_span, Constness::NotConst),
|
||||||
abi)?;
|
abi)?;
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
|
@ -7840,7 +7847,7 @@ impl<'a> Parser<'a> {
|
||||||
self.bump();
|
self.bump();
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_fn(unsafety,
|
self.parse_item_fn(unsafety,
|
||||||
IsAsync::NotAsync,
|
respan(const_span, IsAsync::NotAsync),
|
||||||
respan(const_span, Constness::Const),
|
respan(const_span, Constness::Const),
|
||||||
Abi::Rust)?;
|
Abi::Rust)?;
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
|
@ -7888,14 +7895,15 @@ impl<'a> Parser<'a> {
|
||||||
// ASYNC FUNCTION ITEM
|
// ASYNC FUNCTION ITEM
|
||||||
let unsafety = self.parse_unsafety();
|
let unsafety = self.parse_unsafety();
|
||||||
self.expect_keyword(keywords::Async)?;
|
self.expect_keyword(keywords::Async)?;
|
||||||
|
let async_span = self.prev_span;
|
||||||
self.expect_keyword(keywords::Fn)?;
|
self.expect_keyword(keywords::Fn)?;
|
||||||
let fn_span = self.prev_span;
|
let fn_span = self.prev_span;
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_fn(unsafety,
|
self.parse_item_fn(unsafety,
|
||||||
IsAsync::Async {
|
respan(async_span, IsAsync::Async {
|
||||||
closure_id: ast::DUMMY_NODE_ID,
|
closure_id: ast::DUMMY_NODE_ID,
|
||||||
return_impl_trait_id: ast::DUMMY_NODE_ID,
|
return_impl_trait_id: ast::DUMMY_NODE_ID,
|
||||||
},
|
}),
|
||||||
respan(fn_span, Constness::NotConst),
|
respan(fn_span, Constness::NotConst),
|
||||||
Abi::Rust)?;
|
Abi::Rust)?;
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
|
@ -7904,6 +7912,13 @@ impl<'a> Parser<'a> {
|
||||||
item_,
|
item_,
|
||||||
visibility,
|
visibility,
|
||||||
maybe_append(attrs, extra_attrs));
|
maybe_append(attrs, extra_attrs));
|
||||||
|
if self.span.rust_2015() {
|
||||||
|
self.diagnostic().struct_span_err_with_code(
|
||||||
|
async_span,
|
||||||
|
"`async fn` is not permitted in the 2015 edition",
|
||||||
|
DiagnosticId::Error("E0670".into())
|
||||||
|
).emit();
|
||||||
|
}
|
||||||
return Ok(Some(item));
|
return Ok(Some(item));
|
||||||
}
|
}
|
||||||
if self.check_keyword(keywords::Unsafe) &&
|
if self.check_keyword(keywords::Unsafe) &&
|
||||||
|
@ -7951,7 +7966,7 @@ impl<'a> Parser<'a> {
|
||||||
let fn_span = self.prev_span;
|
let fn_span = self.prev_span;
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_fn(Unsafety::Normal,
|
self.parse_item_fn(Unsafety::Normal,
|
||||||
IsAsync::NotAsync,
|
respan(fn_span, IsAsync::NotAsync),
|
||||||
respan(fn_span, Constness::NotConst),
|
respan(fn_span, Constness::NotConst),
|
||||||
Abi::Rust)?;
|
Abi::Rust)?;
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
|
@ -7977,7 +7992,7 @@ impl<'a> Parser<'a> {
|
||||||
let fn_span = self.prev_span;
|
let fn_span = self.prev_span;
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_fn(Unsafety::Unsafe,
|
self.parse_item_fn(Unsafety::Unsafe,
|
||||||
IsAsync::NotAsync,
|
respan(fn_span, IsAsync::NotAsync),
|
||||||
respan(fn_span, Constness::NotConst),
|
respan(fn_span, Constness::NotConst),
|
||||||
abi)?;
|
abi)?;
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
|
@ -8244,7 +8259,8 @@ impl<'a> Parser<'a> {
|
||||||
lo: Span,
|
lo: Span,
|
||||||
visibility: Visibility
|
visibility: Visibility
|
||||||
) -> PResult<'a, Option<P<Item>>> {
|
) -> PResult<'a, Option<P<Item>>> {
|
||||||
if macros_allowed && self.token.is_path_start() {
|
if macros_allowed && self.token.is_path_start() &&
|
||||||
|
!(self.is_async_fn() && self.span.rust_2015()) {
|
||||||
// MACRO INVOCATION ITEM
|
// MACRO INVOCATION ITEM
|
||||||
|
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
|
@ -8299,7 +8315,8 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
|
fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
|
||||||
at_end: &mut bool) -> PResult<'a, Option<Mac>>
|
at_end: &mut bool) -> PResult<'a, Option<Mac>>
|
||||||
{
|
{
|
||||||
if self.token.is_path_start() {
|
if self.token.is_path_start() &&
|
||||||
|
!(self.is_async_fn() && self.span.rust_2015()) {
|
||||||
let prev_span = self.prev_span;
|
let prev_span = self.prev_span;
|
||||||
let lo = self.span;
|
let lo = self.span;
|
||||||
let pth = self.parse_path(PathStyle::Mod)?;
|
let pth = self.parse_path(PathStyle::Mod)?;
|
||||||
|
|
|
@ -3195,7 +3195,7 @@ impl<'a> State<'a> {
|
||||||
ast::Constness::Const => self.word_nbsp("const")?
|
ast::Constness::Const => self.word_nbsp("const")?
|
||||||
}
|
}
|
||||||
|
|
||||||
self.print_asyncness(header.asyncness)?;
|
self.print_asyncness(header.asyncness.node)?;
|
||||||
self.print_unsafety(header.unsafety)?;
|
self.print_unsafety(header.unsafety)?;
|
||||||
|
|
||||||
if header.abi != Abi::Rust {
|
if header.abi != Abi::Rust {
|
||||||
|
@ -3247,7 +3247,7 @@ mod tests {
|
||||||
ast::FnHeader {
|
ast::FnHeader {
|
||||||
unsafety: ast::Unsafety::Normal,
|
unsafety: ast::Unsafety::Normal,
|
||||||
constness: source_map::dummy_spanned(ast::Constness::NotConst),
|
constness: source_map::dummy_spanned(ast::Constness::NotConst),
|
||||||
asyncness: ast::IsAsync::NotAsync,
|
asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync),
|
||||||
abi: Abi::Rust,
|
abi: Abi::Rust,
|
||||||
},
|
},
|
||||||
abba_ident,
|
abba_ident,
|
||||||
|
|
|
@ -22,7 +22,7 @@ use syntax_pos::Span;
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum FnKind<'a> {
|
pub enum FnKind<'a> {
|
||||||
/// fn foo() or extern "Abi" fn foo()
|
/// fn foo() or extern "Abi" fn foo()
|
||||||
ItemFn(Ident, FnHeader, &'a Visibility, &'a Block),
|
ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
|
||||||
|
|
||||||
/// fn foo(&self)
|
/// fn foo(&self)
|
||||||
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
|
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
|
||||||
|
@ -149,6 +149,9 @@ pub trait Visitor<'ast>: Sized {
|
||||||
fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) {
|
fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) {
|
||||||
walk_fn_ret_ty(self, ret_ty)
|
walk_fn_ret_ty(self, ret_ty)
|
||||||
}
|
}
|
||||||
|
fn visit_fn_header(&mut self, _header: &'ast FnHeader) {
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -225,8 +228,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
||||||
visitor.visit_ty(typ);
|
visitor.visit_ty(typ);
|
||||||
visitor.visit_expr(expr);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
ItemKind::Fn(ref declaration, header, ref generics, ref body) => {
|
ItemKind::Fn(ref declaration, ref header, ref generics, ref body) => {
|
||||||
visitor.visit_generics(generics);
|
visitor.visit_generics(generics);
|
||||||
|
visitor.visit_fn_header(header);
|
||||||
visitor.visit_fn(FnKind::ItemFn(item.ident, header,
|
visitor.visit_fn(FnKind::ItemFn(item.ident, header,
|
||||||
&item.vis, body),
|
&item.vis, body),
|
||||||
declaration,
|
declaration,
|
||||||
|
@ -539,11 +543,13 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
|
||||||
where V: Visitor<'a>,
|
where V: Visitor<'a>,
|
||||||
{
|
{
|
||||||
match kind {
|
match kind {
|
||||||
FnKind::ItemFn(_, _, _, body) => {
|
FnKind::ItemFn(_, header, _, body) => {
|
||||||
|
visitor.visit_fn_header(header);
|
||||||
walk_fn_decl(visitor, declaration);
|
walk_fn_decl(visitor, declaration);
|
||||||
visitor.visit_block(body);
|
visitor.visit_block(body);
|
||||||
}
|
}
|
||||||
FnKind::Method(_, _, _, body) => {
|
FnKind::Method(_, sig, _, body) => {
|
||||||
|
visitor.visit_fn_header(&sig.header);
|
||||||
walk_fn_decl(visitor, declaration);
|
walk_fn_decl(visitor, declaration);
|
||||||
visitor.visit_block(body);
|
visitor.visit_block(body);
|
||||||
}
|
}
|
||||||
|
@ -564,6 +570,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai
|
||||||
walk_list!(visitor, visit_expr, default);
|
walk_list!(visitor, visit_expr, default);
|
||||||
}
|
}
|
||||||
TraitItemKind::Method(ref sig, None) => {
|
TraitItemKind::Method(ref sig, None) => {
|
||||||
|
visitor.visit_fn_header(&sig.header);
|
||||||
walk_fn_decl(visitor, &sig.decl);
|
walk_fn_decl(visitor, &sig.decl);
|
||||||
}
|
}
|
||||||
TraitItemKind::Method(ref sig, Some(ref body)) => {
|
TraitItemKind::Method(ref sig, Some(ref body)) => {
|
||||||
|
|
|
@ -257,7 +257,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
|
||||||
);
|
);
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if header.asyncness.is_async() {
|
if header.asyncness.node.is_async() {
|
||||||
sd.span_err(
|
sd.span_err(
|
||||||
i.span,
|
i.span,
|
||||||
"async functions cannot be used for tests"
|
"async functions cannot be used for tests"
|
||||||
|
|
34
src/test/ui/editions/edition-deny-async-fns-2015.rs
Normal file
34
src/test/ui/editions/edition-deny-async-fns-2015.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// edition:2015
|
||||||
|
|
||||||
|
#![feature(futures_api, async_await)]
|
||||||
|
|
||||||
|
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
|
||||||
|
fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
|
||||||
|
async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo {}
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
//~^ ERROR trait fns cannot be declared `async`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
macro_rules! accept_item { ($x:item) => {} }
|
||||||
|
|
||||||
|
accept_item! {
|
||||||
|
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
}
|
||||||
|
|
||||||
|
let inside_closure = || {
|
||||||
|
async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
};
|
||||||
|
}
|
58
src/test/ui/editions/edition-deny-async-fns-2015.stderr
Normal file
58
src/test/ui/editions/edition-deny-async-fns-2015.stderr
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:5:1
|
||||||
|
|
|
||||||
|
LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:7:12
|
||||||
|
|
|
||||||
|
LL | fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:10:5
|
||||||
|
|
|
||||||
|
LL | async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:9:1
|
||||||
|
|
|
||||||
|
LL | async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:32:9
|
||||||
|
|
|
||||||
|
LL | async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:28:9
|
||||||
|
|
|
||||||
|
LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:16:5
|
||||||
|
|
|
||||||
|
LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error[E0706]: trait fns cannot be declared `async`
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:20:5
|
||||||
|
|
|
||||||
|
LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/edition-deny-async-fns-2015.rs:20:5
|
||||||
|
|
|
||||||
|
LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
Some errors occurred: E0670, E0706.
|
||||||
|
For more information about an error, try `rustc --explain E0670`.
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
#![feature(futures_api)]
|
#![feature(futures_api)]
|
||||||
|
|
||||||
async fn foo() {} //~ ERROR async fn is unstable
|
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
//~^ ERROR async fn is unstable
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
|
let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
|
error[E0670]: `async fn` is not permitted in the 2015 edition
|
||||||
|
--> $DIR/feature-gate-async-await-2015-edition.rs:5:1
|
||||||
|
|
|
||||||
|
LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
error[E0422]: cannot find struct, variant or union type `async` in this scope
|
error[E0422]: cannot find struct, variant or union type `async` in this scope
|
||||||
--> $DIR/feature-gate-async-await-2015-edition.rs:8:13
|
--> $DIR/feature-gate-async-await-2015-edition.rs:9:13
|
||||||
|
|
|
|
||||||
LL | let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
|
LL | let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
|
||||||
| ^^^^^ not found in this scope
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `async` in this scope
|
error[E0425]: cannot find value `async` in this scope
|
||||||
--> $DIR/feature-gate-async-await-2015-edition.rs:9:13
|
--> $DIR/feature-gate-async-await-2015-edition.rs:10:13
|
||||||
|
|
|
|
||||||
LL | let _ = async || { true }; //~ ERROR cannot find value `async` in this scope
|
LL | let _ = async || { true }; //~ ERROR cannot find value `async` in this scope
|
||||||
| ^^^^^ not found in this scope
|
| ^^^^^ not found in this scope
|
||||||
|
@ -13,12 +19,12 @@ LL | let _ = async || { true }; //~ ERROR cannot find value `async` in this
|
||||||
error[E0658]: async fn is unstable (see issue #50547)
|
error[E0658]: async fn is unstable (see issue #50547)
|
||||||
--> $DIR/feature-gate-async-await-2015-edition.rs:5:1
|
--> $DIR/feature-gate-async-await-2015-edition.rs:5:1
|
||||||
|
|
|
|
||||||
LL | async fn foo() {} //~ ERROR async fn is unstable
|
LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: add #![feature(async_await)] to the crate attributes to enable
|
= help: add #![feature(async_await)] to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
Some errors occurred: E0422, E0425, E0658.
|
Some errors occurred: E0422, E0425, E0658, E0670.
|
||||||
For more information about an error, try `rustc --explain E0422`.
|
For more information about an error, try `rustc --explain E0422`.
|
||||||
|
|
11
src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
Normal file
11
src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// edition:2018
|
||||||
|
// Test that impl trait does not allow creating recursive types that are
|
||||||
|
// otherwise forbidden when using `async` and `await`.
|
||||||
|
|
||||||
|
#![feature(await_macro, async_await, futures_api, generators)]
|
||||||
|
|
||||||
|
async fn recursive_async_function() -> () { //~ ERROR
|
||||||
|
await!(recursive_async_function());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0720]: opaque type expands to a recursive type
|
||||||
|
--> $DIR/recursive-async-impl-trait-type.rs:7:40
|
||||||
|
|
|
||||||
|
LL | async fn recursive_async_function() -> () { //~ ERROR
|
||||||
|
| ^^ expands to self-referential type
|
||||||
|
|
|
||||||
|
= note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0720`.
|
|
@ -1,7 +1,7 @@
|
||||||
// Test that impl trait does not allow creating recursive types that are
|
// Test that impl trait does not allow creating recursive types that are
|
||||||
// otherwise forbidden.
|
// otherwise forbidden.
|
||||||
|
|
||||||
#![feature(await_macro, async_await, futures_api, generators)]
|
#![feature(futures_api, generators)]
|
||||||
|
|
||||||
fn option(i: i32) -> impl Sized { //~ ERROR
|
fn option(i: i32) -> impl Sized { //~ ERROR
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
|
@ -62,10 +62,6 @@ fn generator_hold() -> impl Sized { //~ ERROR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn recursive_async_function() -> () { //~ ERROR
|
|
||||||
await!(recursive_async_function());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_fn_ptr() -> impl Sized { // OK, error already reported
|
fn use_fn_ptr() -> impl Sized { // OK, error already reported
|
||||||
fn_ptr()
|
fn_ptr()
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,15 +95,7 @@ LL | fn generator_hold() -> impl Sized { //~ ERROR
|
||||||
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]`
|
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]`
|
||||||
|
|
||||||
error[E0720]: opaque type expands to a recursive type
|
error[E0720]: opaque type expands to a recursive type
|
||||||
--> $DIR/recursive-impl-trait-type.rs:65:40
|
--> $DIR/recursive-impl-trait-type.rs:69:26
|
||||||
|
|
|
||||||
LL | async fn recursive_async_function() -> () { //~ ERROR
|
|
||||||
| ^^ expands to self-referential type
|
|
||||||
|
|
|
||||||
= note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-impl-trait-type.rs:65:43: 67:2 {impl std::future::Future, ()}]>`
|
|
||||||
|
|
||||||
error[E0720]: opaque type expands to a recursive type
|
|
||||||
--> $DIR/recursive-impl-trait-type.rs:73:26
|
|
||||||
|
|
|
|
||||||
LL | fn mutual_recursion() -> impl Sync { //~ ERROR
|
LL | fn mutual_recursion() -> impl Sync { //~ ERROR
|
||||||
| ^^^^^^^^^ expands to self-referential type
|
| ^^^^^^^^^ expands to self-referential type
|
||||||
|
@ -111,13 +103,13 @@ LL | fn mutual_recursion() -> impl Sync { //~ ERROR
|
||||||
= note: type resolves to itself
|
= note: type resolves to itself
|
||||||
|
|
||||||
error[E0720]: opaque type expands to a recursive type
|
error[E0720]: opaque type expands to a recursive type
|
||||||
--> $DIR/recursive-impl-trait-type.rs:77:28
|
--> $DIR/recursive-impl-trait-type.rs:73:28
|
||||||
|
|
|
|
||||||
LL | fn mutual_recursion_b() -> impl Sized { //~ ERROR
|
LL | fn mutual_recursion_b() -> impl Sized { //~ ERROR
|
||||||
| ^^^^^^^^^^ expands to self-referential type
|
| ^^^^^^^^^^ expands to self-referential type
|
||||||
|
|
|
|
||||||
= note: type resolves to itself
|
= note: type resolves to itself
|
||||||
|
|
||||||
error: aborting due to 15 previous errors
|
error: aborting due to 14 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0720`.
|
For more information about this error, try `rustc --explain E0720`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue