diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-01-30 13:02:06 +0100 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-02-13 10:39:24 +0100 |
| commit | a833be21626890de406e12f2561d2ffbda4aadb4 (patch) | |
| tree | bd75ba7b37902e0ba9d09e775bdd413f9c868201 | |
| parent | 36a17e4067d2e67223cd9a172476ee5503d6b44b (diff) | |
| download | rust-a833be21626890de406e12f2561d2ffbda4aadb4.tar.gz rust-a833be21626890de406e12f2561d2ffbda4aadb4.zip | |
parser: fuse free `fn` parsing together.
28 files changed, 181 insertions, 185 deletions
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index e0217de1d3b..0bc6179dabf 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -1089,6 +1089,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_c_varadic_type(fk); + // Functions cannot both be `const async` + if let Some(FnHeader { + constness: Const::Yes(cspan), + asyncness: Async::Yes { span: aspan, .. }, + .. + }) = fk.header() + { + self.err_handler() + .struct_span_err(span, "functions cannot be both `const` and `async`") + .span_label(*cspan, "`const` because of this") + .span_label(*aspan, "`async` because of this") + .emit(); + } + // Functions without bodies cannot have patterns. if let FnKind::Fn(ctxt, _, sig, _, None) = fk { Self::check_decl_no_pat(&sig.decl, |span, mut_ident| { diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index cfab54925b1..0b21de4d78b 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -496,6 +496,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let Some(header) = fn_kind.header() { // Stability of const fn methods are covered in `visit_assoc_item` below. self.check_extern(header.ext); + + if let (ast::Const::Yes(_), ast::Extern::Implicit) + | (ast::Const::Yes(_), ast::Extern::Explicit(_)) = (header.constness, header.ext) + { + gate_feature_post!( + &self, + const_extern_fn, + span, + "`const extern fn` definitions are unstable" + ); + } } if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() { @@ -595,7 +606,6 @@ pub fn check_crate( gate_all!(async_closure, "async closures are unstable"); gate_all!(generators, "yield syntax is experimental"); gate_all!(or_patterns, "or-patterns syntax is experimental"); - gate_all!(const_extern_fn, "`const extern fn` definitions are unstable"); gate_all!(raw_ref_op, "raw address of syntax is experimental"); gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental"); gate_all!(const_trait_impl, "const trait impls are experimental"); diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d2bcf31cb05..906b82f746b 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -11,7 +11,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::BytePos; use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind}; -use syntax::ast::{Async, Const, Defaultness, Extern, IsAuto, PathSegment, StrLit, Unsafe}; +use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, StrLit, Unsafe}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind}; @@ -96,53 +96,30 @@ impl<'a> Parser<'a> { return Ok(Some(item)); } + if self.is_fn_front_matter() { + // FUNCTION ITEM + return self.parse_item_fn(lo, vis, attrs); + } + if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { + // EXTERN CRATE return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); } - + // EXTERN BLOCK let abi = self.parse_abi(); - - if self.eat_keyword(kw::Fn) { - // EXTERN FUNCTION ITEM - let header = FnHeader { - unsafety: Unsafe::No, - asyncness: Async::No, - constness: Const::No, - ext: Extern::from_abi(abi), - }; - return self.parse_item_fn(lo, vis, attrs, header); - } else if self.check(&token::OpenDelim(token::Brace)) { - return Ok(Some(self.parse_item_foreign_mod(lo, abi, vis, attrs)?)); - } - - self.unexpected()?; + return Ok(Some(self.parse_item_foreign_mod(lo, abi, vis, attrs)?)); } if self.is_static_global() { - self.bump(); // STATIC ITEM + self.bump(); let m = self.parse_mutability(); let info = self.parse_item_const(Some(m))?; return self.mk_item_with_info(attrs, lo, vis, info); } - let constness = self.parse_constness(); - if let Const::Yes(const_span) = constness { - if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) { - // CONST FUNCTION ITEM - let unsafety = self.parse_unsafety(); - - if self.check_keyword(kw::Extern) { - self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span)); - } - let ext = self.parse_extern()?; - self.expect_keyword(kw::Fn)?; - - let header = FnHeader { unsafety, asyncness: Async::No, constness, ext }; - return self.parse_item_fn(lo, vis, attrs, header); - } - + if let Const::Yes(const_span) = self.parse_constness() { // CONST ITEM if self.eat_keyword(kw::Mut) { let prev_span = self.prev_span; @@ -161,21 +138,6 @@ impl<'a> Parser<'a> { return self.mk_item_with_info(attrs, lo, vis, info); } - // Parses `async unsafe? fn`. - if self.check_keyword(kw::Async) { - let async_span = self.token.span; - if self.is_keyword_ahead(1, &[kw::Fn]) || self.is_keyword_ahead(2, &[kw::Fn]) { - // ASYNC FUNCTION ITEM - let asyncness = self.parse_asyncness(); // `async` - let unsafety = self.parse_unsafety(); // `unsafe`? - self.expect_keyword(kw::Fn)?; // `fn` - self.ban_async_in_2015(async_span); - let header = - FnHeader { unsafety, asyncness, constness: Const::No, ext: Extern::None }; - return self.parse_item_fn(lo, vis, attrs, header); - } - } - if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) { // UNSAFE TRAIT ITEM let unsafety = self.parse_unsafety(); @@ -195,26 +157,6 @@ impl<'a> Parser<'a> { return self.mk_item_with_info(attrs, lo, vis, info); } - if self.check_keyword(kw::Fn) { - // FUNCTION ITEM - self.bump(); - let header = FnHeader::default(); - return self.parse_item_fn(lo, vis, attrs, header); - } - - if self.check_keyword(kw::Unsafe) - && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) - { - // UNSAFE FUNCTION ITEM - let unsafety = self.parse_unsafety(); - // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic. - self.check(&token::OpenDelim(token::Brace)); - let ext = self.parse_extern()?; - self.expect_keyword(kw::Fn)?; - let header = FnHeader { unsafety, asyncness: Async::No, constness: Const::No, ext }; - return self.parse_item_fn(lo, vis, attrs, header); - } - if self.eat_keyword(kw::Mod) { // MODULE ITEM let info = self.parse_item_mod(&attrs[..])?; @@ -1662,9 +1604,9 @@ impl<'a> Parser<'a> { lo: Span, vis: Visibility, mut attrs: Vec<Attribute>, - header: FnHeader, ) -> PResult<'a, Option<P<Item>>> { let cfg = ParamCfg { is_name_required: |_| true }; + let header = self.parse_fn_front_matter()?; let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; let body = self.parse_fn_body(&mut false, &mut attrs)?; let kind = ItemKind::Fn(FnSig { decl, header }, generics, body); @@ -1730,27 +1672,24 @@ impl<'a> Parser<'a> { Ok(body) } - /// Is the current token unambiguously the start of an `FnHeader`? + /// Is the current token the start of an `FnHeader` / not a valid parse? fn is_fn_front_matter(&mut self) -> bool { // We use an over-approximation here. // `const const`, `fn const` won't parse, but we're not stepping over other syntax either. - // This works for `async fn` and similar as `async async` is an invalid - // parse and `async fn` is never a valid parse on previous editions. - const QUALIFIER: [Symbol; 4] = [kw::Const, kw::Async, kw::Unsafe, kw::Extern]; - - let check_qual_follow = |this: &mut Self, dist| { - this.look_ahead(dist, |t| { - // ...qualified and then `fn`, e.g. `const fn`. - t.is_keyword(kw::Fn) - // Two qualifiers. This is enough. - || QUALIFIER.iter().any(|&kw| t.is_keyword(kw)) - }) - }; + const QUALS: [Symbol; 4] = [kw::Const, kw::Async, kw::Unsafe, kw::Extern]; self.check_keyword(kw::Fn) // Definitely an `fn`. // `$qual fn` or `$qual $qual`: - || QUALIFIER.iter().any(|&kw| self.check_keyword(kw)) && check_qual_follow(self, 1) - // `extern ABI fn` or `extern ABI $qual`; skip 1 for the ABI. - || self.check_keyword(kw::Extern) && check_qual_follow(self, 2) + || QUALS.iter().any(|&kw| self.check_keyword(kw)) + && self.look_ahead(1, |t| { + // ...qualified and then `fn`, e.g. `const fn`. + t.is_keyword(kw::Fn) + // Two qualifiers. This is enough. Due `async` we need to check that it's reserved. + || t.is_non_raw_ident_where(|i| QUALS.contains(&i.name) && i.is_reserved()) + }) + // `extern ABI fn` + || self.check_keyword(kw::Extern) + && self.look_ahead(1, |t| t.can_begin_literal_or_bool()) + && self.look_ahead(2, |t| t.is_keyword(kw::Fn)) } /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs index 3045f147698..862934300e0 100644 --- a/src/libsyntax/token.rs +++ b/src/libsyntax/token.rs @@ -402,12 +402,14 @@ impl Token { /// Returns `true` if the token is any literal, a minus (which can prefix a literal, /// for example a '-42', or one of the boolean idents). + /// + /// Keep this in sync with `Lit::from_token`. pub fn can_begin_literal_or_bool(&self) -> bool { match self.kind { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, - Interpolated(ref nt) => match **nt { - NtLiteral(..) => true, + Interpolated(ref nt) => match &**nt { + NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)), _ => false, }, _ => false, @@ -530,7 +532,7 @@ impl Token { } /// Returns `true` if the token is a non-raw identifier for which `pred` holds. - fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool { + pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool { match self.ident() { Some((id, false)) => pred(id), _ => false, diff --git a/src/libsyntax/util/literal.rs b/src/libsyntax/util/literal.rs index dd06c25b4de..0c611adc06b 100644 --- a/src/libsyntax/util/literal.rs +++ b/src/libsyntax/util/literal.rs @@ -188,6 +188,8 @@ impl Lit { } /// Converts arbitrary token into an AST literal. + /// + /// Keep this in sync with `Token::can_begin_literal_or_bool`. pub fn from_token(token: &Token) -> Result<Lit, LitError> { let lit = match token.kind { token::Ident(name, false) if name.is_bool_lit() => { diff --git a/src/test/ui/async-await/no-async-const.rs b/src/test/ui/async-await/no-async-const.rs index 64322990d0a..963460c1182 100644 --- a/src/test/ui/async-await/no-async-const.rs +++ b/src/test/ui/async-await/no-async-const.rs @@ -2,4 +2,4 @@ // compile-flags: --crate-type lib pub async const fn x() {} -//~^ ERROR expected one of `fn` or `unsafe`, found keyword `const` +//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` diff --git a/src/test/ui/async-await/no-async-const.stderr b/src/test/ui/async-await/no-async-const.stderr index d5b8b344abe..e324a77187a 100644 --- a/src/test/ui/async-await/no-async-const.stderr +++ b/src/test/ui/async-await/no-async-const.stderr @@ -1,8 +1,8 @@ -error: expected one of `fn` or `unsafe`, found keyword `const` +error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const` --> $DIR/no-async-const.rs:4:11 | LL | pub async const fn x() {} - | ^^^^^ expected one of `fn` or `unsafe` + | ^^^^^ expected one of `extern`, `fn`, or `unsafe` error: aborting due to previous error diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs index 55b27bd3fa1..b3c59734e03 100644 --- a/src/test/ui/async-await/no-const-async.rs +++ b/src/test/ui/async-await/no-const-async.rs @@ -2,5 +2,4 @@ // compile-flags: --crate-type lib pub const async fn x() {} -//~^ ERROR expected identifier, found keyword `async` -//~^^ expected `:`, found keyword `fn` +//~^ ERROR functions cannot be both `const` and `async` diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index 62cd5c45d19..f6ae0f1447c 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -1,14 +1,11 @@ -error: expected identifier, found keyword `async` - --> $DIR/no-const-async.rs:4:11 +error: functions cannot be both `const` and `async` + --> $DIR/no-const-async.rs:4:1 | LL | pub const async fn x() {} - | ^^^^^ expected identifier, found keyword + | ^^^^-----^-----^^^^^^^^^^ + | | | + | | `async` because of this + | `const` because of this -error: expected `:`, found keyword `fn` - --> $DIR/no-const-async.rs:4:17 - | -LL | pub const async fn x() {} - | ^^ expected `:` - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/async-await/no-unsafe-async.rs b/src/test/ui/async-await/no-unsafe-async.rs index 1ac1bdffda9..f40154e16f3 100644 --- a/src/test/ui/async-await/no-unsafe-async.rs +++ b/src/test/ui/async-await/no-unsafe-async.rs @@ -8,4 +8,4 @@ impl S { } #[cfg(FALSE)] -unsafe async fn f() {} //~ ERROR expected one of `extern`, `fn`, or `{`, found keyword `async` +unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` diff --git a/src/test/ui/async-await/no-unsafe-async.stderr b/src/test/ui/async-await/no-unsafe-async.stderr index bbeb3427849..2651588d597 100644 --- a/src/test/ui/async-await/no-unsafe-async.stderr +++ b/src/test/ui/async-await/no-unsafe-async.stderr @@ -4,11 +4,11 @@ error: expected one of `extern` or `fn`, found keyword `async` LL | unsafe async fn g() {} | ^^^^^ expected one of `extern` or `fn` -error: expected one of `extern`, `fn`, or `{`, found keyword `async` +error: expected one of `extern` or `fn`, found keyword `async` --> $DIR/no-unsafe-async.rs:11:8 | LL | unsafe async fn f() {} - | ^^^^^ expected one of `extern`, `fn`, or `{` + | ^^^^^ expected one of `extern` or `fn` error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs index d39f2c1fe27..5667d553527 100644 --- a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs +++ b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs @@ -1,12 +1,10 @@ // Check that `const extern fn` and `const unsafe extern fn` are feature-gated. -#[cfg(FALSE)] const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const unsafe extern "C" fn bar2() {} -//~^ ERROR `const extern fn` definitions are unstable -#[cfg(FALSE)] const unsafe extern "Rust" fn bar3() {} -//~^ ERROR `const extern fn` definitions are unstable +const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable +const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable +const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable +const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable +const unsafe extern "C" fn bar2() {} //~ ERROR `const extern fn` definitions are unstable +const unsafe extern "Rust" fn bar3() {} //~ ERROR `const extern fn` definitions are unstable fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr index ed5e0c84a16..bd5940a3fd6 100644 --- a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr +++ b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr @@ -1,53 +1,53 @@ error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:3:15 + --> $DIR/feature-gate-const_extern_fn.rs:3:1 | -LL | #[cfg(FALSE)] const extern fn foo1() {} - | ^^^^^^^^^^^^ +LL | const extern fn foo1() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:4:15 + --> $DIR/feature-gate-const_extern_fn.rs:4:1 | -LL | #[cfg(FALSE)] const extern "C" fn foo2() {} - | ^^^^^^^^^^^^ +LL | const extern "C" fn foo2() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:5:15 + --> $DIR/feature-gate-const_extern_fn.rs:5:1 | -LL | #[cfg(FALSE)] const extern "Rust" fn foo3() {} - | ^^^^^^^^^^^^ +LL | const extern "Rust" fn foo3() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:6:15 + --> $DIR/feature-gate-const_extern_fn.rs:6:1 | -LL | #[cfg(FALSE)] const unsafe extern fn bar1() {} - | ^^^^^^^^^^^^^^^^^^^ +LL | const unsafe extern fn bar1() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:7:15 + --> $DIR/feature-gate-const_extern_fn.rs:7:1 | -LL | #[cfg(FALSE)] const unsafe extern "C" fn bar2() {} - | ^^^^^^^^^^^^^^^^^^^ +LL | const unsafe extern "C" fn bar2() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:9:15 + --> $DIR/feature-gate-const_extern_fn.rs:8:1 | -LL | #[cfg(FALSE)] const unsafe extern "Rust" fn bar3() {} - | ^^^^^^^^^^^^^^^^^^^ +LL | const unsafe extern "Rust" fn bar3() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs index 1886bfccb4e..6f575d055a2 100644 --- a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs +++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs @@ -4,5 +4,4 @@ fn main() {} fn container() { const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } //~^ ERROR expected `fn` - //~| ERROR `const extern fn` definitions are unstable } diff --git a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr index d36b781d292..ec415ec9d02 100644 --- a/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr +++ b/src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr @@ -4,15 +4,5 @@ error: expected `fn`, found `PUT_ANYTHING_YOU_WANT_HERE` LL | const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `fn` -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier.rs:5:5 - | -LL | const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } - | ^^^^^^^^^^^^ - | - = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/label/label_break_value_illegal_uses.rs b/src/test/ui/label/label_break_value_illegal_uses.rs index 81cb1774380..9d4c72410a6 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.rs +++ b/src/test/ui/label/label_break_value_illegal_uses.rs @@ -3,7 +3,7 @@ // These are forbidden occurrences of label-break-value fn labeled_unsafe() { - unsafe 'b: {} //~ ERROR expected one of `extern`, `fn`, or `{` + unsafe 'b: {} //~ ERROR expected `{`, found `'b` } fn labeled_if() { diff --git a/src/test/ui/label/label_break_value_illegal_uses.stderr b/src/test/ui/label/label_break_value_illegal_uses.stderr index 46b53c65b48..fd8850dd8da 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.stderr +++ b/src/test/ui/label/label_break_value_illegal_uses.stderr @@ -1,8 +1,8 @@ -error: expected one of `extern`, `fn`, or `{`, found `'b` +error: expected `{`, found `'b` --> $DIR/label_break_value_illegal_uses.rs:6:12 | LL | unsafe 'b: {} - | ^^ expected one of `extern`, `fn`, or `{` + | ^^ expected `{` error: expected `{`, found `'b` --> $DIR/label_break_value_illegal_uses.rs:10:13 diff --git a/src/test/ui/parser/extern-crate-unexpected-token.rs b/src/test/ui/parser/extern-crate-unexpected-token.rs index 58b2fa1afdf..7687f5e6409 100644 --- a/src/test/ui/parser/extern-crate-unexpected-token.rs +++ b/src/test/ui/parser/extern-crate-unexpected-token.rs @@ -1 +1 @@ -extern crte foo; //~ ERROR expected one of `crate`, `fn`, or `{`, found `crte` +extern crte foo; //~ ERROR expected one of `crate` or `{`, found `crte` diff --git a/src/test/ui/parser/extern-crate-unexpected-token.stderr b/src/test/ui/parser/extern-crate-unexpected-token.stderr index 0e745dc582f..e9d287ac0e9 100644 --- a/src/test/ui/parser/extern-crate-unexpected-token.stderr +++ b/src/test/ui/parser/extern-crate-unexpected-token.stderr @@ -1,8 +1,8 @@ -error: expected one of `crate`, `fn`, or `{`, found `crte` +error: expected one of `crate` or `{`, found `crte` --> $DIR/extern-crate-unexpected-token.rs:1:8 | LL | extern crte foo; - | ^^^^ expected one of `crate`, `fn`, or `{` + | ^^^^ expected one of `crate` or `{` error: aborting due to previous error diff --git a/src/test/ui/parser/extern-expected-fn-or-brace.rs b/src/test/ui/parser/extern-expected-fn-or-brace.rs index 907de0d8f91..1dcea17445e 100644 --- a/src/test/ui/parser/extern-expected-fn-or-brace.rs +++ b/src/test/ui/parser/extern-expected-fn-or-brace.rs @@ -1,4 +1,3 @@ -// Verifies that the expected token errors for `extern crate` are -// raised +// Verifies that the expected token errors for `extern crate` are raised. -extern "C" mod foo; //~ERROR expected one of `fn` or `{`, found keyword `mod` +extern "C" mod foo; //~ERROR expected `{`, found keyword `mod` diff --git a/src/test/ui/parser/extern-expected-fn-or-brace.stderr b/src/test/ui/parser/extern-expected-fn-or-brace.stderr index 0ebe9a0d3ea..258a2c2680a 100644 --- a/src/test/ui/parser/extern-expected-fn-or-brace.stderr +++ b/src/test/ui/parser/extern-expected-fn-or-brace.stderr @@ -1,8 +1,8 @@ -error: expected one of `fn` or `{`, found keyword `mod` - --> $DIR/extern-expected-fn-or-brace.rs:4:12 +error: expected `{`, found keyword `mod` + --> $DIR/extern-expected-fn-or-brace.rs:3:12 | LL | extern "C" mod foo; - | ^^^ expected one of `fn` or `{` + | ^^^ expected `{` error: aborting due to previous error diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs index 98ff2b6d2e8..a05ea277eec 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.rs +++ b/src/test/ui/parser/fn-header-semantic-fail.rs @@ -10,8 +10,8 @@ fn main() { unsafe fn ff2() {} // OK. const fn ff3() {} // OK. extern "C" fn ff4() {} // OK. - const /* async */ unsafe extern "C" fn ff5() {} // OK. - //^ FIXME(Centril): `async` should be legal syntactically, ensure it's illegal semantically. + const async unsafe extern "C" fn ff5() {} // OK. + //~^ ERROR functions cannot be both `const` and `async` trait X { async fn ft1(); //~ ERROR trait fns cannot be declared `async` @@ -21,6 +21,7 @@ fn main() { const async unsafe extern "C" fn ft5(); //~^ ERROR trait fns cannot be declared `async` //~| ERROR trait fns cannot be declared const + //~| ERROR functions cannot be both `const` and `async` } struct Y; @@ -34,6 +35,7 @@ fn main() { //~^ ERROR trait fns cannot be declared `async` //~| ERROR trait fns cannot be declared const //~| ERROR method `ft5` has an incompatible type for trait + //~| ERROR functions cannot be both `const` and `async` } impl Y { @@ -41,7 +43,8 @@ fn main() { unsafe fn fi2() {} // OK. const fn fi3() {} // OK. extern "C" fn fi4() {} // OK. - const async unsafe extern "C" fn fi5() {} // OK. + const async unsafe extern "C" fn fi5() {} + //~^ ERROR functions cannot be both `const` and `async` } extern { @@ -50,5 +53,6 @@ fn main() { const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers const async unsafe extern "C" fn fe5(); //~ ERROR functions in `extern` blocks + //~^ ERROR functions cannot be both `const` and `async` } } diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 1860106b255..a9e4a183347 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -1,3 +1,12 @@ +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:13:5 + | +LL | const async unsafe extern "C" fn ff5() {} // OK. + | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `async` because of this + | `const` because of this + error[E0706]: trait fns cannot be declared `async` --> $DIR/fn-header-semantic-fail.rs:17:9 | @@ -32,8 +41,17 @@ LL | const async unsafe extern "C" fn ft5(); = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:21:9 + | +LL | const async unsafe extern "C" fn ft5(); + | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `async` because of this + | `const` because of this + error[E0706]: trait fns cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:28:9 + --> $DIR/fn-header-semantic-fail.rs:29:9 | LL | async fn ft1() {} | -----^^^^^^^^^^^^ @@ -44,19 +62,19 @@ LL | async fn ft1() {} = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait error[E0379]: trait fns cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:31:9 + --> $DIR/fn-header-semantic-fail.rs:32:9 | LL | const fn ft3() {} | ^^^^^ trait fns cannot be const error[E0379]: trait fns cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:33:9 + --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^ trait fns cannot be const error[E0706]: trait fns cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:33:9 + --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,8 +84,26 @@ LL | const async unsafe extern "C" fn ft5() {} = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:34:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `async` because of this + | `const` because of this + +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:46:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `async` because of this + | `const` because of this + error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:48:18 + --> $DIR/fn-header-semantic-fail.rs:51:18 | LL | extern { | ------ in this `extern` block @@ -77,7 +113,7 @@ LL | async fn fe1(); | help: remove the qualifiers: `fn` error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:49:19 + --> $DIR/fn-header-semantic-fail.rs:52:19 | LL | extern { | ------ in this `extern` block @@ -88,7 +124,7 @@ LL | unsafe fn fe2(); | help: remove the qualifiers: `fn` error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:50:18 + --> $DIR/fn-header-semantic-fail.rs:53:18 | LL | extern { | ------ in this `extern` block @@ -99,7 +135,7 @@ LL | const fn fe3(); | help: remove the qualifiers: `fn` error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:51:23 + --> $DIR/fn-header-semantic-fail.rs:54:23 | LL | extern { | ------ in this `extern` block @@ -110,7 +146,7 @@ LL | extern "C" fn fe4(); | help: remove the qualifiers: `fn` error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:52:42 + --> $DIR/fn-header-semantic-fail.rs:55:42 | LL | extern { | ------ in this `extern` block @@ -120,8 +156,17 @@ LL | const async unsafe extern "C" fn fe5(); | | | help: remove the qualifiers: `fn` +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:55:9 + | +LL | const async unsafe extern "C" fn fe5(); + | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `async` because of this + | `const` because of this + error[E0053]: method `ft1` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:28:24 + --> $DIR/fn-header-semantic-fail.rs:29:24 | LL | async fn ft1(); | - type in trait @@ -136,7 +181,7 @@ LL | async fn ft1() {} found fn pointer `fn() -> impl std::future::Future` error[E0053]: method `ft5` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:33:48 + --> $DIR/fn-header-semantic-fail.rs:34:48 | LL | const async unsafe extern "C" fn ft5(); | - type in trait @@ -150,7 +195,7 @@ LL | const async unsafe extern "C" fn ft5() {} = note: expected fn pointer `unsafe extern "C" fn()` found fn pointer `unsafe extern "C" fn() -> impl std::future::Future` -error: aborting due to 15 previous errors +error: aborting due to 20 previous errors Some errors have detailed explanations: E0053, E0379, E0706. For more information about an error, try `rustc --explain E0053`. diff --git a/src/test/ui/parser/fn-header-syntactic-pass.rs b/src/test/ui/parser/fn-header-syntactic-pass.rs index 0557b9ef6ca..9e44541993d 100644 --- a/src/test/ui/parser/fn-header-syntactic-pass.rs +++ b/src/test/ui/parser/fn-header-syntactic-pass.rs @@ -3,9 +3,6 @@ // check-pass // edition:2018 -#![feature(const_extern_fn)] -//^ FIXME(Centril): move check to ast_validation. - fn main() {} #[cfg(FALSE)] @@ -14,8 +11,7 @@ fn syntax() { unsafe fn f(); const fn f(); extern "C" fn f(); - const /* async */ unsafe extern "C" fn f(); - //^ FIXME(Centril): `async` should be legal syntactically. + const async unsafe extern "C" fn f(); trait X { async fn f(); diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs index 90221039b41..2158a2fd6c1 100644 --- a/src/test/ui/parser/issue-19398.rs +++ b/src/test/ui/parser/issue-19398.rs @@ -1,5 +1,5 @@ trait T { - extern "Rust" unsafe fn foo(); //~ ERROR expected `fn`, found keyword `unsafe` + extern "Rust" unsafe fn foo(); //~ ERROR expected one of `async`, `const` } fn main() {} diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr index 41ec4f3ced4..201a6b2d66a 100644 --- a/src/test/ui/parser/issue-19398.stderr +++ b/src/test/ui/parser/issue-19398.stderr @@ -1,8 +1,10 @@ -error: expected `fn`, found keyword `unsafe` - --> $DIR/issue-19398.rs:2:19 +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `extern` + --> $DIR/issue-19398.rs:2:5 | +LL | trait T { + | - expected one of 10 possible tokens LL | extern "Rust" unsafe fn foo(); - | ^^^^^^ expected `fn` + | ^^^^^^ unexpected token error: aborting due to previous error diff --git a/src/test/ui/unsafe/unsafe-block-without-braces.rs b/src/test/ui/unsafe/unsafe-block-without-braces.rs index a291eb2eed7..4e461161854 100644 --- a/src/test/ui/unsafe/unsafe-block-without-braces.rs +++ b/src/test/ui/unsafe/unsafe-block-without-braces.rs @@ -3,4 +3,4 @@ fn main() { std::mem::transmute::<f32, u32>(1.0); //} } -//~^^^ ERROR expected one of `extern`, `fn`, or `{`, found `std` +//~^^^ ERROR expected `{`, found `std` diff --git a/src/test/ui/unsafe/unsafe-block-without-braces.stderr b/src/test/ui/unsafe/unsafe-block-without-braces.stderr index 637fdeead36..13e0c3681fa 100644 --- a/src/test/ui/unsafe/unsafe-block-without-braces.stderr +++ b/src/test/ui/unsafe/unsafe-block-without-braces.stderr @@ -1,8 +1,8 @@ -error: expected one of `extern`, `fn`, or `{`, found `std` +error: expected `{`, found `std` --> $DIR/unsafe-block-without-braces.rs:3:9 | LL | unsafe //{ - | - expected one of `extern`, `fn`, or `{` + | - expected `{` LL | std::mem::transmute::<f32, u32>(1.0); | ^^^ unexpected token |
