From 4c098db7b372b146151def96e9b553d54c89f136 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 12:17:09 +1000 Subject: [PATCH 01/12] Remove `NtVis`. We now use invisible delimiters for expanded `vis` fragments, instead of `Token::Interpolated`. --- compiler/rustc_ast/src/ast_traits.rs | 2 - compiler/rustc_ast/src/mut_visit.rs | 1 - compiler/rustc_ast/src/token.rs | 13 ++++-- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 36 ++++++++++++++- compiler/rustc_parse/src/parser/mod.rs | 46 ++++++++++++++++++- .../rustc_parse/src/parser/nonterminal.rs | 13 +++--- tests/ui/macros/block-to-expr-metavar.rs | 17 +++++++ 8 files changed, 110 insertions(+), 19 deletions(-) create mode 100644 tests/ui/macros/block-to-expr-metavar.rs diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 60f8c6e10481b..a2923d6448ae9 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -206,7 +206,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtTy(ty) => ty.tokens(), Nonterminal::NtMeta(attr_item) => attr_item.tokens(), Nonterminal::NtPath(path) => path.tokens(), - Nonterminal::NtVis(vis) => vis.tokens(), Nonterminal::NtBlock(block) => block.tokens(), } } @@ -219,7 +218,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtTy(ty) => ty.tokens_mut(), Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), Nonterminal::NtPath(path) => path.tokens_mut(), - Nonterminal::NtVis(vis) => vis.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 198e1bca77443..780f416645766 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -889,7 +889,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { visit_lazy_tts(vis, tokens); } token::NtPath(path) => vis.visit_path(path), - token::NtVis(visib) => vis.visit_vis(visib), } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 678f43e351137..a1afaf3895737 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -963,6 +963,15 @@ impl Token { } } + /// Is this an invisible open delimiter at the start of a token sequence + /// from an expanded metavar? + pub fn is_metavar_seq(&self) -> Option { + match self.kind { + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => Some(kind), + _ => None, + } + } + pub fn glue(&self, joint: &Token) -> Option { let kind = match self.kind { Eq => match joint.kind { @@ -1066,7 +1075,6 @@ pub enum Nonterminal { /// Stuff inside brackets for attributes NtMeta(P), NtPath(P), - NtVis(P), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] @@ -1163,7 +1171,6 @@ impl Nonterminal { NtTy(ty) => ty.span, NtMeta(attr_item) => attr_item.span(), NtPath(path) => path.span, - NtVis(vis) => vis.span, } } @@ -1178,7 +1185,6 @@ impl Nonterminal { NtTy(..) => "type", NtMeta(..) => "attribute", NtPath(..) => "path", - NtVis(..) => "visibility", } } } @@ -1205,7 +1211,6 @@ impl fmt::Debug for Nonterminal { NtLiteral(..) => f.pad("NtLiteral(..)"), NtMeta(..) => f.pad("NtMeta(..)"), NtPath(..) => f.pad("NtPath(..)"), - NtVis(..) => f.pad("NtVis(..)"), } } } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index c6b6addc946e8..145df25caff2f 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -471,7 +471,6 @@ impl TokenStream { Nonterminal::NtTy(ty) => TokenStream::from_ast(ty), Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr), Nonterminal::NtPath(path) => TokenStream::from_ast(path), - Nonterminal::NtVis(vis) => TokenStream::from_ast(vis), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index b77d02e630a21..2fa985b8206bd 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -2,7 +2,10 @@ use std::mem; use rustc_ast::ExprKind; use rustc_ast::mut_visit::{self, MutVisitor}; -use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, LitKind, Nonterminal, Token, TokenKind}; +use rustc_ast::token::{ + self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token, + TokenKind, +}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -253,7 +256,6 @@ pub(super) fn transcribe<'a>( } } - // Replace the meta-var with the matched token tree from the invocation. mbe::TokenTree::MetaVar(mut sp, mut original_ident) => { // Find the matched nonterminal from the macro invocation, and use it to replace // the meta-var. @@ -273,6 +275,33 @@ pub(super) fn transcribe<'a>( // some of the unnecessary whitespace. let ident = MacroRulesNormalizedIdent::new(original_ident); if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { + // We wrap the tokens in invisible delimiters, unless they are already wrapped + // in invisible delimiters with the same `MetaVarKind`. Because there is no + // point in having multiple layers of invisible delimiters of the same + // `MetaVarKind`. Indeed, some proc macros can't handle them. + let mut mk_delimited = |mv_kind, mut stream: TokenStream| { + if stream.len() == 1 { + let tree = stream.trees().next().unwrap(); + if let TokenTree::Delimited(_, _, delim, inner) = tree + && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mvk)) = delim + && mv_kind == *mvk + { + stream = inner.clone(); + } + } + + // Emit as a token stream within `Delimiter::Invisible` to maintain + // parsing priorities. + marker.visit_span(&mut sp); + // Both the open delim and close delim get the same span, which covers the + // `$foo` in the decl macro RHS. + TokenTree::Delimited( + DelimSpan::from_single(sp), + DelimSpacing::new(Spacing::Alone, Spacing::Alone), + Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)), + stream, + ) + }; let tt = match cur_matched { MatchedSingle(ParseNtResult::Tt(tt)) => { // `tt`s are emitted into the output stream directly as "raw tokens", @@ -289,6 +318,9 @@ pub(super) fn transcribe<'a>( let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } + MatchedSingle(ParseNtResult::Vis(vis)) => { + mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) + } MatchedSingle(ParseNtResult::Nt(nt)) => { // Other variables are emitted into the output stream as groups with // `Delimiter::Invisible` to maintain parsing priorities. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0ed8d152d2d34..f9159bd557741 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -720,6 +720,43 @@ impl<'a> Parser<'a> { if !self.eat_keyword(kw) { self.unexpected() } else { Ok(()) } } + /// Consume a sequence produced by a metavar expansion, if present. + fn eat_metavar_seq( + &mut self, + mv_kind: MetaVarKind, + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> Option { + self.eat_metavar_seq_with_matcher(|mvk| mvk == mv_kind, f) + } + + /// A slightly more general form of `eat_metavar_seq`, for use with the + /// `MetaVarKind` variants that have parameters, where an exact match isn't + /// desired. + fn eat_metavar_seq_with_matcher( + &mut self, + match_mv_kind: impl Fn(MetaVarKind) -> bool, + mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> Option { + if let token::OpenDelim(delim) = self.token.kind + && let Delimiter::Invisible(token::InvisibleOrigin::MetaVar(mv_kind)) = delim + && match_mv_kind(mv_kind) + { + self.bump(); + let res = f(self).expect("failed to reparse {mv_kind:?}"); + if let token::CloseDelim(delim) = self.token.kind + && let Delimiter::Invisible(token::InvisibleOrigin::MetaVar(mv_kind)) = delim + && match_mv_kind(mv_kind) + { + self.bump(); + Some(res) + } else { + panic!("no close delim when reparsing {mv_kind:?}"); + } + } else { + None + } + } + /// Is the given keyword `kw` followed by a non-reserved identifier? fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) @@ -1461,7 +1498,11 @@ impl<'a> Parser<'a> { /// so emit a proper diagnostic. // Public for rustfmt usage. pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { - maybe_whole!(self, NtVis, |vis| vis.into_inner()); + if let Some(vis) = self + .eat_metavar_seq(MetaVarKind::Vis, |this| this.parse_visibility(FollowedByType::Yes)) + { + return Ok(vis); + } if !self.eat_keyword(kw::Pub) { // We need a span for our `Spanned`, but there's inherently no @@ -1699,7 +1740,8 @@ pub enum ParseNtResult { Tt(TokenTree), Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), + Vis(P), - /// This case will eventually be removed, along with `Token::Interpolate`. + /// This variant will eventually be removed, along with `Token::Interpolate`. Nt(Lrc), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 8fb6f85d0dd8f..9bcb61db0f3cb 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -55,9 +55,7 @@ impl<'a> Parser<'a> { | NtMeta(_) | NtPath(_) => true, - NtItem(_) - | NtBlock(_) - | NtVis(_) => false, + NtItem(_) | NtBlock(_) => false, } } @@ -87,7 +85,7 @@ impl<'a> Parser<'a> { NonterminalKind::Ident => get_macro_ident(token).is_some(), NonterminalKind::Literal => token.can_begin_literal_maybe_minus(), NonterminalKind::Vis => match token.kind { - // The follow-set of :vis + "priv" keyword + interpolated + // The follow-set of :vis + "priv" keyword + interpolated/metavar-expansion. token::Comma | token::Ident(..) | token::NtIdent(..) @@ -101,7 +99,7 @@ impl<'a> Parser<'a> { token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, - NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false, + NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -207,8 +205,9 @@ impl<'a> Parser<'a> { } NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)), NonterminalKind::Vis => { - NtVis(P(self - .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?)) + return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| { + this.parse_visibility(FollowedByType::Yes) + })?))); } NonterminalKind::Lifetime => { // We want to keep `'keyword` parsing, just like `keyword` is still diff --git a/tests/ui/macros/block-to-expr-metavar.rs b/tests/ui/macros/block-to-expr-metavar.rs new file mode 100644 index 0000000000000..04f10ad0f9886 --- /dev/null +++ b/tests/ui/macros/block-to-expr-metavar.rs @@ -0,0 +1,17 @@ +//@ check-pass +// +// A test case where a `block` fragment specifier is interpreted as an `expr` +// fragment specifier. It's an interesting case for the handling of invisible +// delimiters. + +macro_rules! m_expr { + ($e:expr) => { const _CURRENT: u32 = $e; }; +} + +macro_rules! m_block { + ($b:block) => ( m_expr!($b); ); +} + +fn main() { + m_block!({ 1 }); +} From 3efa3256f061c0ff3002927301f88b74c3d079ab Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 13:17:44 +1000 Subject: [PATCH 02/12] Remove `NtTy`. Notes about tests: - tests/ui/parser/macro/trait-object-macro-matcher.rs: the syntax error is duplicated, because it occurs now when parsing the decl macro input, and also when parsing the expanded decl macro. But this won't show up for normal users due to error de-duplication. - tests/ui/associated-consts/issue-93835.rs: ditto. - The changes to metavariable descriptions in this PR's earlier commits are now visible in error message for several tests. --- compiler/rustc_ast/src/ast_traits.rs | 2 -- compiler/rustc_ast/src/mut_visit.rs | 1 - compiler/rustc_ast/src/token.rs | 7 +--- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 3 ++ compiler/rustc_parse/src/parser/mod.rs | 33 ++++++++++++++++--- .../rustc_parse/src/parser/nonterminal.rs | 7 ++-- compiler/rustc_parse/src/parser/path.rs | 17 +++++----- compiler/rustc_parse/src/parser/ty.rs | 14 +++++--- tests/ui/associated-consts/issue-93835.rs | 1 + tests/ui/associated-consts/issue-93835.stderr | 13 +++++++- tests/ui/macros/macro-interpolation.rs | 2 +- tests/ui/macros/macro-interpolation.stderr | 4 +-- tests/ui/macros/syntax-error-recovery.rs | 4 +-- tests/ui/macros/syntax-error-recovery.stderr | 4 +-- tests/ui/parser/macro/issue-37113.rs | 2 +- tests/ui/parser/macro/issue-37113.stderr | 4 +-- .../macro/trait-object-macro-matcher.rs | 1 + .../macro/trait-object-macro-matcher.stderr | 10 +++++- 19 files changed, 88 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index a2923d6448ae9..346edc87c86bc 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -203,7 +203,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtStmt(stmt) => stmt.tokens(), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), Nonterminal::NtPat(pat) => pat.tokens(), - Nonterminal::NtTy(ty) => ty.tokens(), Nonterminal::NtMeta(attr_item) => attr_item.tokens(), Nonterminal::NtPath(path) => path.tokens(), Nonterminal::NtBlock(block) => block.tokens(), @@ -215,7 +214,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtStmt(stmt) => stmt.tokens_mut(), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), Nonterminal::NtPat(pat) => pat.tokens_mut(), - Nonterminal::NtTy(ty) => ty.tokens_mut(), Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), Nonterminal::NtPath(path) => path.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 780f416645766..09dd80f0c58e8 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -880,7 +880,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { }), token::NtPat(pat) => vis.visit_pat(pat), token::NtExpr(expr) => vis.visit_expr(expr), - token::NtTy(ty) => vis.visit_ty(ty), token::NtLiteral(expr) => vis.visit_expr(expr), token::NtMeta(item) => { let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut(); diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index a1afaf3895737..d6d044d9221d9 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -660,7 +660,6 @@ impl Token { | NtMeta(..) | NtPat(..) | NtPath(..) - | NtTy(..) ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | @@ -689,7 +688,7 @@ impl Token { Lifetime(..) | // lifetime bound in trait object Lt | BinOp(Shl) | // associated path PathSep => true, // global path - Interpolated(ref nt) => matches!(&**nt, NtTy(..) | NtPath(..)), + Interpolated(ref nt) => matches!(&**nt, NtPath(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Ty | MetaVarKind::Path @@ -1070,7 +1069,6 @@ pub enum Nonterminal { NtStmt(P), NtPat(P), NtExpr(P), - NtTy(P), NtLiteral(P), /// Stuff inside brackets for attributes NtMeta(P), @@ -1168,7 +1166,6 @@ impl Nonterminal { NtStmt(stmt) => stmt.span, NtPat(pat) => pat.span, NtExpr(expr) | NtLiteral(expr) => expr.span, - NtTy(ty) => ty.span, NtMeta(attr_item) => attr_item.span(), NtPath(path) => path.span, } @@ -1182,7 +1179,6 @@ impl Nonterminal { NtPat(..) => "pattern", NtExpr(..) => "expression", NtLiteral(..) => "literal", - NtTy(..) => "type", NtMeta(..) => "attribute", NtPath(..) => "path", } @@ -1207,7 +1203,6 @@ impl fmt::Debug for Nonterminal { NtStmt(..) => f.pad("NtStmt(..)"), NtPat(..) => f.pad("NtPat(..)"), NtExpr(..) => f.pad("NtExpr(..)"), - NtTy(..) => f.pad("NtTy(..)"), NtLiteral(..) => f.pad("NtLiteral(..)"), NtMeta(..) => f.pad("NtMeta(..)"), NtPath(..) => f.pad("NtPath(..)"), diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 145df25caff2f..a455f9bc92dbc 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -468,7 +468,6 @@ impl TokenStream { } Nonterminal::NtStmt(stmt) => TokenStream::from_ast(stmt), Nonterminal::NtPat(pat) => TokenStream::from_ast(pat), - Nonterminal::NtTy(ty) => TokenStream::from_ast(ty), Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr), Nonterminal::NtPath(path) => TokenStream::from_ast(path), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 2fa985b8206bd..36665149b977d 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -318,6 +318,9 @@ pub(super) fn transcribe<'a>( let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } + MatchedSingle(ParseNtResult::Ty(ty)) => { + mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty)) + } MatchedSingle(ParseNtResult::Vis(vis)) => { mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index f9159bd557741..d3b3ccdb89b83 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -116,12 +116,16 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { ($self: expr, $allow_qpath_recovery: expr) => { if $allow_qpath_recovery && $self.may_recover() - && $self.look_ahead(1, |t| t == &token::PathSep) - && let token::Interpolated(nt) = &$self.token.kind - && let token::NtTy(ty) = &**nt + && let Some(token::MetaVarKind::Ty) = $self.token.is_metavar_seq() + && $self.check_noexpect_past_close_delim(&token::PathSep) { - let ty = ty.clone(); - $self.bump(); + // Reparse the type, then move to recovery. + let ty = $self + .eat_metavar_seq(token::MetaVarKind::Ty, |this| { + this.parse_ty_no_question_mark_recover() + }) + .expect("metavar seq ty"); + return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty); } }; @@ -611,6 +615,24 @@ impl<'a> Parser<'a> { self.token == *tok } + // Check the first token after the delimiter that closes the current + // delimited sequence. (Panics if used in the outermost token stream, which + // has no delimiters.) It uses a clone of the relevant tree cursor to skip + // past the entire `TokenTree::Delimited` in a single step, avoiding the + // need for unbounded token lookahead. + // + // Primarily used when `self.token` matches + // `OpenDelim(Delimiter::Invisible(_))`, to look ahead through the current + // metavar expansion. + fn check_noexpect_past_close_delim(&self, tok: &TokenKind) -> bool { + let mut tree_cursor = self.token_cursor.stack.last().unwrap().0.clone(); + let tt = tree_cursor.next_ref(); + matches!( + tt, + Some(ast::tokenstream::TokenTree::Token(token::Token { kind, .. }, _)) if kind == tok + ) + } + /// Consumes a token 'tok' if it exists. Returns whether the given token was present. /// /// the main purpose of this function is to reduce the cluttering of the suggestions list @@ -1740,6 +1762,7 @@ pub enum ParseNtResult { Tt(TokenTree), Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), + Ty(P), Vis(P), /// This variant will eventually be removed, along with `Token::Interpolate`. diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 9bcb61db0f3cb..becba48a1a825 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -50,7 +50,6 @@ impl<'a> Parser<'a> { NtStmt(_) | NtPat(_) | NtExpr(_) - | NtTy(_) | NtLiteral(_) // `true`, `false` | NtMeta(_) | NtPath(_) => true, @@ -99,7 +98,7 @@ impl<'a> Parser<'a> { token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, - NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) => false, + NtItem(_) | NtPat(_) | NtMeta(_) | NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -186,7 +185,9 @@ impl<'a> Parser<'a> { NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) } NonterminalKind::Ty => { - NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?) + return Ok(ParseNtResult::Ty( + self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, + )); } // this could be handled like a token, since it is one NonterminalKind::Ident => { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 2f19a9b6b20b4..950d633435f9f 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -2,7 +2,7 @@ use std::mem; use ast::token::IdentIsRaw; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, MetaVarKind, Token, TokenKind}; use rustc_ast::{ self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint, AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, @@ -198,13 +198,14 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner())); - if let token::Interpolated(nt) = &self.token.kind { - if let token::NtTy(ty) = &**nt { - if let ast::TyKind::Path(None, path) = &ty.kind { - let path = path.clone(); - self.bump(); - return Ok(reject_generics_if_mod_style(self, path)); - } + if let Some(MetaVarKind::Ty) = self.token.is_metavar_seq() { + let mut snapshot = self.create_snapshot_for_diagnostic(); + let ty = snapshot + .eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover()) + .expect("metavar seq ty"); + if let ast::TyKind::Path(None, path) = ty.into_inner().kind { + self.restore_snapshot(snapshot); + return Ok(reject_generics_if_mod_style(self, path)); } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index c561ea3823d09..865a75f9f3608 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,5 +1,5 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind}; +use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy, @@ -19,7 +19,7 @@ use crate::errors::{ HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow, }; -use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; +use crate::maybe_recover_from_interpolated_ty_qpath; /// Signals whether parsing a type should allow `+`. /// @@ -184,7 +184,8 @@ impl<'a> Parser<'a> { ) } - /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>` + /// Parse a type without recovering `:` as `->` to avoid breaking code such + /// as `where fn() : for<'a>`. pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P> { self.parse_ty_common( AllowPlus::Yes, @@ -248,7 +249,12 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); - maybe_whole!(self, NtTy, |ty| ty); + + if let Some(ty) = + self.eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover()) + { + return Ok(ty); + } let lo = self.token.span; let mut impl_dyn_multi = false; diff --git a/tests/ui/associated-consts/issue-93835.rs b/tests/ui/associated-consts/issue-93835.rs index 9cc33d53f9cd5..c8b0990d0f0fa 100644 --- a/tests/ui/associated-consts/issue-93835.rs +++ b/tests/ui/associated-consts/issue-93835.rs @@ -5,6 +5,7 @@ fn e() { //~^ ERROR cannot find type `a` in this scope //~| ERROR cannot find value //~| ERROR associated const equality + //~| ERROR associated const equality //~| ERROR cannot find trait `p` in this scope } diff --git a/tests/ui/associated-consts/issue-93835.stderr b/tests/ui/associated-consts/issue-93835.stderr index dfe78b3d1f380..551b50d0eb6b5 100644 --- a/tests/ui/associated-consts/issue-93835.stderr +++ b/tests/ui/associated-consts/issue-93835.stderr @@ -26,7 +26,18 @@ LL | type_ascribe!(p, a>); = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 4 previous errors +error[E0658]: associated const equality is incomplete + --> $DIR/issue-93835.rs:4:28 + | +LL | type_ascribe!(p, a>); + | ^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0405, E0412, E0425, E0658. For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/macros/macro-interpolation.rs b/tests/ui/macros/macro-interpolation.rs index 48c1f19e777f7..b5d2322c8052c 100644 --- a/tests/ui/macros/macro-interpolation.rs +++ b/tests/ui/macros/macro-interpolation.rs @@ -19,7 +19,7 @@ macro_rules! qpath { (ty, <$type:ty as $trait:ty>::$name:ident) => { <$type as $trait>::$name - //~^ ERROR expected identifier, found `!` + //~^ ERROR expected identifier, found metavariable }; } diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr index e6b39dfef8581..bc24a15861295 100644 --- a/tests/ui/macros/macro-interpolation.stderr +++ b/tests/ui/macros/macro-interpolation.stderr @@ -1,8 +1,8 @@ -error: expected identifier, found `!` +error: expected identifier, found metavariable --> $DIR/macro-interpolation.rs:21:19 | LL | <$type as $trait>::$name - | ^^^^^^ expected identifier + | ^^^^^^ expected identifier, found metavariable ... LL | let _: qpath!(ty, ::Owned); | ----------------------------- diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs index 016e4def28497..6cf9d54e82636 100644 --- a/tests/ui/macros/syntax-error-recovery.rs +++ b/tests/ui/macros/syntax-error-recovery.rs @@ -9,8 +9,8 @@ macro_rules! values { } }; } -//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)` -//~| ERROR macro expansion ignores type `(String)` and any tokens following +//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable +//~| ERROR macro expansion ignores `ty` metavariable and any tokens following values!(STRING(1) as (String) => cfg(test),); //~^ ERROR expected one of `!` or `::`, found `` diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr index 3cfbd8ce82b56..61758fb9d7dc6 100644 --- a/tests/ui/macros/syntax-error-recovery.stderr +++ b/tests/ui/macros/syntax-error-recovery.stderr @@ -1,4 +1,4 @@ -error: expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)` +error: expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable --> $DIR/syntax-error-recovery.rs:7:26 | LL | $token $($inner)? = $value, @@ -10,7 +10,7 @@ LL | values!(STRING(1) as (String) => cfg(test),); = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info) -error: macro expansion ignores type `(String)` and any tokens following +error: macro expansion ignores `ty` metavariable and any tokens following --> $DIR/syntax-error-recovery.rs:7:26 | LL | $token $($inner)? = $value, diff --git a/tests/ui/parser/macro/issue-37113.rs b/tests/ui/parser/macro/issue-37113.rs index 0044aa5610f5f..e0957542f8f19 100644 --- a/tests/ui/parser/macro/issue-37113.rs +++ b/tests/ui/parser/macro/issue-37113.rs @@ -1,7 +1,7 @@ macro_rules! test_macro { ( $( $t:ty ),* $(),*) => { enum SomeEnum { - $( $t, )* //~ ERROR expected identifier, found `String` + $( $t, )* //~ ERROR expected identifier, found metavariable }; }; } diff --git a/tests/ui/parser/macro/issue-37113.stderr b/tests/ui/parser/macro/issue-37113.stderr index 1f2fe23106ae3..560329df5ccbd 100644 --- a/tests/ui/parser/macro/issue-37113.stderr +++ b/tests/ui/parser/macro/issue-37113.stderr @@ -1,10 +1,10 @@ -error: expected identifier, found `String` +error: expected identifier, found metavariable --> $DIR/issue-37113.rs:4:16 | LL | enum SomeEnum { | -------- while parsing this enum LL | $( $t, )* - | ^^ expected identifier + | ^^ expected identifier, found metavariable ... LL | test_macro!(String,); | -------------------- in this macro invocation diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.rs b/tests/ui/parser/macro/trait-object-macro-matcher.rs index 560195977d03a..d4ec199070e7c 100644 --- a/tests/ui/parser/macro/trait-object-macro-matcher.rs +++ b/tests/ui/parser/macro/trait-object-macro-matcher.rs @@ -10,5 +10,6 @@ macro_rules! m { fn main() { m!('static); //~^ ERROR lifetime in trait object type must be followed by `+` + //~| ERROR lifetime in trait object type must be followed by `+` //~| ERROR at least one trait is required for an object type } diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.stderr index 40082564bad4c..81dca6f71c436 100644 --- a/tests/ui/parser/macro/trait-object-macro-matcher.stderr +++ b/tests/ui/parser/macro/trait-object-macro-matcher.stderr @@ -4,12 +4,20 @@ error: lifetime in trait object type must be followed by `+` LL | m!('static); | ^^^^^^^ +error: lifetime in trait object type must be followed by `+` + --> $DIR/trait-object-macro-matcher.rs:11:8 + | +LL | m!('static); + | ^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0224]: at least one trait is required for an object type --> $DIR/trait-object-macro-matcher.rs:11:8 | LL | m!('static); | ^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0224`. From ce05de527c4a5c18210ac0b7d45d37907d29ffc9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 12:44:11 +1000 Subject: [PATCH 03/12] Remove `NtPat`. The one notable test change is `tests/ui/macros/trace_faulty_macros.rs`. This commit removes the complicated `Interpolated` handling in `expected_expression_found` that results in a longer error message. But I think the new, shorter message is actually an improvement. The original complaint was in #71039, when the error message started with "error: expected expression, found `1 + 1`". That was confusing because `1 + 1` is an expression. Other than that, the reporter said "the whole error message is not too bad if you ignore the first line". Subsequently, extra complexity and wording was added to the error message. But I don't think the extra wording actually helps all that much. In particular, it still says of the `1+1` that "this is expected to be expression". This repeats the problem from the original complaint! This commit removes the extra complexity, reverting to a simpler error message. This is primarily because the traversal is a pain without `Interpolated` tokens. Nonetheless, I think the error message is *improved*. It now starts with "expected expression, found `pat` metavariable", which is much clearer and the real problem. It also doesn't say anything specific about `1+1`, which is good, because the `1+1` isn't really relevant to the error -- it's the `$e:pat` that's important. --- compiler/rustc_ast/src/ast_traits.rs | 2 - compiler/rustc_ast/src/mut_visit.rs | 1 - compiler/rustc_ast/src/token.rs | 5 -- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 3 ++ .../rustc_parse/src/parser/diagnostics.rs | 52 +------------------ compiler/rustc_parse/src/parser/item.rs | 8 +-- compiler/rustc_parse/src/parser/mod.rs | 4 +- .../rustc_parse/src/parser/nonterminal.rs | 24 +++++---- compiler/rustc_parse/src/parser/pat.rs | 37 ++++++++++--- tests/ui/macros/trace_faulty_macros.rs | 2 +- tests/ui/macros/trace_faulty_macros.stderr | 13 ++--- .../issue-65122-mac-invoc-in-mut-patterns.rs | 2 +- ...sue-65122-mac-invoc-in-mut-patterns.stderr | 4 +- tests/ui/parser/mut-patterns.rs | 2 +- tests/ui/parser/mut-patterns.stderr | 4 +- 16 files changed, 66 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 346edc87c86bc..8b94d65c44ecb 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -202,7 +202,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtItem(item) => item.tokens(), Nonterminal::NtStmt(stmt) => stmt.tokens(), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), - Nonterminal::NtPat(pat) => pat.tokens(), Nonterminal::NtMeta(attr_item) => attr_item.tokens(), Nonterminal::NtPath(path) => path.tokens(), Nonterminal::NtBlock(block) => block.tokens(), @@ -213,7 +212,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtItem(item) => item.tokens_mut(), Nonterminal::NtStmt(stmt) => stmt.tokens_mut(), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), - Nonterminal::NtPat(pat) => pat.tokens_mut(), Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), Nonterminal::NtPath(path) => path.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 09dd80f0c58e8..c4a9e83360dc3 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -878,7 +878,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item") }) }), - token::NtPat(pat) => vis.visit_pat(pat), token::NtExpr(expr) => vis.visit_expr(expr), token::NtLiteral(expr) => vis.visit_expr(expr), token::NtMeta(item) => { diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index d6d044d9221d9..b722557b0de9f 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -658,7 +658,6 @@ impl Token { | NtExpr(..) | NtLiteral(..) | NtMeta(..) - | NtPat(..) | NtPath(..) ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( @@ -1067,7 +1066,6 @@ pub enum Nonterminal { NtItem(P), NtBlock(P), NtStmt(P), - NtPat(P), NtExpr(P), NtLiteral(P), /// Stuff inside brackets for attributes @@ -1164,7 +1162,6 @@ impl Nonterminal { NtItem(item) => item.span, NtBlock(block) => block.span, NtStmt(stmt) => stmt.span, - NtPat(pat) => pat.span, NtExpr(expr) | NtLiteral(expr) => expr.span, NtMeta(attr_item) => attr_item.span(), NtPath(path) => path.span, @@ -1176,7 +1173,6 @@ impl Nonterminal { NtItem(..) => "item", NtBlock(..) => "block", NtStmt(..) => "statement", - NtPat(..) => "pattern", NtExpr(..) => "expression", NtLiteral(..) => "literal", NtMeta(..) => "attribute", @@ -1201,7 +1197,6 @@ impl fmt::Debug for Nonterminal { NtItem(..) => f.pad("NtItem(..)"), NtBlock(..) => f.pad("NtBlock(..)"), NtStmt(..) => f.pad("NtStmt(..)"), - NtPat(..) => f.pad("NtPat(..)"), NtExpr(..) => f.pad("NtExpr(..)"), NtLiteral(..) => f.pad("NtLiteral(..)"), NtMeta(..) => f.pad("NtMeta(..)"), diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index a455f9bc92dbc..36684cfdf702d 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -467,7 +467,6 @@ impl TokenStream { TokenStream::token_alone(token::Semi, stmt.span) } Nonterminal::NtStmt(stmt) => TokenStream::from_ast(stmt), - Nonterminal::NtPat(pat) => TokenStream::from_ast(pat), Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr), Nonterminal::NtPath(path) => TokenStream::from_ast(path), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 36665149b977d..ee7131f314b73 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -318,6 +318,9 @@ pub(super) fn transcribe<'a>( let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } + MatchedSingle(ParseNtResult::Pat(pat, pat_kind)) => { + mk_delimited(MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat)) + } MatchedSingle(ParseNtResult::Ty(ty)) => { mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty)) } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a1fe550897073..e4bba95eb03d7 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -5,16 +5,14 @@ use ast::token::IdentIsRaw; use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind}; -use rustc_ast::tokenstream::AttrTokenTree; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block, - BlockCheckMode, Expr, ExprKind, GenericArg, Generics, HasTokens, Item, ItemKind, Param, Pat, - PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind, + BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind, + Path, PathSegment, QSelf, Recovered, Ty, TyKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::Lrc; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, PErr, PResult, Subdiagnostic, Suggestions, pluralize, @@ -2429,52 +2427,6 @@ impl<'a> Parser<'a> { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } err.span_label(span, "expected expression"); - - // Walk the chain of macro expansions for the current token to point at how the original - // code was interpreted. This helps the user realize when a macro argument of one type is - // later reinterpreted as a different type, like `$x:expr` being reinterpreted as `$x:pat` - // in a subsequent macro invocation (#71039). - let mut tok = self.token.clone(); - let mut labels = vec![]; - while let TokenKind::Interpolated(nt) = &tok.kind { - let tokens = nt.tokens(); - labels.push(Lrc::clone(nt)); - if let Some(tokens) = tokens - && let tokens = tokens.to_attr_token_stream() - && let tokens = tokens.0.deref() - && let [AttrTokenTree::Token(token, _)] = &tokens[..] - { - tok = token.clone(); - } else { - break; - } - } - let mut iter = labels.into_iter().peekable(); - let mut show_link = false; - while let Some(nt) = iter.next() { - let descr = nt.descr(); - if let Some(next) = iter.peek() { - let next_descr = next.descr(); - if next_descr != descr { - err.span_label(next.use_span(), format!("this is expected to be {next_descr}")); - err.span_label( - nt.use_span(), - format!( - "this is interpreted as {}, but it is expected to be {}", - next_descr, descr, - ), - ); - show_link = true; - } - } - } - if show_link { - err.note( - "when forwarding a matched fragment to another macro-by-example, matchers in the \ - second macro will see an opaque AST of the fragment type, not the underlying \ - tokens", - ); - } err } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 26e81b7676bb1..c97e1044dcf63 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -4,7 +4,7 @@ use std::mem; use ast::token::IdentIsRaw; use rustc_ast::ast::*; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, TokenKind}; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; use rustc_ast::{self as ast}; @@ -3011,8 +3011,10 @@ impl<'a> Parser<'a> { fn is_named_param(&self) -> bool { let offset = match &self.token.kind { - token::Interpolated(nt) => match &**nt { - token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), + token::OpenDelim(Delimiter::Invisible(origin)) => match origin { + InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => { + return self.check_noexpect_past_close_delim(&token::Colon); + } _ => 0, }, token::BinOp(token::And) | token::AndAnd => 1, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index d3b3ccdb89b83..9800a376699d3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -22,7 +22,8 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, Token, TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtPatKind, Token, + TokenKind, }; use rustc_ast::tokenstream::{ AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor, @@ -1762,6 +1763,7 @@ pub enum ParseNtResult { Tt(TokenTree), Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), + Pat(P, NtPatKind), Ty(P), Vis(P), diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index becba48a1a825..e0ee24e75822f 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -48,7 +48,6 @@ impl<'a> Parser<'a> { fn nt_may_be_ident(nt: &Nonterminal) -> bool { match nt { NtStmt(_) - | NtPat(_) | NtExpr(_) | NtLiteral(_) // `true`, `false` | NtMeta(_) @@ -98,7 +97,7 @@ impl<'a> Parser<'a> { token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, - NtItem(_) | NtPat(_) | NtMeta(_) | NtPath(_) => false, + NtItem(_) | NtMeta(_) | NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -169,15 +168,18 @@ impl<'a> Parser<'a> { } }, NonterminalKind::Pat(pat_kind) => { - NtPat(self.collect_tokens_no_attrs(|this| match pat_kind { - PatParam { .. } => this.parse_pat_no_top_alt(None, None), - PatWithOr => this.parse_pat_allow_top_alt( - None, - RecoverComma::No, - RecoverColon::No, - CommaRecoveryMode::EitherTupleOrPipe, - ), - })?) + return Ok(ParseNtResult::Pat( + self.collect_tokens_no_attrs(|this| match pat_kind { + PatParam { .. } => this.parse_pat_no_top_alt(None, None), + PatWithOr => this.parse_pat_allow_top_alt( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::EitherTupleOrPipe, + ), + })?, + pat_kind, + )); } NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index c4326427f67b0..4ffae4426f481 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,6 +1,7 @@ use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token}; +use rustc_ast::token::NtPatKind::*; +use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token}; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, ExprPrecedence, @@ -28,8 +29,8 @@ use crate::errors::{ UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, }; +use crate::maybe_recover_from_interpolated_ty_qpath; use crate::parser::expr::{DestructuredFloat, could_be_unclosed_char_literal}; -use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; #[derive(PartialEq, Copy, Clone)] pub enum Expected { @@ -664,6 +665,27 @@ impl<'a> Parser<'a> { PatVisitor { parser: self, stmt, arm: None, field: None }.visit_stmt(stmt); } + fn eat_metavar_pat(&mut self) -> Option> { + // Must try both kinds of pattern nonterminals. + if let Some(pat) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Pat(PatParam { .. })), + |this| this.parse_pat_no_top_alt(None, None), + ) { + Some(pat) + } else if let Some(pat) = self.eat_metavar_seq(MetaVarKind::Pat(PatWithOr), |this| { + this.parse_pat_allow_top_alt( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::EitherTupleOrPipe, + ) + }) { + Some(pat) + } else { + None + } + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( @@ -673,7 +695,10 @@ impl<'a> Parser<'a> { syntax_loc: Option, ) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, true); - maybe_whole!(self, NtPat, |pat| pat); + + if let Some(pat) = self.eat_metavar_pat() { + return Ok(pat); + } let mut lo = self.token.span; @@ -1017,10 +1042,8 @@ impl<'a> Parser<'a> { self.recover_additional_muts(); // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`. - if let token::Interpolated(nt) = &self.token.kind { - if let token::NtPat(..) = &**nt { - self.expected_ident_found_err().emit(); - } + if let Some(MetaVarKind::Pat(_)) = self.token.is_metavar_seq() { + self.expected_ident_found_err().emit(); } // Parse the pattern we hope to be an identifier. diff --git a/tests/ui/macros/trace_faulty_macros.rs b/tests/ui/macros/trace_faulty_macros.rs index 87036bb9c6f75..e0cbbd8f5c9e6 100644 --- a/tests/ui/macros/trace_faulty_macros.rs +++ b/tests/ui/macros/trace_faulty_macros.rs @@ -46,7 +46,7 @@ macro_rules! test { (let $p:pat = $e:expr) => {test!(($p,$e))}; // this should be expr // vvv - (($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found pattern `1+1` + (($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found `pat` metavariable } fn foo() { diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr index 10ad3faab1612..73fed66e61906 100644 --- a/tests/ui/macros/trace_faulty_macros.stderr +++ b/tests/ui/macros/trace_faulty_macros.stderr @@ -50,7 +50,7 @@ LL | my_recursive_macro!(); = note: expanding `my_recursive_macro! { }` = note: to `my_recursive_macro! ();` -error: expected expression, found pattern `A { a : a, b : 0, c : _, .. }` +error: expected expression, found `pat` metavariable --> $DIR/trace_faulty_macros.rs:16:9 | LL | $a @@ -69,22 +69,15 @@ LL | #[derive(Debug)] LL | fn use_derive_macro_as_attr() {} | -------------------------------- not a `struct`, `enum` or `union` -error: expected expression, found pattern `1+1` +error: expected expression, found `pat` metavariable --> $DIR/trace_faulty_macros.rs:49:37 | -LL | (let $p:pat = $e:expr) => {test!(($p,$e))}; - | -- this is interpreted as expression, but it is expected to be pattern -... LL | (($p:pat, $e:pat)) => {let $p = $e;}; | ^^ expected expression ... LL | test!(let x = 1+1); - | ------------------ - | | | - | | this is expected to be expression - | in this macro invocation + | ------------------ in this macro invocation | - = note: when forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type, not the underlying tokens = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro diff --git a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs index 30f3781bf7743..1a0833ebb2f61 100644 --- a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs +++ b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs @@ -12,7 +12,7 @@ macro_rules! mac2 { ($eval:pat) => { let mut $eval = (); //~^ ERROR `mut` must be followed by a named binding - //~| ERROR expected identifier, found `does_not_exist!()` + //~| ERROR expected identifier, found metavariable }; } diff --git a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr index 76259b40a9332..aec054c205c37 100644 --- a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr +++ b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr @@ -15,11 +15,11 @@ LL - let mut $eval = (); LL + let $eval = (); | -error: expected identifier, found `does_not_exist!()` +error: expected identifier, found metavariable --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:17 | LL | let mut $eval = (); - | ^^^^^ expected identifier + | ^^^^^ expected identifier, found metavariable ... LL | mac2! { does_not_exist!() } | --------------------------- in this macro invocation diff --git a/tests/ui/parser/mut-patterns.rs b/tests/ui/parser/mut-patterns.rs index b8610c4e19050..8b0a2d99ea96c 100644 --- a/tests/ui/parser/mut-patterns.rs +++ b/tests/ui/parser/mut-patterns.rs @@ -41,7 +41,7 @@ pub fn main() { // Make sure we don't accidentally allow `mut $p` where `$p:pat`. macro_rules! foo { ($p:pat) => { - let mut $p = 0; //~ ERROR expected identifier, found `x` + let mut $p = 0; //~ ERROR expected identifier, found metavariable } } foo!(x); diff --git a/tests/ui/parser/mut-patterns.stderr b/tests/ui/parser/mut-patterns.stderr index f4f11b88d3615..59cbe01c47894 100644 --- a/tests/ui/parser/mut-patterns.stderr +++ b/tests/ui/parser/mut-patterns.stderr @@ -142,11 +142,11 @@ help: add `mut` to each binding LL | let W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f })))) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: expected identifier, found `x` +error: expected identifier, found metavariable --> $DIR/mut-patterns.rs:44:21 | LL | let mut $p = 0; - | ^^ expected identifier + | ^^ expected identifier, found metavariable ... LL | foo!(x); | ------- in this macro invocation From 2dfeaa908e491a6f9b0fbf20886e6933ac55ba50 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 14:53:52 +1000 Subject: [PATCH 04/12] Remove `NtItem` and `NtStmt`. This involves replacing `nt_pretty_printing_compatibility_hack` with `stream_pretty_printing_compatibility_hack`. The handling of statements in `transcribe` is slightly different to other nonterminal kinds, due to the lack of `from_ast` implementation for empty statements. Notable test changes: - `tests/ui/proc-macro/expand-to-derive.rs`: the diff looks large but the only difference is the insertion of a single invisible-delimited group around a metavar. --- compiler/rustc_ast/src/ast_traits.rs | 4 - compiler/rustc_ast/src/mut_visit.rs | 12 --- compiler/rustc_ast/src/token.rs | 8 -- compiler/rustc_ast/src/tokenstream.rs | 8 +- compiler/rustc_builtin_macros/src/cfg_eval.rs | 5 +- compiler/rustc_expand/src/base.rs | 49 ++++++++---- compiler/rustc_expand/src/mbe/transcribe.rs | 14 +++- compiler/rustc_expand/src/proc_macro.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 31 ++++--- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 14 ++-- compiler/rustc_parse/src/parser/mod.rs | 12 ++- .../rustc_parse/src/parser/nonterminal.rs | 13 ++- compiler/rustc_parse/src/parser/stmt.rs | 60 +++++++++----- tests/ui/macros/macro-stmt-2.rs | 11 +++ tests/ui/macros/nonterminal-matching.rs | 4 +- tests/ui/macros/nonterminal-matching.stderr | 6 +- tests/ui/proc-macro/expand-to-derive.stdout | 80 ++++++++++--------- 18 files changed, 195 insertions(+), 140 deletions(-) create mode 100644 tests/ui/macros/macro-stmt-2.rs diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 8b94d65c44ecb..26ae64a4b6886 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -199,8 +199,6 @@ impl HasTokens for Attribute { impl HasTokens for Nonterminal { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { - Nonterminal::NtItem(item) => item.tokens(), - Nonterminal::NtStmt(stmt) => stmt.tokens(), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), Nonterminal::NtMeta(attr_item) => attr_item.tokens(), Nonterminal::NtPath(path) => path.tokens(), @@ -209,8 +207,6 @@ impl HasTokens for Nonterminal { } fn tokens_mut(&mut self) -> Option<&mut Option> { match self { - Nonterminal::NtItem(item) => item.tokens_mut(), - Nonterminal::NtStmt(stmt) => stmt.tokens_mut(), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), Nonterminal::NtPath(path) => path.tokens_mut(), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c4a9e83360dc3..86ee6425aa425 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -865,19 +865,7 @@ pub fn visit_token(vis: &mut T, t: &mut Token) { // multiple items there.... fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { match nt { - token::NtItem(item) => visit_clobber(item, |item| { - // This is probably okay, because the only visitors likely to - // peek inside interpolated nodes will be renamings/markings, - // which map single items to single items. - vis.flat_map_item(item).expect_one("expected visitor to produce exactly one item") - }), token::NtBlock(block) => vis.visit_block(block), - token::NtStmt(stmt) => visit_clobber(stmt, |stmt| { - // See reasoning above. - stmt.map(|stmt| { - vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item") - }) - }), token::NtExpr(expr) => vis.visit_expr(expr), token::NtLiteral(expr) => vis.visit_expr(expr), token::NtMeta(item) => { diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index b722557b0de9f..ffe3a75b1f314 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -1063,9 +1063,7 @@ pub enum NtExprKind { #[derive(Clone, Encodable, Decodable)] /// For interpolation during macro expansion. pub enum Nonterminal { - NtItem(P), NtBlock(P), - NtStmt(P), NtExpr(P), NtLiteral(P), /// Stuff inside brackets for attributes @@ -1159,9 +1157,7 @@ impl fmt::Display for NonterminalKind { impl Nonterminal { pub fn use_span(&self) -> Span { match self { - NtItem(item) => item.span, NtBlock(block) => block.span, - NtStmt(stmt) => stmt.span, NtExpr(expr) | NtLiteral(expr) => expr.span, NtMeta(attr_item) => attr_item.span(), NtPath(path) => path.span, @@ -1170,9 +1166,7 @@ impl Nonterminal { pub fn descr(&self) -> &'static str { match self { - NtItem(..) => "item", NtBlock(..) => "block", - NtStmt(..) => "statement", NtExpr(..) => "expression", NtLiteral(..) => "literal", NtMeta(..) => "attribute", @@ -1194,9 +1188,7 @@ impl PartialEq for Nonterminal { impl fmt::Debug for Nonterminal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - NtItem(..) => f.pad("NtItem(..)"), NtBlock(..) => f.pad("NtBlock(..)"), - NtStmt(..) => f.pad("NtStmt(..)"), NtExpr(..) => f.pad("NtExpr(..)"), NtLiteral(..) => f.pad("NtLiteral(..)"), NtMeta(..) => f.pad("NtMeta(..)"), diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 36684cfdf702d..20774362592f3 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -22,7 +22,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym}; -use crate::ast::{AttrStyle, StmtKind}; +use crate::ast::AttrStyle; use crate::ast_traits::{HasAttrs, HasTokens}; use crate::token::{self, Delimiter, InvisibleOrigin, Nonterminal, Token, TokenKind}; use crate::{AttrVec, Attribute}; @@ -460,13 +460,7 @@ impl TokenStream { pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream { match nt { - Nonterminal::NtItem(item) => TokenStream::from_ast(item), Nonterminal::NtBlock(block) => TokenStream::from_ast(block), - Nonterminal::NtStmt(stmt) if let StmtKind::Empty = stmt.kind => { - // FIXME: Properly collect tokens for empty statements. - TokenStream::token_alone(token::Semi, stmt.span) - } - Nonterminal::NtStmt(stmt) => TokenStream::from_ast(stmt), Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr), Nonterminal::NtPath(path) => TokenStream::from_ast(path), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index d46a1bd3d3139..7f61b9a511027 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -141,8 +141,9 @@ impl CfgEval<'_> { Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap()) } Annotatable::Stmt(_) => { - let stmt = - parser.parse_stmt_without_recovery(false, ForceCollect::Yes)?.unwrap(); + let stmt = parser + .parse_stmt_without_recovery(false, ForceCollect::Yes, false)? + .unwrap(); Annotatable::Stmt(P(self.flat_map_stmt(stmt).pop().unwrap())) } Annotatable::Expr(_) => { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index bed500c303242..8f4150501dac1 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use rustc_ast::attr::MarkedAttrs; use rustc_ast::ptr::P; -use rustc_ast::token::Nonterminal; +use rustc_ast::token::MetaVarKind; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind}; @@ -17,7 +17,7 @@ use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult}; use rustc_feature::Features; use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools}; use rustc_parse::MACRO_ARGUMENTS; -use rustc_parse::parser::Parser; +use rustc_parse::parser::{ForceCollect, Parser}; use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::parse::ParseSess; use rustc_session::{Limit, Session}; @@ -1380,13 +1380,13 @@ pub fn parse_macro_name_and_helper_attrs( /// If this item looks like a specific enums from `rental`, emit a fatal error. /// See #73345 and #83125 for more details. /// FIXME(#73933): Remove this eventually. -fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) { +fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) { let name = item.ident.name; if name == sym::ProceduralMasqueradeDummyType && let ast::ItemKind::Enum(enum_def, _) = &item.kind && let [variant] = &*enum_def.variants && variant.ident.name == sym::Input - && let FileName::Real(real) = sess.source_map().span_to_filename(item.ident.span) + && let FileName::Real(real) = psess.source_map().span_to_filename(item.ident.span) && let Some(c) = real .local_path() .unwrap_or(Path::new("")) @@ -1404,7 +1404,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) { }; if crate_matches { - sess.dcx().emit_fatal(errors::ProcMacroBackCompat { + psess.dcx().emit_fatal(errors::ProcMacroBackCompat { crate_name: "rental".to_string(), fixed_version: "0.5.6".to_string(), }); @@ -1412,7 +1412,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) { } } -pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) { +pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, psess: &ParseSess) { let item = match ann { Annotatable::Item(item) => item, Annotatable::Stmt(stmt) => match &stmt.kind { @@ -1421,17 +1421,36 @@ pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &S }, _ => return, }; - pretty_printing_compatibility_hack(item, sess) + pretty_printing_compatibility_hack(item, psess) } -pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) { - let item = match nt { - Nonterminal::NtItem(item) => item, - Nonterminal::NtStmt(stmt) => match &stmt.kind { - ast::StmtKind::Item(item) => item, - _ => return, - }, +pub(crate) fn stream_pretty_printing_compatibility_hack( + kind: MetaVarKind, + stream: &TokenStream, + psess: &ParseSess, +) { + let item = match kind { + MetaVarKind::Item => { + let mut parser = Parser::new(psess, stream.clone(), None); + // No need to collect tokens for this simple check. + parser + .parse_item(ForceCollect::No) + .expect("failed to reparse item") + .expect("an actual item") + } + MetaVarKind::Stmt => { + let mut parser = Parser::new(psess, stream.clone(), None); + // No need to collect tokens for this simple check. + let stmt = parser + .parse_stmt(ForceCollect::No) + .expect("failed to reparse") + .expect("an actual stmt"); + match &stmt.kind { + ast::StmtKind::Item(item) => item.clone(), + _ => return, + } + } _ => return, }; - pretty_printing_compatibility_hack(item, sess) + pretty_printing_compatibility_hack(&item, psess) } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index ee7131f314b73..961c76e50ca7f 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,12 +1,12 @@ use std::mem; -use rustc_ast::ExprKind; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{ self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token, TokenKind, }; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; +use rustc_ast::{ExprKind, StmtKind}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; @@ -318,6 +318,18 @@ pub(super) fn transcribe<'a>( let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } + MatchedSingle(ParseNtResult::Item(item)) => { + mk_delimited(MetaVarKind::Item, TokenStream::from_ast(item)) + } + MatchedSingle(ParseNtResult::Stmt(stmt)) => { + let stream = if let StmtKind::Empty = stmt.kind { + // FIXME: Properly collect tokens for empty statements. + TokenStream::token_alone(token::Semi, stmt.span) + } else { + TokenStream::from_ast(stmt) + }; + mk_delimited(MetaVarKind::Stmt, stream) + } MatchedSingle(ParseNtResult::Pat(pat, pat_kind)) => { mk_delimited(MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat)) } diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index dca0516f9f3b3..bb77b9fa5bc8d 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -122,7 +122,7 @@ impl MultiItemModifier for DeriveProcMacro { // We had a lint for a long time, but now we just emit a hard error. // Eventually we might remove the special case hard error check // altogether. See #73345. - crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess); + crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.psess); let input = item.to_tokens(); let stream = { let _timer = diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 263df235b3ecc..396da61f75679 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -116,11 +116,25 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { - let delimiter = pm::Delimiter::from_internal(delim); + tokenstream::TokenTree::Delimited(span, _, delim, stream) => { + // We used to have an alternative behaviour for crates that + // needed it: a hack used to pass AST fragments to + // attribute and derive macros as a single nonterminal + // token instead of a token stream. Such token needs to be + // "unwrapped" and not represented as a delimited group. We + // had a lint for a long time, but now we just emit a hard + // error. Eventually we might remove the special case hard + // error check altogether. See #73345. + if let Delimiter::Invisible(InvisibleOrigin::MetaVar(kind)) = delim { + crate::base::stream_pretty_printing_compatibility_hack( + kind, + &stream, + rustc.psess(), + ); + } trees.push(TokenTree::Group(Group { - delimiter, - stream: Some(tts), + delimiter: pm::Delimiter::from_internal(delim), + stream: Some(stream), span: DelimSpan { open: span.open, close: span.close, @@ -280,15 +294,6 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { let stream = TokenStream::from_nonterminal_ast(&nt); - // We used to have an alternative behaviour for crates that - // needed it: a hack used to pass AST fragments to - // attribute and derive macros as a single nonterminal - // token instead of a token stream. Such token needs to be - // "unwrapped" and not represented as a delimited group. We - // had a lint for a long time, but now we just emit a hard - // error. Eventually we might remove the special case hard - // error check altogether. See #73345. - crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess); trees.push(TokenTree::Group(Group { delimiter: pm::Delimiter::None, stream: Some(stream), diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index aa5e9586daf96..0540eb22b8ecb 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3072,7 +3072,7 @@ impl<'a> Parser<'a> { } self.restore_snapshot(pre_pat_snapshot); - match self.parse_stmt_without_recovery(true, ForceCollect::No) { + match self.parse_stmt_without_recovery(true, ForceCollect::No, false) { // Consume statements for as long as possible. Ok(Some(stmt)) => { stmts.push(stmt); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c97e1044dcf63..e59a7c620f8c0 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -21,10 +21,11 @@ use tracing::debug; use super::diagnostics::{ConsumeClosingDelim, dummy_arg}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{ - AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos, + AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Recovered, Trailing, + UsePreAttrPos, }; use crate::errors::{self, MacroExpandsToAdtField}; -use crate::{fluent_generated as fluent, maybe_whole}; +use crate::fluent_generated as fluent; impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. @@ -143,10 +144,13 @@ impl<'a> Parser<'a> { fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option> { - maybe_whole!(self, NtItem, |item| { + if let Some(item) = + self.eat_metavar_seq(MetaVarKind::Item, |this| this.parse_item(ForceCollect::Yes)) + { + let mut item = item.expect("an actual item"); attrs.prepend_to_nt_inner(&mut item.attrs); - Some(item.into_inner()) - }); + return Ok(Some(item.into_inner())); + } self.collect_tokens(None, attrs, force_collect, |this, mut attrs| { let lo = this.token.span; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 9800a376699d3..7d8aabdbd3963 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1081,10 +1081,12 @@ impl<'a> Parser<'a> { let initial_semicolon = self.token.span; while self.eat(&TokenKind::Semi) { - let _ = self.parse_stmt_without_recovery(false, ForceCollect::No).unwrap_or_else(|e| { - e.cancel(); - None - }); + let _ = self + .parse_stmt_without_recovery(false, ForceCollect::No, false) + .unwrap_or_else(|e| { + e.cancel(); + None + }); } expect_err @@ -1763,6 +1765,8 @@ pub enum ParseNtResult { Tt(TokenTree), Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), + Item(P), + Stmt(P), Pat(P, NtPatKind), Ty(P), Vis(P), diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index e0ee24e75822f..75fb432e7b568 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -47,13 +47,12 @@ impl<'a> Parser<'a> { /// Old variant of `may_be_ident`. Being phased out. fn nt_may_be_ident(nt: &Nonterminal) -> bool { match nt { - NtStmt(_) - | NtExpr(_) + NtExpr(_) | NtLiteral(_) // `true`, `false` | NtMeta(_) | NtPath(_) => true, - NtItem(_) | NtBlock(_) => false, + NtBlock(_) => false, } } @@ -96,8 +95,8 @@ impl<'a> Parser<'a> { token::OpenDelim(Delimiter::Brace) => true, token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { - NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, - NtItem(_) | NtMeta(_) | NtPath(_) => false, + NtBlock(_) | NtExpr(_) | NtLiteral(_) => true, + NtMeta(_) | NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -147,7 +146,7 @@ impl<'a> Parser<'a> { // Note that TT is treated differently to all the others. NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())), NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { - Some(item) => NtItem(item), + Some(item) => return Ok(ParseNtResult::Item(item)), None => { return Err(self .dcx() @@ -160,7 +159,7 @@ impl<'a> Parser<'a> { NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) } NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { - Some(s) => NtStmt(P(s)), + Some(stmt) => return Ok(ParseNtResult::Stmt(P(stmt))), None => { return Err(self .dcx() diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 190cd9ed0610f..1351af406b27c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -4,7 +4,7 @@ use std::mem; use ast::Label; use rustc_ast as ast; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, TokenKind}; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; use rustc_ast::util::classify::{self, TrailingBrace}; use rustc_ast::{ AttrStyle, AttrVec, Block, BlockCheckMode, DUMMY_NODE_ID, Expr, ExprKind, HasAttrs, Local, @@ -33,8 +33,8 @@ impl<'a> Parser<'a> { /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of /// whether or not we have attributes. // Public for rustfmt usage. - pub(super) fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option> { - Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| { + pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option> { + Ok(self.parse_stmt_without_recovery(false, force_collect, false).unwrap_or_else(|e| { e.emit(); self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); None @@ -42,23 +42,27 @@ impl<'a> Parser<'a> { } /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of - /// whether or not we have attributes. - // Public for `cfg_eval` macro expansion. + /// whether or not we have attributes. If `force_full_expr` is true, parses the stmt without + /// using `Restriction::STMT_EXPR`. Public for `cfg_eval` macro expansion. pub fn parse_stmt_without_recovery( &mut self, capture_semi: bool, force_collect: ForceCollect, + force_full_expr: bool, ) -> PResult<'a, Option> { let pre_attr_pos = self.collect_pos(); let attrs = self.parse_outer_attributes()?; let lo = self.token.span; - maybe_whole!(self, NtStmt, |stmt| { + if let Some(stmt) = self.eat_metavar_seq(MetaVarKind::Stmt, |this| { + this.parse_stmt_without_recovery(false, ForceCollect::Yes, false) + }) { + let mut stmt = stmt.expect("an actual statement"); stmt.visit_attrs(|stmt_attrs| { attrs.prepend_to_nt_inner(stmt_attrs); }); - Some(stmt.into_inner()) - }); + return Ok(Some(stmt)); + } if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) { self.bump(); @@ -147,12 +151,14 @@ impl<'a> Parser<'a> { } else if self.token != token::CloseDelim(Delimiter::Brace) { // Remainder are line-expr stmts. This is similar to the `parse_stmt_path_start` case // above. + let restrictions = + if force_full_expr { Restrictions::empty() } else { Restrictions::STMT_EXPR }; let e = self.collect_tokens( Some(pre_attr_pos), AttrWrapper::empty(), force_collect, |this, _empty_attrs| { - let (expr, _) = this.parse_expr_res(Restrictions::STMT_EXPR, attrs)?; + let (expr, _) = this.parse_expr_res(restrictions, attrs)?; Ok((expr, Trailing::No, UsePreAttrPos::Yes)) }, )?; @@ -229,11 +235,15 @@ impl<'a> Parser<'a> { let mac = P(MacCall { path, args }); let kind = if (style == MacStmtStyle::Braces - && self.token != token::Dot - && self.token != token::Question) - || self.token == token::Semi - || self.token == token::Eof - { + && !matches!(self.token.kind, token::Dot | token::Question)) + || matches!( + self.token.kind, + token::Semi + | token::Eof + | token::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Stmt + ))) + ) { StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None })) } else { // Since none of the above applied, this is an expression statement macro. @@ -486,7 +496,7 @@ impl<'a> Parser<'a> { // bar; // // which is valid in other languages, but not Rust. - match self.parse_stmt_without_recovery(false, ForceCollect::No) { + match self.parse_stmt_without_recovery(false, ForceCollect::No, false) { // If the next token is an open brace, e.g., we have: // // if expr other_expr { @@ -750,10 +760,24 @@ impl<'a> Parser<'a> { &mut self, recover: AttemptLocalParseRecovery, ) -> PResult<'a, Option> { - // Skip looking for a trailing semicolon when we have an interpolated statement. - maybe_whole!(self, NtStmt, |stmt| Some(stmt.into_inner())); + // Skip looking for a trailing semicolon when we have a metavar seq. + if let Some(stmt) = self.eat_metavar_seq(MetaVarKind::Stmt, |this| { + // Why pass `true` for `force_full_expr`? Statement expressions are less expressive + // than "full" expressions, due to the `STMT_EXPR` restriction, and sometimes need + // parentheses. E.g. the "full" expression `match paren_around_match {} | true` when + // used in statement context must be written `(match paren_around_match {} | true)`. + // However, if the expression we are parsing in this statement context was pasted by a + // declarative macro, it may have come from a "full" expression context, and lack + // these parentheses. So we lift the `STMT_EXPR` restriction to ensure the statement + // will reparse successfully. + this.parse_stmt_without_recovery(false, ForceCollect::No, true) + }) { + let stmt = stmt.expect("an actual statement"); + return Ok(Some(stmt)); + } - let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else { + let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No, false)? + else { return Ok(None); }; diff --git a/tests/ui/macros/macro-stmt-2.rs b/tests/ui/macros/macro-stmt-2.rs new file mode 100644 index 0000000000000..663d8ddc4843a --- /dev/null +++ b/tests/ui/macros/macro-stmt-2.rs @@ -0,0 +1,11 @@ +//@ check-pass +// +// This shows a tricky case for #124141, where `declare!(_x)` was incorrectly +// being categorised as a `StmtKind::Expr` instead of a `StmtKind::MacCall` in +// `parse_stmt_mac`. + +macro_rules! as_stmt { ($s:stmt) => { $s }; } + +macro_rules! declare { ($name:ident) => { let $name = 0u32; }; } + +fn main() { as_stmt!(declare!(_x)); } diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs index a655b66510311..f71a1ae50cc19 100644 --- a/tests/ui/macros/nonterminal-matching.rs +++ b/tests/ui/macros/nonterminal-matching.rs @@ -16,7 +16,7 @@ macro complex_nonterminal($nt_item: item) { struct S; } - n!(a $nt_item b); //~ ERROR no rules expected item `enum E {}` + n!(a $nt_item b); //~ ERROR no rules expected `item` metavariable } simple_nonterminal!(a, 'a, (x, y, z)); // OK @@ -32,7 +32,7 @@ macro_rules! foo { (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3` (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4` (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected path `a::b::c` - (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected statement `let abc = 0` + (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected `stmt` metavariable } macro_rules! bar { diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index e283dfcb8fdc4..6e057ac3317f0 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -1,4 +1,4 @@ -error: no rules expected item `enum E {}` +error: no rules expected `item` metavariable --> $DIR/nonterminal-matching.rs:19:10 | LL | macro n(a $nt_item b) { @@ -10,7 +10,7 @@ LL | n!(a $nt_item b); LL | complex_nonterminal!(enum E {}); | ------------------------------- in this macro invocation | -note: while trying to match item `enum E {}` +note: while trying to match `item` metavariable --> $DIR/nonterminal-matching.rs:15:15 | LL | macro n(a $nt_item b) { @@ -89,7 +89,7 @@ LL | (path a::b::c) => {}; = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected statement `let abc = 0` +error: no rules expected `stmt` metavariable --> $DIR/nonterminal-matching.rs:35:35 | LL | (stmt $x:stmt) => { bar!(stmt $x); }; diff --git a/tests/ui/proc-macro/expand-to-derive.stdout b/tests/ui/proc-macro/expand-to-derive.stdout index 81fc52ea22d7b..3a16f23ecf23c 100644 --- a/tests/ui/proc-macro/expand-to-derive.stdout +++ b/tests/ui/proc-macro/expand-to-derive.stdout @@ -44,52 +44,58 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Group { delimiter: Brace, stream: TokenStream [ - Punct { - ch: '#', - spacing: Alone, - span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "rustc_dummy", - span: $DIR/expand-to-derive.rs:27:28: 27:39 (#0), - }, - ], - span: $DIR/expand-to-derive.rs:27:6: 27:41 (#0), - }, - Ident { - ident: "struct", - span: $DIR/expand-to-derive.rs:28:5: 28:11 (#0), - }, - Ident { - ident: "Inner", - span: $DIR/expand-to-derive.rs:28:12: 28:17 (#0), - }, Group { - delimiter: Brace, + delimiter: None, stream: TokenStream [ - Ident { - ident: "other_inner_field", - span: $DIR/expand-to-derive.rs:30:9: 30:26 (#0), - }, Punct { - ch: ':', + ch: '#', spacing: Alone, - span: $DIR/expand-to-derive.rs:30:26: 30:27 (#0), + span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/expand-to-derive.rs:27:28: 27:39 (#0), + }, + ], + span: $DIR/expand-to-derive.rs:27:6: 27:41 (#0), }, Ident { - ident: "u8", - span: $DIR/expand-to-derive.rs:30:28: 30:30 (#0), + ident: "struct", + span: $DIR/expand-to-derive.rs:28:5: 28:11 (#0), }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/expand-to-derive.rs:30:30: 30:31 (#0), + Ident { + ident: "Inner", + span: $DIR/expand-to-derive.rs:28:12: 28:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "other_inner_field", + span: $DIR/expand-to-derive.rs:30:9: 30:26 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/expand-to-derive.rs:30:26: 30:27 (#0), + }, + Ident { + ident: "u8", + span: $DIR/expand-to-derive.rs:30:28: 30:30 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/expand-to-derive.rs:30:30: 30:31 (#0), + }, + ], + span: $DIR/expand-to-derive.rs:28:18: 31:6 (#0), }, ], - span: $DIR/expand-to-derive.rs:28:18: 31:6 (#0), + span: $DIR/expand-to-derive.rs:19:17: 19:22 (#3), }, Literal { kind: Integer, From d4fbe1f3f6c125a73b2095edd63522aa00d9a84f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 24 Sep 2024 15:24:26 +1000 Subject: [PATCH 05/12] More denesting of invisibly-delimited groups. This time when converting them to proc-macro `Group` form. --- .../rustc_expand/src/proc_macro_server.rs | 20 ++++++++++++++++++- tests/ui/proc-macro/nodelim-groups.rs | 13 ++++++++++++ tests/ui/proc-macro/nodelim-groups.stdout | 15 ++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 396da61f75679..c3470ffc27990 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -116,7 +116,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { + tokenstream::TokenTree::Delimited(span, _, mut delim, mut stream) => { // We used to have an alternative behaviour for crates that // needed it: a hack used to pass AST fragments to // attribute and derive macros as a single nonterminal @@ -132,6 +132,24 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { print_bang_consume!($e) }; } +macro_rules! m4 { ($e:expr) => { m5!($e); } } +macro_rules! m3 { ($e:expr) => { m4!($e); } } +macro_rules! m2 { ($e:expr) => { m3!($e); } } +macro_rules! m1 { ($e:expr) => { m2!($e); } } + +fn f() { + m1!(123); } diff --git a/tests/ui/proc-macro/nodelim-groups.stdout b/tests/ui/proc-macro/nodelim-groups.stdout index cdf851b535aa5..61001035c26cf 100644 --- a/tests/ui/proc-macro/nodelim-groups.stdout +++ b/tests/ui/proc-macro/nodelim-groups.stdout @@ -165,3 +165,18 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ span: $DIR/nodelim-groups.rs:16:52: 16:59 (#8), }, ] +PRINT-BANG INPUT (DISPLAY): 123 +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "123", + suffix: None, + span: $DIR/nodelim-groups.rs:34:9: 34:12 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:27:54: 27:56 (#16), + }, +] From f5acfd7f4227447b6dbfd4ed047176d8d30b80ad Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 16:22:02 +1000 Subject: [PATCH 06/12] Remove `NtMeta`. Note: there was an existing code path involving `Interpolated` in `MetaItem::from_tokens` that was dead. This commit transfers that to the new form, but puts an `unreachable!` call inside it. --- compiler/rustc_ast/src/ast_traits.rs | 2 -- compiler/rustc_ast/src/attr/mod.rs | 12 ++++++-- compiler/rustc_ast/src/mut_visit.rs | 6 ---- compiler/rustc_ast/src/token.rs | 7 +---- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 3 ++ compiler/rustc_parse/messages.ftl | 2 +- compiler/rustc_parse/src/errors.rs | 2 +- compiler/rustc_parse/src/parser/attr.rs | 30 +++++++++++-------- compiler/rustc_parse/src/parser/expr.rs | 1 - compiler/rustc_parse/src/parser/mod.rs | 1 + .../rustc_parse/src/parser/nonterminal.rs | 7 +++-- tests/ui/attributes/nonterminal-expansion.rs | 2 +- .../attributes/nonterminal-expansion.stderr | 2 +- .../cfg-attr-syntax-validation.rs | 4 +-- .../cfg-attr-syntax-validation.stderr | 4 +-- tests/ui/parser/attribute/attr-bad-meta-4.rs | 4 +-- .../parser/attribute/attr-bad-meta-4.stderr | 4 +-- .../parser/attribute/attr-unquoted-ident.rs | 2 +- .../attribute/attr-unquoted-ident.stderr | 2 +- 20 files changed, 50 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 26ae64a4b6886..dd04a6491b829 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -200,7 +200,6 @@ impl HasTokens for Nonterminal { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), - Nonterminal::NtMeta(attr_item) => attr_item.tokens(), Nonterminal::NtPath(path) => path.tokens(), Nonterminal::NtBlock(block) => block.tokens(), } @@ -208,7 +207,6 @@ impl HasTokens for Nonterminal { fn tokens_mut(&mut self) -> Option<&mut Option> { match self { Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), - Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), Nonterminal::NtPath(path) => path.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 888b13efa31a3..30ea742fa0c42 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -15,7 +15,7 @@ use crate::ast::{ NormalAttr, Path, PathSegment, Safety, }; use crate::ptr::P; -use crate::token::{self, CommentKind, Delimiter, Token}; +use crate::token::{self, CommentKind, Delimiter, InvisibleOrigin, MetaVarKind, Token}; use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenTree}; use crate::util::comments; use crate::util::literal::escape_string_symbol; @@ -411,10 +411,18 @@ impl MetaItem { Path { span, segments, tokens: None } } Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt { - token::Nonterminal::NtMeta(item) => return item.meta(item.path.span), token::Nonterminal::NtPath(path) => (**path).clone(), _ => return None, }, + Some(TokenTree::Delimited( + _span, + _spacing, + Delimiter::Invisible(InvisibleOrigin::MetaVar(MetaVarKind::Meta)), + _stream, + )) => { + // This path is currently unreachable in the test suite. + unreachable!() + } Some(TokenTree::Token( Token { kind: token::OpenDelim(_) | token::CloseDelim(_), .. }, _, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 86ee6425aa425..64bc3da06ac12 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -868,12 +868,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { token::NtBlock(block) => vis.visit_block(block), token::NtExpr(expr) => vis.visit_expr(expr), token::NtLiteral(expr) => vis.visit_expr(expr), - token::NtMeta(item) => { - let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut(); - vis.visit_path(path); - visit_attr_args(vis, args); - visit_lazy_tts(vis, tokens); - } token::NtPath(path) => vis.visit_path(path), } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index ffe3a75b1f314..918313603a959 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -657,7 +657,6 @@ impl Token { matches!(&**nt, | NtExpr(..) | NtLiteral(..) - | NtMeta(..) | NtPath(..) ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( @@ -860,6 +859,7 @@ impl Token { /// Is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? pub fn is_whole_expr(&self) -> bool { + #[allow(irrefutable_let_patterns)] // FIXME: temporary if let Interpolated(nt) = &self.kind && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = &**nt { @@ -1066,8 +1066,6 @@ pub enum Nonterminal { NtBlock(P), NtExpr(P), NtLiteral(P), - /// Stuff inside brackets for attributes - NtMeta(P), NtPath(P), } @@ -1159,7 +1157,6 @@ impl Nonterminal { match self { NtBlock(block) => block.span, NtExpr(expr) | NtLiteral(expr) => expr.span, - NtMeta(attr_item) => attr_item.span(), NtPath(path) => path.span, } } @@ -1169,7 +1166,6 @@ impl Nonterminal { NtBlock(..) => "block", NtExpr(..) => "expression", NtLiteral(..) => "literal", - NtMeta(..) => "attribute", NtPath(..) => "path", } } @@ -1191,7 +1187,6 @@ impl fmt::Debug for Nonterminal { NtBlock(..) => f.pad("NtBlock(..)"), NtExpr(..) => f.pad("NtExpr(..)"), NtLiteral(..) => f.pad("NtLiteral(..)"), - NtMeta(..) => f.pad("NtMeta(..)"), NtPath(..) => f.pad("NtPath(..)"), } } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 20774362592f3..b92a82ddb7320 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -461,7 +461,6 @@ impl TokenStream { pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream { match nt { Nonterminal::NtBlock(block) => TokenStream::from_ast(block), - Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr), Nonterminal::NtPath(path) => TokenStream::from_ast(path), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 961c76e50ca7f..206b4ef9f3b22 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -336,6 +336,9 @@ pub(super) fn transcribe<'a>( MatchedSingle(ParseNtResult::Ty(ty)) => { mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty)) } + MatchedSingle(ParseNtResult::Meta(meta)) => { + mk_delimited(MetaVarKind::Meta, TokenStream::from_ast(meta)) + } MatchedSingle(ParseNtResult::Vis(vis)) => { mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 8c4f669c332b2..1171cacaa6985 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -424,7 +424,7 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction -parse_invalid_meta_item = expected unsuffixed literal, found `{$token}` +parse_invalid_meta_item = expected unsuffixed literal, found {$descr} .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal parse_invalid_offset_of = offset_of expects dot-separated field and variant names diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 9bdb99dc00077..7e9737acb6450 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1025,7 +1025,7 @@ pub(crate) struct SuffixedLiteralInAttribute { pub(crate) struct InvalidMetaItem { #[primary_span] pub span: Span, - pub token: Token, + pub descr: String, #[subdiagnostic] pub quote_ident_sugg: Option, } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index b6fa209958831..5b6bb3887d7ed 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,6 +1,6 @@ use rustc_ast as ast; use rustc_ast::attr; -use rustc_ast::token::{self, Delimiter}; +use rustc_ast::token::{self, Delimiter, MetaVarKind}; use rustc_errors::codes::*; use rustc_errors::{Diag, PResult}; use rustc_span::symbol::kw; @@ -12,7 +12,7 @@ use super::{ AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle, Trailing, UsePreAttrPos, }; -use crate::{errors, fluent_generated as fluent, maybe_whole}; +use crate::{errors, fluent_generated as fluent}; // Public for rustfmt usage #[derive(Debug)] @@ -272,7 +272,11 @@ impl<'a> Parser<'a> { /// PATH `=` UNSUFFIXED_LIT /// The delimiters or `=` are still put into the resulting token stream. pub fn parse_attr_item(&mut self, force_collect: ForceCollect) -> PResult<'a, ast::AttrItem> { - maybe_whole!(self, NtMeta, |attr| attr.into_inner()); + if let Some(item) = + self.eat_metavar_seq(MetaVarKind::Meta, |this| this.parse_attr_item(force_collect)) + { + return Ok(item); + } // Attr items don't have attributes. self.collect_tokens(None, AttrWrapper::empty(), force_collect, |this, _empty_attrs| { @@ -399,18 +403,18 @@ impl<'a> Parser<'a> { &mut self, unsafe_allowed: AllowLeadingUnsafe, ) -> PResult<'a, ast::MetaItem> { - // We can't use `maybe_whole` here because it would bump in the `None` - // case, which we don't want. - if let token::Interpolated(nt) = &self.token.kind - && let token::NtMeta(attr_item) = &**nt + // Snapshot the parser so we can backtrack in the case where `attr_item.meta()` fails. + let mut snapshot = self.create_snapshot_for_diagnostic(); + if let Some(attr_item) = snapshot + .eat_metavar_seq(MetaVarKind::Meta, |this| this.parse_attr_item(ForceCollect::No)) { - match attr_item.meta(attr_item.path.span) { + return match attr_item.meta(attr_item.path.span) { Some(meta) => { - self.bump(); - return Ok(meta); + self.restore_snapshot(snapshot); + Ok(meta) } - None => self.unexpected()?, - } + None => self.unexpected_any(), + }; } let lo = self.token.span; @@ -467,7 +471,7 @@ impl<'a> Parser<'a> { let mut err = errors::InvalidMetaItem { span: self.token.span, - token: self.token.clone(), + descr: super::token_descr(&self.token), quote_ident_sugg: None, }; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0540eb22b8ecb..26678669278c2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1399,7 +1399,6 @@ impl<'a> Parser<'a> { self.bump(); return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); } - _ => {} }; } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 7d8aabdbd3963..a30d45a14ce49 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1769,6 +1769,7 @@ pub enum ParseNtResult { Stmt(P), Pat(P, NtPatKind), Ty(P), + Meta(P), Vis(P), /// This variant will eventually be removed, along with `Token::Interpolate`. diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 75fb432e7b568..0fc167e6bd752 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -49,7 +49,6 @@ impl<'a> Parser<'a> { match nt { NtExpr(_) | NtLiteral(_) // `true`, `false` - | NtMeta(_) | NtPath(_) => true, NtBlock(_) => false, @@ -96,7 +95,7 @@ impl<'a> Parser<'a> { token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { NtBlock(_) | NtExpr(_) | NtLiteral(_) => true, - NtMeta(_) | NtPath(_) => false, + NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -205,7 +204,9 @@ impl<'a> Parser<'a> { NonterminalKind::Path => { NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?)) } - NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)), + NonterminalKind::Meta => { + return Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?))); + } NonterminalKind::Vis => { return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| { this.parse_visibility(FollowedByType::Yes) diff --git a/tests/ui/attributes/nonterminal-expansion.rs b/tests/ui/attributes/nonterminal-expansion.rs index 1b2e92a31703c..796c81a5cdf29 100644 --- a/tests/ui/attributes/nonterminal-expansion.rs +++ b/tests/ui/attributes/nonterminal-expansion.rs @@ -5,7 +5,7 @@ macro_rules! pass_nonterminal { ($n:expr) => { #[repr(align($n))] - //~^ ERROR expected unsuffixed literal, found `n!()` + //~^ ERROR expected unsuffixed literal, found expression `n!()` struct S; }; } diff --git a/tests/ui/attributes/nonterminal-expansion.stderr b/tests/ui/attributes/nonterminal-expansion.stderr index b640575d17dc7..15a61a642609b 100644 --- a/tests/ui/attributes/nonterminal-expansion.stderr +++ b/tests/ui/attributes/nonterminal-expansion.stderr @@ -1,4 +1,4 @@ -error: expected unsuffixed literal, found `n!()` +error: expected unsuffixed literal, found expression `n!()` --> $DIR/nonterminal-expansion.rs:7:22 | LL | #[repr(align($n))] diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index d885281249203..9a041557c7cc9 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -28,8 +28,8 @@ struct S9; macro_rules! generate_s10 { ($expr: expr) => { #[cfg(feature = $expr)] - //~^ ERROR expected unsuffixed literal, found `concat!("nonexistent")` - //~| ERROR expected unsuffixed literal, found `concat!("nonexistent")` + //~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` + //~| ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` struct S10; } } diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 3dd0823389cde..21a3712d9391a 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")] | | | help: consider removing the prefix -error: expected unsuffixed literal, found `concat!("nonexistent")` +error: expected unsuffixed literal, found expression `concat!("nonexistent")` --> $DIR/cfg-attr-syntax-validation.rs:30:25 | LL | #[cfg(feature = $expr)] @@ -65,7 +65,7 @@ LL | generate_s10!(concat!("nonexistent")); | = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected unsuffixed literal, found `concat!("nonexistent")` +error: expected unsuffixed literal, found expression `concat!("nonexistent")` --> $DIR/cfg-attr-syntax-validation.rs:30:25 | LL | #[cfg(feature = $expr)] diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs index 2a69ae5ac0639..2d0c6dbb50ab8 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.rs +++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs @@ -1,8 +1,8 @@ macro_rules! mac { ($attr_item: meta) => { #[cfg($attr_item)] - //~^ ERROR expected unsuffixed literal, found `an(arbitrary token stream)` - //~| ERROR expected unsuffixed literal, found `an(arbitrary token stream)` + //~^ ERROR expected unsuffixed literal, found `meta` metavariable + //~| ERROR expected unsuffixed literal, found `meta` metavariable struct S; } } diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr index 192be28db3fb8..dea574fd36d5b 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr @@ -4,7 +4,7 @@ error: expected unsuffixed literal, found `-` LL | #[cfg(feature = -1)] | ^ -error: expected unsuffixed literal, found `an(arbitrary token stream)` +error: expected unsuffixed literal, found `meta` metavariable --> $DIR/attr-bad-meta-4.rs:3:15 | LL | #[cfg($attr_item)] @@ -15,7 +15,7 @@ LL | mac!(an(arbitrary token stream)); | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected unsuffixed literal, found `an(arbitrary token stream)` +error: expected unsuffixed literal, found `meta` metavariable --> $DIR/attr-bad-meta-4.rs:3:15 | LL | #[cfg($attr_item)] diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.rs b/tests/ui/parser/attribute/attr-unquoted-ident.rs index 5b15b8d69fcf8..396265f715e97 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.rs +++ b/tests/ui/parser/attribute/attr-unquoted-ident.rs @@ -19,7 +19,7 @@ fn main() { macro_rules! make { ($name:ident) => { #[doc(alias = $name)] pub struct S; } - //~^ ERROR expected unsuffixed literal, found `nickname` + //~^ ERROR expected unsuffixed literal, found identifier `nickname` } make!(nickname); //~ NOTE in this expansion diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr index e0f99459c44e7..2d7997f1aea5a 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.stderr +++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr @@ -20,7 +20,7 @@ help: surround the identifier with quotation marks to make it into a string lite LL | #[cfg(key="foo bar baz")] | + + -error: expected unsuffixed literal, found `nickname` +error: expected unsuffixed literal, found identifier `nickname` --> $DIR/attr-unquoted-ident.rs:21:38 | LL | ($name:ident) => { #[doc(alias = $name)] pub struct S; } From 6af929b76cf55cffc11fb7bbfe7259dd1708ee90 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 20:09:37 +1000 Subject: [PATCH 07/12] Remove `NtPath`. --- compiler/rustc_ast/src/ast_traits.rs | 2 -- compiler/rustc_ast/src/attr/mod.rs | 8 ++--- compiler/rustc_ast/src/mut_visit.rs | 1 - compiler/rustc_ast/src/token.rs | 32 +++++-------------- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 3 ++ compiler/rustc_parse/src/parser/expr.rs | 12 +++---- compiler/rustc_parse/src/parser/mod.rs | 1 + .../rustc_parse/src/parser/nonterminal.rs | 7 ++-- compiler/rustc_parse/src/parser/path.rs | 9 ++++-- tests/ui/imports/import-prefix-macro-2.rs | 2 +- tests/ui/imports/import-prefix-macro-2.stderr | 4 +-- tests/ui/macros/nonterminal-matching.rs | 2 +- tests/ui/macros/nonterminal-matching.stderr | 2 +- 14 files changed, 36 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index dd04a6491b829..044569e451253 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -200,14 +200,12 @@ impl HasTokens for Nonterminal { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), - Nonterminal::NtPath(path) => path.tokens(), Nonterminal::NtBlock(block) => block.tokens(), } } fn tokens_mut(&mut self) -> Option<&mut Option> { match self { Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), - Nonterminal::NtPath(path) => path.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), } } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 30ea742fa0c42..8cca046abdb67 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -410,14 +410,12 @@ impl MetaItem { let span = span.with_hi(segments.last().unwrap().ident.span.hi()); Path { span, segments, tokens: None } } - Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt { - token::Nonterminal::NtPath(path) => (**path).clone(), - _ => return None, - }, Some(TokenTree::Delimited( _span, _spacing, - Delimiter::Invisible(InvisibleOrigin::MetaVar(MetaVarKind::Meta)), + Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Meta | MetaVarKind::Path, + )), _stream, )) => { // This path is currently unreachable in the test suite. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 64bc3da06ac12..28b329a9677ec 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -868,7 +868,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { token::NtBlock(block) => vis.visit_block(block), token::NtExpr(expr) => vis.visit_expr(expr), token::NtLiteral(expr) => vis.visit_expr(expr), - token::NtPath(path) => vis.visit_path(path), } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 918313603a959..ab1ab5facd89b 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -620,8 +620,7 @@ impl Token { matches!(&**nt, NtBlock(..) | NtExpr(..) | - NtLiteral(..) | - NtPath(..) + NtLiteral(..) ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Block | @@ -657,7 +656,6 @@ impl Token { matches!(&**nt, | NtExpr(..) | NtLiteral(..) - | NtPath(..) ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | @@ -686,7 +684,6 @@ impl Token { Lifetime(..) | // lifetime bound in trait object Lt | BinOp(Shl) | // associated path PathSep => true, // global path - Interpolated(ref nt) => matches!(&**nt, NtPath(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Ty | MetaVarKind::Path @@ -845,28 +842,19 @@ impl Token { self.ident().is_some_and(|(ident, _)| ident.name == name) } - /// Returns `true` if the token is an interpolated path. - fn is_whole_path(&self) -> bool { - if let Interpolated(nt) = &self.kind - && let NtPath(..) = &**nt - { - return true; - } - - false - } - /// Is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? pub fn is_whole_expr(&self) -> bool { #[allow(irrefutable_let_patterns)] // FIXME: temporary if let Interpolated(nt) = &self.kind - && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = &**nt + && let NtExpr(_) | NtLiteral(_) | NtBlock(_) = &**nt { - return true; + true + } else if matches!(self.is_metavar_seq(), Some(MetaVarKind::Path)) { + true + } else { + false } - - false } /// Is the token an interpolated block (`$b:block`)? @@ -892,7 +880,7 @@ impl Token { pub fn is_path_start(&self) -> bool { self == &PathSep || self.is_qpath_start() - || self.is_whole_path() + || matches!(self.is_metavar_seq(), Some(MetaVarKind::Path)) || self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident() } @@ -1066,7 +1054,6 @@ pub enum Nonterminal { NtBlock(P), NtExpr(P), NtLiteral(P), - NtPath(P), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] @@ -1157,7 +1144,6 @@ impl Nonterminal { match self { NtBlock(block) => block.span, NtExpr(expr) | NtLiteral(expr) => expr.span, - NtPath(path) => path.span, } } @@ -1166,7 +1152,6 @@ impl Nonterminal { NtBlock(..) => "block", NtExpr(..) => "expression", NtLiteral(..) => "literal", - NtPath(..) => "path", } } } @@ -1187,7 +1172,6 @@ impl fmt::Debug for Nonterminal { NtBlock(..) => f.pad("NtBlock(..)"), NtExpr(..) => f.pad("NtExpr(..)"), NtLiteral(..) => f.pad("NtLiteral(..)"), - NtPath(..) => f.pad("NtPath(..)"), } } } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index b92a82ddb7320..51acc08a568e1 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -461,7 +461,6 @@ impl TokenStream { pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream { match nt { Nonterminal::NtBlock(block) => TokenStream::from_ast(block), - Nonterminal::NtPath(path) => TokenStream::from_ast(path), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 206b4ef9f3b22..314d43370bab9 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -339,6 +339,9 @@ pub(super) fn transcribe<'a>( MatchedSingle(ParseNtResult::Meta(meta)) => { mk_delimited(MetaVarKind::Meta, TokenStream::from_ast(meta)) } + MatchedSingle(ParseNtResult::Path(path)) => { + mk_delimited(MetaVarKind::Path, TokenStream::from_ast(path)) + } MatchedSingle(ParseNtResult::Vis(vis)) => { mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 26678669278c2..5a262fec5df63 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4,7 +4,7 @@ use core::mem; use core::ops::ControlFlow; use ast::mut_visit::{self, MutVisitor}; -use ast::token::IdentIsRaw; +use ast::token::{IdentIsRaw, MetaVarKind}; use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -1382,6 +1382,7 @@ impl<'a> Parser<'a> { fn parse_expr_bottom(&mut self) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, true); + let span = self.token.span; if let token::Interpolated(nt) = &self.token.kind { match &**nt { token::NtExpr(e) | token::NtLiteral(e) => { @@ -1389,17 +1390,16 @@ impl<'a> Parser<'a> { self.bump(); return Ok(e); } - token::NtPath(path) => { - let path = (**path).clone(); - self.bump(); - return Ok(self.mk_expr(self.prev_token.span, ExprKind::Path(None, path))); - } token::NtBlock(block) => { let block = block.clone(); self.bump(); return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); } }; + } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| { + this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type)) + }) { + return Ok(self.mk_expr(span, ExprKind::Path(None, path))); } // Outer attributes are already parsed and will be diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index a30d45a14ce49..573d61d13ffbf 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1770,6 +1770,7 @@ pub enum ParseNtResult { Pat(P, NtPatKind), Ty(P), Meta(P), + Path(P), Vis(P), /// This variant will eventually be removed, along with `Token::Interpolate`. diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 0fc167e6bd752..daa4b3c5910fa 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -49,7 +49,7 @@ impl<'a> Parser<'a> { match nt { NtExpr(_) | NtLiteral(_) // `true`, `false` - | NtPath(_) => true, + => true, NtBlock(_) => false, } @@ -95,7 +95,6 @@ impl<'a> Parser<'a> { token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { NtBlock(_) | NtExpr(_) | NtLiteral(_) => true, - NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -202,7 +201,9 @@ impl<'a> Parser<'a> { }; } NonterminalKind::Path => { - NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?)) + return Ok(ParseNtResult::Path(P( + self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))? + ))); } NonterminalKind::Meta => { return Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?))); diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 950d633435f9f..518669d104336 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -16,9 +16,8 @@ use tracing::debug; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{Parser, Restrictions, TokenType}; -use crate::errors::{PathSingleColon, PathTripleColon}; +use crate::errors::{self, PathSingleColon, PathTripleColon}; use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma}; -use crate::{errors, maybe_whole}; /// Specifies how to parse a path. #[derive(Copy, Clone, PartialEq)] @@ -196,7 +195,11 @@ impl<'a> Parser<'a> { } }; - maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner())); + if let Some(path) = + self.eat_metavar_seq(MetaVarKind::Path, |this| this.parse_path(PathStyle::Type)) + { + return Ok(reject_generics_if_mod_style(self, path)); + } if let Some(MetaVarKind::Ty) = self.token.is_metavar_seq() { let mut snapshot = self.create_snapshot_for_diagnostic(); diff --git a/tests/ui/imports/import-prefix-macro-2.rs b/tests/ui/imports/import-prefix-macro-2.rs index 952d161e83fac..17898c0a67995 100644 --- a/tests/ui/imports/import-prefix-macro-2.rs +++ b/tests/ui/imports/import-prefix-macro-2.rs @@ -8,7 +8,7 @@ mod a { } macro_rules! import { - ($p: path) => (use ::$p {S, Z}); //~ERROR expected identifier, found `a::b::c` + ($p: path) => (use ::$p {S, Z}); //~ERROR expected identifier, found metavariable } import! { a::b::c } diff --git a/tests/ui/imports/import-prefix-macro-2.stderr b/tests/ui/imports/import-prefix-macro-2.stderr index 070186f2bf2fb..fbeca99b13800 100644 --- a/tests/ui/imports/import-prefix-macro-2.stderr +++ b/tests/ui/imports/import-prefix-macro-2.stderr @@ -1,8 +1,8 @@ -error: expected identifier, found `a::b::c` +error: expected identifier, found metavariable --> $DIR/import-prefix-macro-2.rs:11:26 | LL | ($p: path) => (use ::$p {S, Z}); - | ^^ expected identifier + | ^^ expected identifier, found metavariable ... LL | import! { a::b::c } | ------------------- in this macro invocation diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs index f71a1ae50cc19..b0a7f3e4650fd 100644 --- a/tests/ui/macros/nonterminal-matching.rs +++ b/tests/ui/macros/nonterminal-matching.rs @@ -31,7 +31,7 @@ macro_rules! foo { (tt $x:tt) => { bar!(tt $x); }; (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3` (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4` - (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected path `a::b::c` + (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected `path` metavariable (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected `stmt` metavariable } diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index 6e057ac3317f0..2d9252fbfc1fa 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -67,7 +67,7 @@ LL | (literal 4) => {}; = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected path `a::b::c` +error: no rules expected `path` metavariable --> $DIR/nonterminal-matching.rs:34:35 | LL | (path $x:path) => { bar!(path $x); }; From f797ad5d1f8442afadca15011c6807313b394b46 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 21:31:17 +1000 Subject: [PATCH 08/12] Remove `NtExpr` and `NtLiteral`. Notes about tests: - tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs: some messages are now duplicated due to repeated parsing. - tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs: ditto. - `tests/ui/proc-macro/macro-rules-derive-cfg.rs`: the diff looks large but the only difference is the insertion of a single invisible-delimited group around a metavar. --- compiler/rustc_ast/src/ast_traits.rs | 2 - compiler/rustc_ast/src/mut_visit.rs | 2 - compiler/rustc_ast/src/token.rs | 71 +- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 34 +- compiler/rustc_parse/messages.ftl | 2 +- compiler/rustc_parse/src/errors.rs | 4 +- compiler/rustc_parse/src/parser/expr.rs | 172 ++- compiler/rustc_parse/src/parser/item.rs | 11 +- compiler/rustc_parse/src/parser/mod.rs | 28 +- .../rustc_parse/src/parser/nonterminal.rs | 16 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- tests/ui/attributes/nonterminal-expansion.rs | 2 +- .../attributes/nonterminal-expansion.stderr | 2 +- .../cfg-attr-syntax-validation.rs | 4 +- .../cfg-attr-syntax-validation.stderr | 4 +- tests/ui/macros/nonterminal-matching.rs | 4 +- tests/ui/macros/nonterminal-matching.stderr | 4 +- tests/ui/parser/float-field-interpolated.rs | 8 +- .../ui/parser/float-field-interpolated.stderr | 8 +- .../ui/parser/macro/trait-non-item-macros.rs | 2 +- .../parser/macro/trait-non-item-macros.stderr | 2 +- .../proc-macro/macro-rules-derive-cfg.stdout | 129 +- .../rfc-2294-if-let-guard/feature-gate.rs | 2 + .../rfc-2294-if-let-guard/feature-gate.stderr | 26 +- .../disallowed-positions.feature.stderr | 264 ++-- .../disallowed-positions.no_feature.stderr | 274 ++-- .../disallowed-positions.nofeature.stderr | 1111 ----------------- .../disallowed-positions.nothing.stderr | 196 +-- .../disallowed-positions.rs | 4 + 30 files changed, 728 insertions(+), 1663 deletions(-) delete mode 100644 tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 044569e451253..8c07c328eeba0 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -199,13 +199,11 @@ impl HasTokens for Attribute { impl HasTokens for Nonterminal { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), Nonterminal::NtBlock(block) => block.tokens(), } } fn tokens_mut(&mut self) -> Option<&mut Option> { match self { - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 28b329a9677ec..6f6366026aa41 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -866,8 +866,6 @@ pub fn visit_token(vis: &mut T, t: &mut Token) { fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { match nt { token::NtBlock(block) => vis.visit_block(block), - token::NtExpr(expr) => vis.visit_expr(expr), - token::NtLiteral(expr) => vis.visit_expr(expr), } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index ab1ab5facd89b..90a46bb53f4c3 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -210,16 +210,17 @@ impl Lit { } } - /// Keep this in sync with `Token::can_begin_literal_maybe_minus` excluding unary negation. + /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and + /// `Parser::eat_token_lit` (excluding unary negation). pub fn from_token(token: &Token) -> Option { match token.uninterpolate().kind { Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)), Literal(token_lit) => Some(token_lit), - Interpolated(ref nt) - if let NtExpr(expr) | NtLiteral(expr) = &**nt - && let ast::ExprKind::Lit(token_lit) = expr.kind => - { - Some(token_lit) + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Literal | MetaVarKind::Expr { .. }, + ))) => { + // Unreachable with the current test suite. + panic!("from_token metavar"); } _ => None, } @@ -564,6 +565,9 @@ impl Token { /// for which spans affect name resolution and edition checks. /// Note that keywords are also identifiers, so they should use this /// if they keep spans or perform edition checks. + // + // Note: `Parser::uninterpolated_token_span` may give better information + // than this method does. pub fn uninterpolated_span(&self) -> Span { match self.kind { NtIdent(ident, _) | NtLifetime(ident, _) => ident.span, @@ -616,12 +620,7 @@ impl Token { PathSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt) => - matches!(&**nt, - NtBlock(..) | - NtExpr(..) | - NtLiteral(..) - ), + Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Block | MetaVarKind::Expr { .. } | @@ -652,11 +651,6 @@ impl Token { BinOp(Shl) => true, // path (double UFCS) // leading vert `|` or-pattern BinOp(Or) => matches!(pat_kind, PatWithOr), - Interpolated(nt) => - matches!(&**nt, - | NtExpr(..) - | NtLiteral(..) - ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Literal | @@ -699,7 +693,7 @@ impl Token { match self.kind { OpenDelim(Delimiter::Brace) | Literal(..) | BinOp(Minus) => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), + Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, ))) => true, @@ -743,22 +737,12 @@ impl Token { /// /// In other words, would this token be a valid start of `parse_literal_maybe_minus`? /// - /// Keep this in sync with and `Lit::from_token`, excluding unary negation. + /// Keep this in sync with `Lit::from_token` and `Parser::eat_token_lit` + /// (excluding unary negation). pub fn can_begin_literal_maybe_minus(&self) -> bool { match self.uninterpolate().kind { Literal(..) | BinOp(Minus) => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - Interpolated(ref nt) => match &**nt { - NtLiteral(_) => true, - NtExpr(e) => match &e.kind { - ast::ExprKind::Lit(_) => true, - ast::ExprKind::Unary(ast::UnOp::Neg, e) => { - matches!(&e.kind, ast::ExprKind::Lit(_)) - } - _ => false, - }, - _ => false, - }, OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { MetaVarKind::Literal => true, MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => { @@ -773,14 +757,6 @@ impl Token { pub fn can_begin_string_literal(&self) -> bool { match self.uninterpolate().kind { Literal(..) => true, - Interpolated(ref nt) => match &**nt { - NtLiteral(_) => true, - NtExpr(e) => match &e.kind { - ast::ExprKind::Lit(_) => true, - _ => false, - }, - _ => false, - }, OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { MetaVarKind::Literal => true, MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal, @@ -844,13 +820,16 @@ impl Token { /// Is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? - pub fn is_whole_expr(&self) -> bool { + pub fn is_metavar_expr(&self) -> bool { #[allow(irrefutable_let_patterns)] // FIXME: temporary if let Interpolated(nt) = &self.kind - && let NtExpr(_) | NtLiteral(_) | NtBlock(_) = &**nt + && let NtBlock(_) = &**nt { true - } else if matches!(self.is_metavar_seq(), Some(MetaVarKind::Path)) { + } else if matches!( + self.is_metavar_seq(), + Some(MetaVarKind::Expr { .. } | MetaVarKind::Literal | MetaVarKind::Path) + ) { true } else { false @@ -859,6 +838,7 @@ impl Token { /// Is the token an interpolated block (`$b:block`)? pub fn is_whole_block(&self) -> bool { + #[allow(irrefutable_let_patterns)] // FIXME: temporary if let Interpolated(nt) = &self.kind && let NtBlock(..) = &**nt { @@ -1052,8 +1032,6 @@ pub enum NtExprKind { /// For interpolation during macro expansion. pub enum Nonterminal { NtBlock(P), - NtExpr(P), - NtLiteral(P), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] @@ -1143,15 +1121,12 @@ impl Nonterminal { pub fn use_span(&self) -> Span { match self { NtBlock(block) => block.span, - NtExpr(expr) | NtLiteral(expr) => expr.span, } } pub fn descr(&self) -> &'static str { match self { NtBlock(..) => "block", - NtExpr(..) => "expression", - NtLiteral(..) => "literal", } } } @@ -1170,8 +1145,6 @@ impl fmt::Debug for Nonterminal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { NtBlock(..) => f.pad("NtBlock(..)"), - NtExpr(..) => f.pad("NtExpr(..)"), - NtLiteral(..) => f.pad("NtLiteral(..)"), } } } @@ -1194,7 +1167,7 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Lit, 12); static_assert_size!(LitKind, 2); - static_assert_size!(Nonterminal, 16); + static_assert_size!(Nonterminal, 8); static_assert_size!(Token, 24); static_assert_size!(TokenKind, 16); // tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 51acc08a568e1..680092a0dcd18 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -461,7 +461,6 @@ impl TokenStream { pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream { match nt { Nonterminal::NtBlock(block) => TokenStream::from_ast(block), - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 314d43370bab9..f62caf06c819f 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -2,11 +2,10 @@ use std::mem; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token, - TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Token, TokenKind, }; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; -use rustc_ast::{ExprKind, StmtKind}; +use rustc_ast::{ExprKind, StmtKind, UnOp}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; @@ -333,6 +332,29 @@ pub(super) fn transcribe<'a>( MatchedSingle(ParseNtResult::Pat(pat, pat_kind)) => { mk_delimited(MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat)) } + MatchedSingle(ParseNtResult::Expr(expr, kind)) => { + let (can_begin_literal_maybe_minus, can_begin_string_literal) = + match &expr.kind { + ExprKind::Lit(_) => (true, true), + ExprKind::Unary(UnOp::Neg, e) + if matches!(&e.kind, ExprKind::Lit(_)) => + { + (true, false) + } + _ => (false, false), + }; + mk_delimited( + MetaVarKind::Expr { + kind: *kind, + can_begin_literal_maybe_minus, + can_begin_string_literal, + }, + TokenStream::from_ast(expr), + ) + } + MatchedSingle(ParseNtResult::Literal(lit)) => { + mk_delimited(MetaVarKind::Literal, TokenStream::from_ast(lit)) + } MatchedSingle(ParseNtResult::Ty(ty)) => { mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty)) } @@ -852,10 +874,8 @@ fn extract_symbol_from_pnr<'a>( }, _, )) => Ok(*symbol), - ParseNtResult::Nt(nt) - if let Nonterminal::NtLiteral(expr) = &**nt - && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = - &expr.kind => + ParseNtResult::Literal(expr) + if let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind => { Ok(*symbol) } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 1171cacaa6985..0783f784f4b1b 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -855,7 +855,7 @@ parse_unexpected_parentheses_in_match_arm_pattern = unexpected parentheses surro parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters .note = you cannot use `Self` as a generic parameter because it is reserved for associated items -parse_unexpected_token_after_dot = unexpected token: `{$actual}` +parse_unexpected_token_after_dot = unexpected token: {$actual} parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label .suggestion_remove_label = consider removing the label diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 7e9737acb6450..dcb222837152f 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1675,10 +1675,10 @@ pub(crate) struct SelfArgumentPointer { #[derive(Diagnostic)] #[diag(parse_unexpected_token_after_dot)] -pub(crate) struct UnexpectedTokenAfterDot<'a> { +pub(crate) struct UnexpectedTokenAfterDot { #[primary_span] pub span: Span, - pub actual: Cow<'a, str>, + pub actual: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 5a262fec5df63..a182c132dde9a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4,10 +4,10 @@ use core::mem; use core::ops::ControlFlow; use ast::mut_visit::{self, MutVisitor}; -use ast::token::{IdentIsRaw, MetaVarKind}; +use ast::token::IdentIsRaw; use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::util::classify; use rustc_ast::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; @@ -17,7 +17,6 @@ use rustc_ast::{ ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, }; -use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; use rustc_lexer::unescape::unescape_char; @@ -644,7 +643,7 @@ impl<'a> Parser<'a> { // can't continue an expression after an ident token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), token::Literal(..) | token::Pound => true, - _ => t.is_whole_expr(), + _ => t.is_metavar_expr(), }; self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr) } @@ -680,6 +679,13 @@ impl<'a> Parser<'a> { TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => { self.prev_token.span } + TokenKind::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { + // `expr.span` is the interpolated span, because invisible open + // and close delims both get marked with the same span, one + // that covers the entire thing between them. (See + // `rustc_expand::mbe::transcribe::transcribe`.) + self.prev_token.span + } _ => expr.span, } } @@ -1016,12 +1022,16 @@ impl<'a> Parser<'a> { } fn error_unexpected_after_dot(&self) { - let actual = pprust::token_to_string(&self.token); + let actual = super::token_descr(&self.token); let span = self.token.span; let sm = self.psess.source_map(); let (span, actual) = match (&self.token.kind, self.subparser_name) { - (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => { - (span.shrink_to_hi(), actual.into()) + (token::Eof, Some(_)) if let Ok(snippet) = sm.span_to_snippet(sm.next_point(span)) => { + (span.shrink_to_hi(), format!("`{}`", snippet)) + } + (token::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))), _) => { + // Don't need to report an error in this case. + return; } _ => (span, actual), }; @@ -1385,17 +1395,31 @@ impl<'a> Parser<'a> { let span = self.token.span; if let token::Interpolated(nt) = &self.token.kind { match &**nt { - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - self.bump(); - return Ok(e); - } token::NtBlock(block) => { let block = block.clone(); self.bump(); return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); } }; + } else if let Some(expr) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), + |this| { + let expr = this.parse_expr(); + // FIXME(nnethercote) Sometimes with expressions we get a trailing comma, possibly + // related to the FIXME in `collect_tokens_for_expr`. Examples are the multi-line + // `assert_eq!` calls involving arguments annotated with `#[rustfmt::skip]` in + // `compiler/rustc_index/src/bit_set/tests.rs`. + if this.token.kind == token::Comma { + this.bump(); + } + expr + }, + ) { + return Ok(expr); + } else if let Some(lit) = + self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + { + return Ok(lit); } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| { this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type)) }) { @@ -1407,7 +1431,8 @@ impl<'a> Parser<'a> { let restrictions = self.restrictions; self.with_res(restrictions - Restrictions::ALLOW_LET, |this| { - // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`. + // Note: when adding new syntax here, don't forget to adjust + // `TokenKind::can_begin_expr()`. let lo = this.token.span; if let token::Literal(_) = this.token.kind { // This match arm is a special-case of the `_` match arm below and @@ -2104,49 +2129,78 @@ impl<'a> Parser<'a> { recovered } + /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and + /// `Lit::from_token` (excluding unary negation). + pub fn eat_token_lit(&mut self) -> Option { + match self.token.uninterpolate().kind { + token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => { + self.bump(); + Some(token::Lit::new(token::Bool, name, None)) + } + token::Literal(token_lit) => { + self.bump(); + Some(token_lit) + } + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Literal, + ))) => { + let lit = self + .eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + .expect("metavar seq literal"); + let ast::ExprKind::Lit(token_lit) = lit.kind else { + panic!("didn't reparse a literal"); + }; + Some(token_lit) + } + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + mv_kind @ MetaVarKind::Expr { can_begin_literal_maybe_minus: true, .. }, + ))) => { + let expr = self + .eat_metavar_seq(mv_kind, |this| this.parse_expr()) + .expect("metavar seq expr"); + let ast::ExprKind::Lit(token_lit) = expr.kind else { + panic!("didn't reparse an expr"); + }; + Some(token_lit) + } + _ => None, + } + } + /// Matches `lit = true | false | token_lit`. /// Returns `None` if the next token is not a literal. - pub(super) fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> { - let recovered = self.recover_after_dot(); - let token = recovered.as_ref().unwrap_or(&self.token); - let span = token.span; - - token::Lit::from_token(token).map(|token_lit| { - self.bump(); - (token_lit, span) - }) + fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> { + match self.recover_after_dot() { + Some(recovered) => self.token = recovered, + None => {} + } + let span = self.token.span; + self.eat_token_lit().map(|token_lit| (token_lit, span)) } /// Matches `lit = true | false | token_lit`. /// Returns `None` if the next token is not a literal. - pub(super) fn parse_opt_meta_item_lit(&mut self) -> Option { - let recovered = self.recover_after_dot(); - let token = recovered.as_ref().unwrap_or(&self.token); - match token::Lit::from_token(token) { - Some(lit) => { - match MetaItemLit::from_token_lit(lit, token.span) { - Ok(lit) => { - self.bump(); - Some(lit) - } - Err(err) => { - let span = token.uninterpolated_span(); - self.bump(); - let guar = report_lit_error(self.psess, err, lit, span); - // Pack possible quotes and prefixes from the original literal into - // the error literal's symbol so they can be pretty-printed faithfully. - let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); - let symbol = Symbol::intern(&suffixless_lit.to_string()); - let lit = token::Lit::new(token::Err(guar), symbol, lit.suffix); - Some( - MetaItemLit::from_token_lit(lit, span) - .unwrap_or_else(|_| unreachable!()), - ) - } + fn parse_opt_meta_item_lit(&mut self) -> Option { + match self.recover_after_dot() { + Some(recovered) => self.token = recovered, + None => {} + } + let span = self.token.span; + let span2 = self.uninterpolated_token_span(); + self.eat_token_lit().map(|token_lit| { + match MetaItemLit::from_token_lit(token_lit, span) { + Ok(lit) => lit, + Err(err) => { + let guar = report_lit_error(&self.psess, err, token_lit, span2); + // Pack possible quotes and prefixes from the original literal into + // the error literal's symbol so they can be pretty-printed faithfully. + let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None); + let symbol = Symbol::intern(&suffixless_lit.to_string()); + let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix); + MetaItemLit::from_token_lit(token_lit, span2).unwrap_or_else(|_| unreachable!()) } } - None => None, - } + }) } pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) { @@ -2170,9 +2224,10 @@ impl<'a> Parser<'a> { /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { - if let token::Interpolated(nt) = &self.token.kind { - match &**nt { - // FIXME(nnethercote) The `NtExpr` case should only match if + if let Some(expr) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), + |this| { + // FIXME(nnethercote) The `expr` case should only match if // `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing // an `UnOp::Neg` and an `ExprKind::Lit`, like how // `can_begin_literal_maybe_minus` works. But this method has @@ -2182,13 +2237,14 @@ impl<'a> Parser<'a> { // `ExprKind::Path` must be accepted when parsing range // patterns. That requires some care. So for now, we continue // being less strict here than we should be. - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - self.bump(); - return Ok(e); - } - _ => {} - }; + this.parse_expr() + }, + ) { + return Ok(expr); + } else if let Some(lit) = + self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + { + return Ok(lit); } let lo = self.token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e59a7c620f8c0..8ac272dd86d9f 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2560,12 +2560,17 @@ impl<'a> Parser<'a> { }) // `extern ABI fn` || self.check_keyword_case(kw::Extern, case) + // Use `tree_look_ahead` because `ABI` might be a metavariable, + // i.e. an invisible-delimited sequence, and `tree_look_ahead` + // will consider that a single element when looking ahead. && self.look_ahead(1, |t| t.can_begin_string_literal()) - && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) || + && (self.tree_look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) == Some(true) || // this branch is only for better diagnostics; `pub`, `unsafe`, etc. are not allowed here (self.may_recover() - && self.look_ahead(2, |t| ALL_QUALS.iter().any(|&kw| t.is_keyword(kw))) - && self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case)))) + && self.tree_look_ahead(2, |t| ALL_QUALS.iter().any(|&kw| t.is_keyword(kw))) == Some(true) + && self.tree_look_ahead(3, |t| t.is_keyword_case(kw::Fn, case)) == Some(true) + ) + ) } /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 573d61d13ffbf..32a8256cf54e9 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -22,8 +22,8 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtPatKind, Token, - TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtExprKind, NtPatKind, + Token, TokenKind, }; use rustc_ast::tokenstream::{ AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor, @@ -100,6 +100,7 @@ pub enum ForceCollect { #[macro_export] macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { + #[allow(irrefutable_let_patterns)] // FIXME: temporary if let token::Interpolated(nt) = &$p.token.kind && let token::$constructor(x) = &**nt { @@ -1298,6 +1299,17 @@ impl<'a> Parser<'a> { looker(&token) } + /// Like `lookahead`, but skips over token trees rather than tokens. Useful + /// when looking past possible metavariable pasting sites. + pub fn tree_look_ahead(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> Option { + assert_ne!(dist, 0); + + match self.token_cursor.tree_cursor.look_ahead(dist - 1) { + Some(TokenTree::Token(token, _)) => Some(looker(token)), + _ => None, + } + } + /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. pub(crate) fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) @@ -1716,6 +1728,16 @@ impl<'a> Parser<'a> { pub fn approx_token_stream_pos(&self) -> u32 { self.num_bump_calls } + + pub fn uninterpolated_token_span(&self) -> Span { + match &self.token.kind { + token::Interpolated(nt) => nt.use_span(), + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { + self.look_ahead(1, |t| t.span) + } + _ => self.token.span, + } + } } pub(crate) fn make_unclosed_delims_error( @@ -1768,6 +1790,8 @@ pub enum ParseNtResult { Item(P), Stmt(P), Pat(P, NtPatKind), + Expr(P, NtExprKind), + Literal(P), Ty(P), Meta(P), Path(P), diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index daa4b3c5910fa..0f32302f602e9 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -47,10 +47,6 @@ impl<'a> Parser<'a> { /// Old variant of `may_be_ident`. Being phased out. fn nt_may_be_ident(nt: &Nonterminal) -> bool { match nt { - NtExpr(_) - | NtLiteral(_) // `true`, `false` - => true, - NtBlock(_) => false, } } @@ -94,7 +90,7 @@ impl<'a> Parser<'a> { token::OpenDelim(Delimiter::Brace) => true, token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { - NtBlock(_) | NtExpr(_) | NtLiteral(_) => true, + NtBlock(_) => true, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -178,10 +174,14 @@ impl<'a> Parser<'a> { pat_kind, )); } - NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?), + NonterminalKind::Expr(expr_kind) => { + return Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind)); + } NonterminalKind::Literal => { - // The `:literal` matcher does not support attributes - NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) + // The `:literal` matcher does not support attributes. + return Ok(ParseNtResult::Literal( + self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?, + )); } NonterminalKind::Ty => { return Ok(ParseNtResult::Ty( diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 4ffae4426f481..7b7cf51bd6e04 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1229,7 +1229,7 @@ impl<'a> Parser<'a> { || *t == token::Dot // e.g. `.5` for recovery; || matches!(t.kind, token::Literal(..) | token::BinOp(token::Minus)) || t.is_bool_lit() - || t.is_whole_expr() + || t.is_metavar_expr() || t.is_lifetime() // recover `'a` instead of `'a'` || (self.may_recover() // recover leading `(` && *t == token::OpenDelim(Delimiter::Parenthesis) diff --git a/tests/ui/attributes/nonterminal-expansion.rs b/tests/ui/attributes/nonterminal-expansion.rs index 796c81a5cdf29..004a8a23fd61f 100644 --- a/tests/ui/attributes/nonterminal-expansion.rs +++ b/tests/ui/attributes/nonterminal-expansion.rs @@ -5,7 +5,7 @@ macro_rules! pass_nonterminal { ($n:expr) => { #[repr(align($n))] - //~^ ERROR expected unsuffixed literal, found expression `n!()` + //~^ ERROR expected unsuffixed literal, found `expr` metavariable struct S; }; } diff --git a/tests/ui/attributes/nonterminal-expansion.stderr b/tests/ui/attributes/nonterminal-expansion.stderr index 15a61a642609b..9c6cb98f61965 100644 --- a/tests/ui/attributes/nonterminal-expansion.stderr +++ b/tests/ui/attributes/nonterminal-expansion.stderr @@ -1,4 +1,4 @@ -error: expected unsuffixed literal, found expression `n!()` +error: expected unsuffixed literal, found `expr` metavariable --> $DIR/nonterminal-expansion.rs:7:22 | LL | #[repr(align($n))] diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index 9a041557c7cc9..59a95307a227c 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -28,8 +28,8 @@ struct S9; macro_rules! generate_s10 { ($expr: expr) => { #[cfg(feature = $expr)] - //~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` - //~| ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` + //~^ ERROR expected unsuffixed literal, found `expr` metavariable + //~| ERROR expected unsuffixed literal, found `expr` metavariable struct S10; } } diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 21a3712d9391a..d073f2a7a3448 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")] | | | help: consider removing the prefix -error: expected unsuffixed literal, found expression `concat!("nonexistent")` +error: expected unsuffixed literal, found `expr` metavariable --> $DIR/cfg-attr-syntax-validation.rs:30:25 | LL | #[cfg(feature = $expr)] @@ -65,7 +65,7 @@ LL | generate_s10!(concat!("nonexistent")); | = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected unsuffixed literal, found expression `concat!("nonexistent")` +error: expected unsuffixed literal, found `expr` metavariable --> $DIR/cfg-attr-syntax-validation.rs:30:25 | LL | #[cfg(feature = $expr)] diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs index b0a7f3e4650fd..a03ede20c5499 100644 --- a/tests/ui/macros/nonterminal-matching.rs +++ b/tests/ui/macros/nonterminal-matching.rs @@ -29,8 +29,8 @@ macro_rules! foo { (ident $x:ident) => { bar!(ident $x); }; (lifetime $x:lifetime) => { bar!(lifetime $x); }; (tt $x:tt) => { bar!(tt $x); }; - (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3` - (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4` + (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected `expr` metavariable + (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected `literal` metavariable (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected `path` metavariable (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected `stmt` metavariable } diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index 2d9252fbfc1fa..d01561415664c 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -23,7 +23,7 @@ LL | complex_nonterminal!(enum E {}); = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected expression `3` +error: no rules expected `expr` metavariable --> $DIR/nonterminal-matching.rs:32:35 | LL | (expr $x:expr) => { bar!(expr $x); }; @@ -45,7 +45,7 @@ LL | (expr 3) => {}; = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected literal `4` +error: no rules expected `literal` metavariable --> $DIR/nonterminal-matching.rs:33:44 | LL | (literal $x:literal) => { bar!(literal $x); }; diff --git a/tests/ui/parser/float-field-interpolated.rs b/tests/ui/parser/float-field-interpolated.rs index 990f2926dc861..bf7163039c420 100644 --- a/tests/ui/parser/float-field-interpolated.rs +++ b/tests/ui/parser/float-field-interpolated.rs @@ -5,10 +5,10 @@ macro_rules! generate_field_accesses { let s = S(0, (0, 0)); s.$a; // OK - { s.$b; } //~ ERROR unexpected token: `1.1` - //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1` - { s.$c; } //~ ERROR unexpected token: `1.1` - //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1` + { s.$b; } //~ ERROR unexpected token: `literal` metavariable + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable + { s.$c; } //~ ERROR unexpected token: `expr` metavariable + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable }; } diff --git a/tests/ui/parser/float-field-interpolated.stderr b/tests/ui/parser/float-field-interpolated.stderr index 2a1a4926cb3c6..e2b7e3a7dbe75 100644 --- a/tests/ui/parser/float-field-interpolated.stderr +++ b/tests/ui/parser/float-field-interpolated.stderr @@ -1,4 +1,4 @@ -error: unexpected token: `1.1` +error: unexpected token: `literal` metavariable --> $DIR/float-field-interpolated.rs:8:13 | LL | { s.$b; } @@ -9,7 +9,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1` +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable --> $DIR/float-field-interpolated.rs:8:13 | LL | { s.$b; } @@ -20,7 +20,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: unexpected token: `1.1` +error: unexpected token: `expr` metavariable --> $DIR/float-field-interpolated.rs:10:13 | LL | { s.$c; } @@ -31,7 +31,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1` +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable --> $DIR/float-field-interpolated.rs:10:13 | LL | { s.$c; } diff --git a/tests/ui/parser/macro/trait-non-item-macros.rs b/tests/ui/parser/macro/trait-non-item-macros.rs index e93000193b6e3..b4140613cbae7 100644 --- a/tests/ui/parser/macro/trait-non-item-macros.rs +++ b/tests/ui/parser/macro/trait-non-item-macros.rs @@ -1,7 +1,7 @@ macro_rules! bah { ($a:expr) => { $a - }; //~^ ERROR macro expansion ignores expression `2` and any tokens following + }; //~^ ERROR macro expansion ignores `expr` metavariable and any tokens following } trait Bar { diff --git a/tests/ui/parser/macro/trait-non-item-macros.stderr b/tests/ui/parser/macro/trait-non-item-macros.stderr index 1a82848377895..62b42fa8b8dd7 100644 --- a/tests/ui/parser/macro/trait-non-item-macros.stderr +++ b/tests/ui/parser/macro/trait-non-item-macros.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores expression `2` and any tokens following +error: macro expansion ignores `expr` metavariable and any tokens following --> $DIR/trait-non-item-macros.rs:3:9 | LL | $a diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout index c1e46b50d40c2..9482b2784d222 100644 --- a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout +++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout @@ -1,8 +1,9 @@ PRINT-DERIVE INPUT (DISPLAY): struct -Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)] -{ #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); +Foo([bool; #[rustc_dummy(first)] +#[rustc_dummy(second)] { #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct -Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)] +Foo([bool; #[rustc_dummy(first)] +#[rustc_dummy(second)] { #! [rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { @@ -53,97 +54,103 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ ], span: $DIR/macro-rules-derive-cfg.rs:18:21: 18:63 (#3), }, - Punct { - ch: '#', - spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0), - }, Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "second", - span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0), - }, - ], - span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0), - }, - ], - span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0), - }, - Group { - delimiter: Brace, + delimiter: None, stream: TokenStream [ Punct { ch: '#', - spacing: Joint, - span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0), - }, - Punct { - ch: '!', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "third", - span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0), + ident: "second", + span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0), - }, - Punct { - ch: '#', - spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0), }, Group { - delimiter: Bracket, + delimiter: Brace, stream: TokenStream [ - Ident { - ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0), + Punct { + ch: '#', + spacing: Joint, + span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0), }, Group { - delimiter: Parenthesis, + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0), + }, + Group { + delimiter: Bracket, stream: TokenStream [ Ident { - ident: "fourth", - span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0), + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0), + span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0), - }, - Literal { - kind: Integer, - symbol: "30", - suffix: None, - span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0), + span: $DIR/macro-rules-derive-cfg.rs:18:64: 18:69 (#3), }, ], span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:70 (#3), diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs index 4b2fc4a03b620..110c03d0e5491 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs @@ -59,8 +59,10 @@ fn _macros() { } use_expr!((let 0 = 1 && 0 == 0)); //~^ ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); //~^ ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement match () { #[cfg(FALSE)] () if let 0 = 1 => {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr index 1c710b04897cb..0997f0c81a019 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr @@ -124,15 +124,33 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:62:16 + --> $DIR/feature-gate.rs:60:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:63:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:63:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: no rules expected keyword `let` - --> $DIR/feature-gate.rs:70:15 + --> $DIR/feature-gate.rs:72:15 | LL | macro_rules! use_expr { | --------------------- when calling this macro @@ -202,7 +220,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:66:12 + --> $DIR/feature-gate.rs:68:12 | LL | () if let 0 = 1 => {} | ^^^^^^^^^^^^ @@ -262,6 +280,6 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 23 previous errors +error: aborting due to 25 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr index db32b8c1de4ff..817e226bc45d5 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -995,15 +995,51 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:130:8 + --> $DIR/disallowed-positions.rs:134:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1012,7 +1048,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:139:12 + --> $DIR/disallowed-positions.rs:143:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1023,7 +1059,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:142:12 + --> $DIR/disallowed-positions.rs:146:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1034,7 +1070,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:148:12 + --> $DIR/disallowed-positions.rs:152:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1045,7 +1081,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:154:12 + --> $DIR/disallowed-positions.rs:158:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1056,7 +1092,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:110:20 + --> $DIR/disallowed-positions.rs:114:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1064,7 +1100,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:221:11 + --> $DIR/disallowed-positions.rs:225:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1073,7 +1109,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:230:15 + --> $DIR/disallowed-positions.rs:234:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1084,7 +1120,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:233:15 + --> $DIR/disallowed-positions.rs:237:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1095,7 +1131,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:239:15 + --> $DIR/disallowed-positions.rs:243:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1106,7 +1142,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:245:15 + --> $DIR/disallowed-positions.rs:249:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1117,7 +1153,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:201:23 + --> $DIR/disallowed-positions.rs:205:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1125,7 +1161,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:330:10 + --> $DIR/disallowed-positions.rs:334:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1136,14 +1172,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:305:17 + --> $DIR/disallowed-positions.rs:309:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 121 previous errors +error: aborting due to 125 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr index ad16a0f8ed812..bab50c22c0308 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -995,12 +995,48 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0658]: `let` expressions in this position are unstable --> $DIR/disallowed-positions.rs:49:8 @@ -1043,7 +1079,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:404:8 + --> $DIR/disallowed-positions.rs:408:8 | LL | if let Some(a) = opt && (true && true) { | ^^^^^^^^^^^^^^^^^ @@ -1053,7 +1089,7 @@ LL | if let Some(a) = opt && (true && true) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:420:28 + --> $DIR/disallowed-positions.rs:424:28 | LL | if (true && (true)) && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1063,7 +1099,7 @@ LL | if (true && (true)) && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:423:18 + --> $DIR/disallowed-positions.rs:427:18 | LL | if (true) && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1073,7 +1109,7 @@ LL | if (true) && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:426:16 + --> $DIR/disallowed-positions.rs:430:16 | LL | if true && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1083,7 +1119,7 @@ LL | if true && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:431:8 + --> $DIR/disallowed-positions.rs:435:8 | LL | if let true = (true && fun()) && (true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1093,7 +1129,7 @@ LL | if let true = (true && fun()) && (true) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:130:8 + --> $DIR/disallowed-positions.rs:134:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1102,7 +1138,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:139:12 + --> $DIR/disallowed-positions.rs:143:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1113,7 +1149,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:142:12 + --> $DIR/disallowed-positions.rs:146:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1124,7 +1160,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:148:12 + --> $DIR/disallowed-positions.rs:152:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1135,7 +1171,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:154:12 + --> $DIR/disallowed-positions.rs:158:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1146,7 +1182,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:110:20 + --> $DIR/disallowed-positions.rs:114:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1154,7 +1190,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:221:11 + --> $DIR/disallowed-positions.rs:225:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1163,7 +1199,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:230:15 + --> $DIR/disallowed-positions.rs:234:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1174,7 +1210,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:233:15 + --> $DIR/disallowed-positions.rs:237:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1185,7 +1221,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:239:15 + --> $DIR/disallowed-positions.rs:243:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1196,7 +1232,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:245:15 + --> $DIR/disallowed-positions.rs:249:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1207,7 +1243,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:201:23 + --> $DIR/disallowed-positions.rs:205:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1215,7 +1251,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:330:10 + --> $DIR/disallowed-positions.rs:334:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1226,14 +1262,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:305:17 + --> $DIR/disallowed-positions.rs:309:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 130 previous errors +error: aborting due to 134 previous errors Some errors have detailed explanations: E0277, E0308, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr deleted file mode 100644 index f556ecf7f91d3..0000000000000 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr +++ /dev/null @@ -1,1111 +0,0 @@ -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:31:9 - | -LL | if (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:31:9 - | -LL | if (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:34:11 - | -LL | if (((let 0 = 1))) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:34:11 - | -LL | if (((let 0 = 1))) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:37:9 - | -LL | if (let 0 = 1) && true {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:37:9 - | -LL | if (let 0 = 1) && true {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:40:17 - | -LL | if true && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:40:17 - | -LL | if true && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:43:9 - | -LL | if (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:43:9 - | -LL | if (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:43:24 - | -LL | if (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:43:24 - | -LL | if (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:47:35 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:47:35 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:47:48 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:47:35 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:47:61 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:47:35 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:56:12 - | -LL | while (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:56:12 - | -LL | while (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:59:14 - | -LL | while (((let 0 = 1))) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:59:14 - | -LL | while (((let 0 = 1))) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:62:12 - | -LL | while (let 0 = 1) && true {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:62:12 - | -LL | while (let 0 = 1) && true {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:65:20 - | -LL | while true && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:65:20 - | -LL | while true && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:12 - | -LL | while (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:12 - | -LL | while (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:27 - | -LL | while (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:27 - | -LL | while (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:72:38 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:72:38 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:72:51 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:72:38 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:72:64 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:72:38 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:9 - | -LL | if &let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:98:9 - | -LL | if !let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:100:9 - | -LL | if *let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 - | -LL | if -let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:110:9 - | -LL | if (let 0 = 0)? {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:113:16 - | -LL | if true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:113:13 - | -LL | if true || let 0 = 0 {} - | ^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:115:17 - | -LL | if (true || let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:25 - | -LL | if true && (true || let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:25 - | -LL | if true || (true && let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:12 - | -LL | if x = let 0 = 0 {} - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:126:15 - | -LL | if true..(let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:129:11 - | -LL | if ..(let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:131:9 - | -LL | if (let 0 = 0).. {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:8 - | -LL | if let Range { start: _, end: _ } = true..true && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:138:8 - | -LL | if let Range { start: _, end: _ } = true..true || false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:144:8 - | -LL | if let Range { start: F, end } = F..|| true {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:150:8 - | -LL | if let Range { start: true, end } = t..&&false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:19 - | -LL | if let true = let true = true {} - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:160:12 - | -LL | while &let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:163:12 - | -LL | while !let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:165:12 - | -LL | while *let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:12 - | -LL | while -let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:175:12 - | -LL | while (let 0 = 0)? {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:178:19 - | -LL | while true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:178:16 - | -LL | while true || let 0 = 0 {} - | ^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:180:20 - | -LL | while (true || let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:182:28 - | -LL | while true && (true || let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:28 - | -LL | while true || (true && let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:188:15 - | -LL | while x = let 0 = 0 {} - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:191:18 - | -LL | while true..(let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:194:14 - | -LL | while ..(let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:196:12 - | -LL | while (let 0 = 0).. {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:200:11 - | -LL | while let Range { start: _, end: _ } = true..true && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:203:11 - | -LL | while let Range { start: _, end: _ } = true..true || false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:209:11 - | -LL | while let Range { start: F, end } = F..|| true {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:215:11 - | -LL | while let Range { start: true, end } = t..&&false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:219:22 - | -LL | while let true = let true = true {} - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:236:6 - | -LL | &let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:6 - | -LL | !let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:241:6 - | -LL | *let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:243:6 - | -LL | -let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:13 - | -LL | let _ = let _ = 3; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:253:6 - | -LL | (let 0 = 0)?; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:256:13 - | -LL | true || let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:14 - | -LL | (true || let 0 = 0); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:260:22 - | -LL | true && (true || let 0 = 0); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:9 - | -LL | x = let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:267:12 - | -LL | true..(let 0 = 0); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:269:8 - | -LL | ..(let 0 = 0); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:271:6 - | -LL | (let 0 = 0)..; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:274:6 - | -LL | (let Range { start: _, end: _ } = true..true || false); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:278:6 - | -LL | (let true = let true = true); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:278:17 - | -LL | (let true = let true = true); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:284:25 - | -LL | let x = true && let y = 1; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:290:19 - | -LL | [1, 2, 3][let _ = ()] - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 - | -LL | &let 0 = 0 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:306:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:311:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:327:9 - | -LL | true && let 1 = 1 - | ^^^^^^^^^^^^^^^^^ - | -help: enclose the `const` expression in braces - | -LL | { true && let 1 = 1 } - | + + - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:337:9 - | -LL | if (let Some(a) = opt && true) { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:337:9 - | -LL | if (let Some(a) = opt && true) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:341:9 - | -LL | if (let Some(a) = opt) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:341:9 - | -LL | if (let Some(a) = opt) && true { - | ^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:9 - | -LL | if (let Some(a) = opt) && (let Some(b) = a) { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:344:9 - | -LL | if (let Some(a) = opt) && (let Some(b) = a) { - | ^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:32 - | -LL | if (let Some(a) = opt) && (let Some(b) = a) { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:344:32 - | -LL | if (let Some(a) = opt) && (let Some(b) = a) { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:351:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:351:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:9 - | -LL | if (let Some(a) = opt && (true)) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:9 - | -LL | if (let Some(a) = opt && (true)) && true { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:375:22 - | -LL | let x = (true && let y = 1); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:380:20 - | -LL | ([1, 2, 3][let _ = ()]) - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:87:16 - | -LL | use_expr!((let 0 = 1 && 0 == 0)); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:89:16 - | -LL | use_expr!((let 0 = 1)); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:47:8 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:47:21 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:72:11 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:72:24 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:348:8 - | -LL | if let Some(a) = opt && (true && true) { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:363:28 - | -LL | if (true && (true)) && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:365:18 - | -LL | if (true) && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:367:16 - | -LL | if true && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:371:8 - | -LL | if let true = (true && fun()) && (true) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: add `#![feature(let_chains)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:126:8 - | -LL | if true..(let 0 = 0) {} - | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` - | - = note: expected type `bool` - found struct `std::ops::Range` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:135:12 - | -LL | if let Range { start: _, end: _ } = true..true && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:138:12 - | -LL | if let Range { start: _, end: _ } = true..true || false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:144:12 - | -LL | if let Range { start: F, end } = F..|| true {} - | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` - | | - | expected fn pointer, found `Range<_>` - | - = note: expected fn pointer `fn() -> bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:150:12 - | -LL | if let Range { start: true, end } = t..&&false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:106:20 - | -LL | if let 0 = 0? {} - | ^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:191:11 - | -LL | while true..(let 0 = 0) {} - | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` - | - = note: expected type `bool` - found struct `std::ops::Range` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:200:15 - | -LL | while let Range { start: _, end: _ } = true..true && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:203:15 - | -LL | while let Range { start: _, end: _ } = true..true || false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:209:15 - | -LL | while let Range { start: F, end } = F..|| true {} - | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` - | | - | expected fn pointer, found `Range<_>` - | - = note: expected fn pointer `fn() -> bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:215:15 - | -LL | while let Range { start: true, end } = t..&&false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:171:23 - | -LL | while let 0 = 0? {} - | ^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:274:10 - | -LL | (let Range { start: _, end: _ } = true..true || false); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:249:17 - | -LL | let 0 = 0?; - | ^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error: aborting due to 114 previous errors - -Some errors have detailed explanations: E0277, E0308, E0658. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr index 2d5fd1144addd..943956feb4e07 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs index 8eb8d617d581c..99f99c2be72de 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs @@ -90,8 +90,12 @@ fn _macros() { } use_expr!((let 0 = 1 && 0 == 0)); //[feature,no_feature]~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); //[feature,no_feature]~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement } #[cfg(not(nothing))] From febfb8dd3d26a9623253a1498602caace7e3c611 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 23 Sep 2024 13:04:36 +1000 Subject: [PATCH 09/12] Fix a problem with metavars and inner attributes. --- compiler/rustc_ast/src/tokenstream.rs | 61 +++++++++++++++-------- tests/ui/attributes/inner-attr-metavar.rs | 14 ++++++ 2 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 tests/ui/attributes/inner-attr-metavar.rs diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 680092a0dcd18..2ca4ada3295ad 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -232,35 +232,52 @@ fn attrs_and_tokens_to_token_trees( // Insert inner attribute tokens. if !inner_attrs.is_empty() { - let mut found = false; - // Check the last two trees (to account for a trailing semi) - for tree in res.iter_mut().rev().take(2) { - if let TokenTree::Delimited(span, spacing, delim, delim_tokens) = tree { - // Inner attributes are only supported on extern blocks, functions, - // impls, and modules. All of these have their inner attributes - // placed at the beginning of the rightmost outermost braced group: - // e.g. fn foo() { #![my_attr] } - // - // Therefore, we can insert them back into the right location - // without needing to do any extra position tracking. - // - // Note: Outline modules are an exception - they can - // have attributes like `#![my_attr]` at the start of a file. - // Support for custom attributes in this position is not - // properly implemented - we always synthesize fake tokens, - // so we never reach this code. + let found = insert_inner_attrs(inner_attrs, res); + assert!(found, "Failed to find trailing delimited group in: {res:?}"); + } + + // Inner attributes are only supported on blocks, functions, impls, and + // modules. All of these have their inner attributes placed at the + // beginning of the rightmost outermost braced group: + // e.g. `fn foo() { #![my_attr] }`. (Note: the braces may be within + // invisible delimiters.) + // + // Therefore, we can insert them back into the right location without + // needing to do any extra position tracking. + // + // Note: Outline modules are an exception - they can have attributes like + // `#![my_attr]` at the start of a file. Support for custom attributes in + // this position is not properly implemented - we always synthesize fake + // tokens, so we never reach this code. + fn insert_inner_attrs(inner_attrs: &[Attribute], tts: &mut Vec) -> bool { + for tree in tts.iter_mut().rev() { + if let TokenTree::Delimited(span, spacing, Delimiter::Brace, stream) = tree { + // Found it: the rightmost, outermost braced group. let mut tts = vec![]; for inner_attr in inner_attrs { tts.extend(inner_attr.token_trees()); } - tts.extend(delim_tokens.0.iter().cloned()); + tts.extend(stream.0.iter().cloned()); let stream = TokenStream::new(tts); - *tree = TokenTree::Delimited(*span, *spacing, *delim, stream); - found = true; - break; + *tree = TokenTree::Delimited(*span, *spacing, Delimiter::Brace, stream); + return true; + } else if let TokenTree::Delimited(span, spacing, Delimiter::Invisible(src), stream) = + tree + { + // Recurse inside invisible delimiters. + let mut vec: Vec<_> = stream.trees().cloned().collect(); + if insert_inner_attrs(inner_attrs, &mut vec) { + *tree = TokenTree::Delimited( + *span, + *spacing, + Delimiter::Invisible(*src), + TokenStream::new(vec), + ); + return true; + } } } - assert!(found, "Failed to find trailing delimited group in: {res:?}"); + false } } diff --git a/tests/ui/attributes/inner-attr-metavar.rs b/tests/ui/attributes/inner-attr-metavar.rs new file mode 100644 index 0000000000000..345121c252e82 --- /dev/null +++ b/tests/ui/attributes/inner-attr-metavar.rs @@ -0,0 +1,14 @@ +//@ check-pass +// +// During `Nonterminal` removal (#124141) there was at one point a problem with +// calling from_ast on expressions with inner attributes within metavars -- the +// inner attributes were being inserted in the wrong place in `from_ast`. This +// test covers that case. + +macro_rules! m3 { ($e:expr) => {} } +macro_rules! m2 { ($e:expr) => { m3!($e); } } +macro_rules! m1 { ($e:expr) => { m2!($e); } } + +m1!({ #![allow(unused)] 0 }); + +fn main() {} From 0a3c9b56b8def4439ab2c6f41df686c9e10b28b8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 20:18:13 +1000 Subject: [PATCH 10/12] Remove `NtBlock`, `Nonterminal`, and `TokenKind::Interpolated`. `NtBlock` is the last remaining variant of `Nonterminal`, so once it is gone then `Nonterminal` can be removed as well. --- compiler/rustc_ast/src/ast_traits.rs | 14 -- compiler/rustc_ast/src/mut_visit.rs | 40 +----- compiler/rustc_ast/src/token.rs | 131 +++--------------- compiler/rustc_ast/src/tokenstream.rs | 26 +--- compiler/rustc_ast_pretty/src/pprust/mod.rs | 6 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 14 +- compiler/rustc_builtin_macros/src/cfg_eval.rs | 6 +- compiler/rustc_expand/src/config.rs | 8 +- compiler/rustc_expand/src/mbe/diagnostics.rs | 4 +- compiler/rustc_expand/src/mbe/transcribe.rs | 15 +- .../rustc_expand/src/proc_macro_server.rs | 9 -- compiler/rustc_parse/src/parser/expr.rs | 36 ++--- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 32 +---- .../rustc_parse/src/parser/nonterminal.rs | 117 +++++----------- compiler/rustc_parse/src/parser/stmt.rs | 9 +- tests/ui/macros/macro-as-fn-body.rs | 2 +- 17 files changed, 104 insertions(+), 367 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 8c07c328eeba0..6a872fc23a04b 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -6,7 +6,6 @@ use std::fmt; use std::marker::PhantomData; use crate::ptr::P; -use crate::token::Nonterminal; use crate::tokenstream::LazyAttrTokenStream; use crate::{ Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField, @@ -196,19 +195,6 @@ impl HasTokens for Attribute { } } -impl HasTokens for Nonterminal { - fn tokens(&self) -> Option<&LazyAttrTokenStream> { - match self { - Nonterminal::NtBlock(block) => block.tokens(), - } - } - fn tokens_mut(&mut self) -> Option<&mut Option> { - match self { - Nonterminal::NtBlock(block) => block.tokens_mut(), - } - } -} - /// A trait for AST nodes having (or not having) attributes. pub trait HasAttrs { /// This is `true` if this `HasAttrs` might support 'custom' (proc-macro) inner diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 6f6366026aa41..a63c217a39d52 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -810,9 +810,9 @@ fn visit_lazy_tts(vis: &mut T, lazy_tts: &mut Option(vis: &mut T, t: &mut Token) { let Token { kind, span } = t; @@ -830,45 +830,11 @@ pub fn visit_token(vis: &mut T, t: &mut Token) { token::NtLifetime(ident, _is_raw) => { vis.visit_ident(ident); } - token::Interpolated(nt) => { - let nt = Lrc::make_mut(nt); - visit_nonterminal(vis, nt); - } _ => {} } vis.visit_span(span); } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -/// Applies the visitor to elements of interpolated nodes. -// -// N.B., this can occur only when applying a visitor to partially expanded -// code, where parsed pieces have gotten implanted ito *other* macro -// invocations. This is relevant for macro hygiene, but possibly not elsewhere. -// -// One problem here occurs because the types for flat_map_item, flat_map_stmt, -// etc., allow the visitor to return *multiple* items; this is a problem for the -// nodes here, because they insist on having exactly one piece. One solution -// would be to mangle the MutVisitor trait to include one-to-many and -// one-to-one versions of these entry points, but that would probably confuse a -// lot of people and help very few. Instead, I'm just going to put in dynamic -// checks. I think the performance impact of this will be pretty much -// nonexistent. The danger is that someone will apply a `MutVisitor` to a -// partially expanded node, and will be confused by the fact that their -// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt` -// nodes. Hopefully they'll wind up reading this comment, and doing something -// appropriate. -// -// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to -// contain multiple items, but decided against it when I looked at -// `parse_item_or_view_item` and tried to figure out what I would do with -// multiple items there.... -fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { - match nt { - token::NtBlock(block) => vis.visit_block(block), - } -} - // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_defaultness(vis: &mut T, defaultness: &mut Defaultness) { match defaultness { diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 90a46bb53f4c3..d1761ce79c468 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -3,12 +3,9 @@ use std::fmt; pub use BinOpToken::*; pub use LitKind::*; -pub use Nonterminal::*; pub use NtExprKind::*; pub use NtPatKind::*; pub use TokenKind::*; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::Lrc; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::Edition; #[allow(clippy::useless_attribute)] // FIXME: following use of `hidden_glob_reexports` incorrectly triggers `useless_attribute` lint. @@ -18,7 +15,6 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::ast; -use crate::ptr::P; use crate::util::case::Case; #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] @@ -52,8 +48,8 @@ pub enum InvisibleOrigin { // `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro. ProcMacro, - // Converted from `TokenKind::Interpolated` in - // `TokenStream::flatten_token`. Treated similarly to `ProcMacro`. + // Converted from `TokenKind::NtLifetime` in `TokenStream::flatten_token`. + // Treated similarly to `ProcMacro`. FlattenToken, } @@ -349,9 +345,7 @@ impl From for bool { } } -// SAFETY: due to the `Clone` impl below, all fields of all variants other than -// `Interpolated` must impl `Copy`. -#[derive(PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum TokenKind { /* Expression-operator symbols. */ /// `=` @@ -440,21 +434,6 @@ pub enum TokenKind { /// the `lifetime` metavariable in the macro's RHS. NtLifetime(Ident, IdentIsRaw), - /// An embedded AST node, as produced by a macro. This only exists for - /// historical reasons. We'd like to get rid of it, for multiple reasons. - /// - It's conceptually very strange. Saying a token can contain an AST - /// node is like saying, in natural language, that a word can contain a - /// sentence. - /// - It requires special handling in a bunch of places in the parser. - /// - It prevents `Token` from implementing `Copy`. - /// It adds complexity and likely slows things down. Please don't add new - /// occurrences of this token kind! - /// - /// The span in the surrounding `Token` is that of the metavariable in the - /// macro's RHS. The span within the Nonterminal is that of the fragment - /// passed to the macro at the call site. - Interpolated(Lrc), - /// A doc comment token. /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc) /// similarly to symbols in string literal tokens. @@ -464,19 +443,6 @@ pub enum TokenKind { Eof, } -impl Clone for TokenKind { - fn clone(&self) -> Self { - // `TokenKind` would impl `Copy` if it weren't for `Interpolated`. So - // for all other variants, this implementation of `clone` is just like - // a copy. This is faster than the `derive(Clone)` version which has a - // separate path for every variant. - match self { - Interpolated(nt) => Interpolated(Lrc::clone(nt)), - _ => unsafe { std::ptr::read(self) }, - } - } -} - #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct Token { pub kind: TokenKind, @@ -571,7 +537,6 @@ impl Token { pub fn uninterpolated_span(&self) -> Span { match self.kind { NtIdent(ident, _) | NtLifetime(ident, _) => ident.span, - Interpolated(ref nt) => nt.use_span(), _ => self.span, } } @@ -589,7 +554,7 @@ impl Token { } OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..) - | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Interpolated(..) | Eof => false, + | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Eof => false, } } @@ -620,7 +585,6 @@ impl Token { PathSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Block | MetaVarKind::Expr { .. } | @@ -693,7 +657,6 @@ impl Token { match self.kind { OpenDelim(Delimiter::Brace) | Literal(..) | BinOp(Minus) => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, ))) => true, @@ -821,31 +784,20 @@ impl Token { /// Is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? pub fn is_metavar_expr(&self) -> bool { - #[allow(irrefutable_let_patterns)] // FIXME: temporary - if let Interpolated(nt) = &self.kind - && let NtBlock(_) = &**nt - { - true - } else if matches!( + matches!( self.is_metavar_seq(), - Some(MetaVarKind::Expr { .. } | MetaVarKind::Literal | MetaVarKind::Path) - ) { - true - } else { - false - } + Some( + MetaVarKind::Expr { .. } + | MetaVarKind::Literal + | MetaVarKind::Path + | MetaVarKind::Block + ) + ) } - /// Is the token an interpolated block (`$b:block`)? - pub fn is_whole_block(&self) -> bool { - #[allow(irrefutable_let_patterns)] // FIXME: temporary - if let Interpolated(nt) = &self.kind - && let NtBlock(..) = &**nt - { - return true; - } - - false + /// Are we at a block from a metavar (`$b:block`)? + pub fn is_metavar_block(&self) -> bool { + matches!(self.is_metavar_seq(), Some(MetaVarKind::Block)) } /// Returns `true` if the token is either the `mut` or `const` keyword. @@ -870,7 +822,8 @@ impl Token { self.is_non_raw_ident_where(|id| id.name == kw) } - /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this token is an identifier equal to `kw` ignoring the case. + /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this + /// token is an identifier equal to `kw` ignoring the case. pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool { self.is_keyword(kw) || (case == Case::Insensitive @@ -991,7 +944,7 @@ impl Token { Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotDotEq | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..) | NtIdent(..) - | Lifetime(..) | NtLifetime(..) | Interpolated(..) | DocComment(..) | Eof => { + | Lifetime(..) | NtLifetime(..) | DocComment(..) | Eof => { return None; } }; @@ -1028,12 +981,6 @@ pub enum NtExprKind { Expr2021 { inferred: bool }, } -#[derive(Clone, Encodable, Decodable)] -/// For interpolation during macro expansion. -pub enum Nonterminal { - NtBlock(P), -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] pub enum NonterminalKind { Item, @@ -1117,47 +1064,6 @@ impl fmt::Display for NonterminalKind { } } -impl Nonterminal { - pub fn use_span(&self) -> Span { - match self { - NtBlock(block) => block.span, - } - } - - pub fn descr(&self) -> &'static str { - match self { - NtBlock(..) => "block", - } - } -} - -impl PartialEq for Nonterminal { - fn eq(&self, _rhs: &Self) -> bool { - // FIXME: Assume that all nonterminals are not equal, we can't compare them - // correctly based on data from AST. This will prevent them from matching each other - // in macros. The comparison will become possible only when each nonterminal has an - // attached token stream from which it was parsed. - false - } -} - -impl fmt::Debug for Nonterminal { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - NtBlock(..) => f.pad("NtBlock(..)"), - } - } -} - -impl HashStable for Nonterminal -where - CTX: crate::HashStableContext, -{ - fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) { - panic!("interpolated tokens should not be present in the HIR") - } -} - // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { @@ -1167,7 +1073,6 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Lit, 12); static_assert_size!(LitKind, 2); - static_assert_size!(Nonterminal, 8); static_assert_size!(Token, 24); static_assert_size!(TokenKind, 16); // tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 2ca4ada3295ad..4a9b4adf85ca6 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -24,7 +24,7 @@ use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym}; use crate::ast::AttrStyle; use crate::ast_traits::{HasAttrs, HasTokens}; -use crate::token::{self, Delimiter, InvisibleOrigin, Nonterminal, Token, TokenKind}; +use crate::token::{self, Delimiter, InvisibleOrigin, Token, TokenKind}; use crate::{AttrVec, Attribute}; /// Part of a `TokenStream`. @@ -304,11 +304,6 @@ pub struct AttrsTarget { } /// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. -/// -/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s -/// instead of a representation of the abstract syntax tree. -/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for -/// backwards compatibility. #[derive(Clone, Debug, Default, Encodable, Decodable)] pub struct TokenStream(pub(crate) Lrc>); @@ -475,12 +470,6 @@ impl TokenStream { TokenStream::new(tts) } - pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream { - match nt { - Nonterminal::NtBlock(block) => TokenStream::from_ast(block), - } - } - fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree { match token.kind { token::NtIdent(ident, is_raw) => { @@ -492,12 +481,6 @@ impl TokenStream { Delimiter::Invisible(InvisibleOrigin::FlattenToken), TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span), ), - token::Interpolated(ref nt) => TokenTree::Delimited( - DelimSpan::from_single(token.span), - DelimSpacing::new(Spacing::JointHidden, spacing), - Delimiter::Invisible(InvisibleOrigin::FlattenToken), - TokenStream::from_nonterminal_ast(&nt).flattened(), - ), _ => TokenTree::Token(token.clone(), spacing), } } @@ -515,10 +498,9 @@ impl TokenStream { pub fn flattened(&self) -> TokenStream { fn can_skip(stream: &TokenStream) -> bool { stream.trees().all(|tree| match tree { - TokenTree::Token(token, _) => !matches!( - token.kind, - token::NtIdent(..) | token::NtLifetime(..) | token::Interpolated(..) - ), + TokenTree::Token(token, _) => { + !matches!(token.kind, token::NtIdent(..) | token::NtLifetime(..)) + } TokenTree::Delimited(.., inner) => can_skip(inner), }) } diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs index 97cb6e52d5625..551506f2aef8a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/mod.rs +++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs @@ -5,14 +5,10 @@ pub mod state; use std::borrow::Cow; use rustc_ast as ast; -use rustc_ast::token::{Nonterminal, Token, TokenKind}; +use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; pub use state::{AnnNode, Comments, PpAnn, PrintState, State, print_crate}; -pub fn nonterminal_to_string(nt: &Nonterminal) -> String { - State::new().nonterminal_to_string(nt) -} - /// Print the token kind precisely, without converting `$crate` into its respective crate name. pub fn token_kind_to_string(tok: &TokenKind) -> Cow<'static, str> { State::new().token_kind_to_string(tok) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d7c531f37608d..930eccab9803c 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -10,9 +10,7 @@ use std::borrow::Cow; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::ptr::P; -use rustc_ast::token::{ - self, BinOpToken, CommentKind, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind, -}; +use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree}; use rustc_ast::util::classify; use rustc_ast::util::comments::{Comment, CommentStyle}; @@ -890,14 +888,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } } - fn nonterminal_to_string(&self, nt: &Nonterminal) -> String { - // We extract the token stream from the AST fragment and pretty print - // it, rather than using AST pretty printing, because `Nonterminal` is - // slated for removal in #124141. (This method will also then be - // removed.) - self.tts_to_string(&TokenStream::from_nonterminal_ast(nt)) - } - /// Print the token kind precisely, without converting `$crate` into its respective crate name. fn token_kind_to_string(&self, tok: &TokenKind) -> Cow<'static, str> { self.token_kind_to_string_ext(tok, None) @@ -972,8 +962,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere doc_comment_to_string(comment_kind, attr_style, data).into() } token::Eof => "".into(), - - token::Interpolated(ref nt) => self.nonterminal_to_string(&nt).into(), } } diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 7f61b9a511027..b337de1c9e307 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -93,11 +93,11 @@ impl CfgEval<'_> { // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // process is lossless, so this process is invisible to proc-macros. - // 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`) + // 'Flatten' all nonterminals (i.e. `TokenKind::Nt{Ident,Lifetime}`) // to `None`-delimited groups containing the corresponding tokens. This // is normally delayed until the proc-macro server actually needs to - // provide a `TokenKind::Interpolated` to a proc-macro. We do this earlier, - // so that we can handle cases like: + // provide tokens to a proc-macro. We do this earlier, so that we can + // handle cases like: // // ```rust // #[cfg_eval] #[cfg] $item diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index dc6aa110f459b..2847ea1232a2f 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -226,13 +226,7 @@ impl<'a> StripUnconfigured<'a> { Some(AttrTokenTree::Delimited(sp, spacing, delim, inner)) } AttrTokenTree::Token( - Token { - kind: - TokenKind::NtIdent(..) - | TokenKind::NtLifetime(..) - | TokenKind::Interpolated(..), - .. - }, + Token { kind: TokenKind::NtIdent(..) | TokenKind::NtLifetime(..), .. }, _, ) => { panic!("Nonterminal should have been flattened: {:?}", tree); diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 77b8d22892218..91cc2f21018f1 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -67,9 +67,7 @@ pub(super) fn failed_to_match_macro( } if let MatcherLoc::Token { token: expected_token } = &remaining_matcher - && (matches!(expected_token.kind, TokenKind::Interpolated(_)) - || matches!(token.kind, TokenKind::Interpolated(_)) - || matches!(expected_token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_))) + && (matches!(expected_token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_))) || matches!(token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_)))) { err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens"); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index f62caf06c819f..4961ddbf30b52 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -7,7 +7,6 @@ use rustc_ast::token::{ use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast::{ExprKind, StmtKind, UnOp}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parser::ParseNtResult; @@ -304,7 +303,9 @@ pub(super) fn transcribe<'a>( let tt = match cur_matched { MatchedSingle(ParseNtResult::Tt(tt)) => { // `tt`s are emitted into the output stream directly as "raw tokens", - // without wrapping them into groups. + // without wrapping them into groups. Other variables are emitted into + // the output stream as groups with `Delimiter::Invisible` to maintain + // parsing priorities. maybe_use_metavar_location(psess, &stack, sp, tt, &mut marker) } MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => { @@ -320,6 +321,9 @@ pub(super) fn transcribe<'a>( MatchedSingle(ParseNtResult::Item(item)) => { mk_delimited(MetaVarKind::Item, TokenStream::from_ast(item)) } + MatchedSingle(ParseNtResult::Block(block)) => { + mk_delimited(MetaVarKind::Block, TokenStream::from_ast(block)) + } MatchedSingle(ParseNtResult::Stmt(stmt)) => { let stream = if let StmtKind::Empty = stmt.kind { // FIXME: Properly collect tokens for empty statements. @@ -367,13 +371,6 @@ pub(super) fn transcribe<'a>( MatchedSingle(ParseNtResult::Vis(vis)) => { mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) } - MatchedSingle(ParseNtResult::Nt(nt)) => { - // Other variables are emitted into the output stream as groups with - // `Delimiter::Invisible` to maintain parsing priorities. - // `Interpolated` is currently used for such groups in rustc parser. - marker.visit_span(&mut sp); - TokenTree::token_alone(token::Interpolated(Lrc::clone(nt)), sp) - } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. return Err(dcx.create_err(VarStillRepeating { span: sp, ident })); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index c3470ffc27990..1306d8289709e 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -310,15 +310,6 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { - let stream = TokenStream::from_nonterminal_ast(&nt); - trees.push(TokenTree::Group(Group { - delimiter: pm::Delimiter::None, - stream: Some(stream), - span: DelimSpan::from_single(span), - })) - } - OpenDelim(..) | CloseDelim(..) => unreachable!(), Eof => unreachable!(), } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a182c132dde9a..240f961115994 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -676,9 +676,7 @@ impl<'a> Parser<'a> { /// Returns the span of expr if it was not interpolated, or the span of the interpolated token. fn interpolated_or_expr_span(&self, expr: &Expr) -> Span { match self.prev_token.kind { - TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => { - self.prev_token.span - } + TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) => self.prev_token.span, TokenKind::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { // `expr.span` is the interpolated span, because invisible open // and close delims both get marked with the same span, one @@ -1393,15 +1391,7 @@ impl<'a> Parser<'a> { maybe_recover_from_interpolated_ty_qpath!(self, true); let span = self.token.span; - if let token::Interpolated(nt) = &self.token.kind { - match &**nt { - token::NtBlock(block) => { - let block = block.clone(); - self.bump(); - return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); - } - }; - } else if let Some(expr) = self.eat_metavar_seq_with_matcher( + if let Some(expr) = self.eat_metavar_seq_with_matcher( |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), |this| { let expr = this.parse_expr(); @@ -1420,9 +1410,13 @@ impl<'a> Parser<'a> { self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) { return Ok(lit); - } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| { - this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type)) - }) { + } else if let Some(block) = + self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block()) + { + return Ok(self.mk_expr(span, ExprKind::Block(block, None))); + } else if let Some(path) = + self.eat_metavar_seq(MetaVarKind::Path, |this| this.parse_path(PathStyle::Type)) + { return Ok(self.mk_expr(span, ExprKind::Path(None, path))); } @@ -1675,7 +1669,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Loop) { self.parse_expr_loop(label, lo) } else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace)) - || self.token.is_whole_block() + || self.token.is_metavar_block() { self.parse_expr_block(label, lo, BlockCheckMode::Default) } else if !ate_colon @@ -2345,7 +2339,7 @@ impl<'a> Parser<'a> { } } - if self.token.is_whole_block() { + if self.token.is_metavar_block() { self.dcx().emit_err(errors::InvalidBlockMacroSegment { span: self.token.span, context: lo.to(self.token.span), @@ -3463,7 +3457,7 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Catch]) && self - .look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()) + .look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block()) && !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) } @@ -3474,7 +3468,7 @@ impl<'a> Parser<'a> { fn is_try_block(&self) -> bool { self.token.is_keyword(kw::Try) && self - .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()) + .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block()) && self.token.uninterpolated_span().at_least_rust_2018() } @@ -3508,12 +3502,12 @@ impl<'a> Parser<'a> { // `async move {` self.is_keyword_ahead(lookahead + 1, &[kw::Move]) && self.look_ahead(lookahead + 2, |t| { - *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block() + *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block() }) ) || ( // `async {` self.look_ahead(lookahead + 1, |t| { - *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block() + *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block() }) )) } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8ac272dd86d9f..8cb5593e5e6d4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2496,7 +2496,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; *sig_hi = self.prev_token.span; (AttrVec::new(), None) - } else if self.check(&token::OpenDelim(Delimiter::Brace)) || self.token.is_whole_block() { + } else if self.check(&token::OpenDelim(Delimiter::Brace)) || self.token.is_metavar_block() { self.parse_block_common(self.token.span, BlockCheckMode::Default, false) .map(|(attrs, body)| (attrs, Some(body)))? } else if self.token == token::Eq { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 32a8256cf54e9..c8bfb3c3bb791 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -22,8 +22,8 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtExprKind, NtPatKind, - Token, TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, NtExprKind, NtPatKind, Token, + TokenKind, }; use rustc_ast::tokenstream::{ AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor, @@ -36,7 +36,6 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diag, FatalError, MultiSpan, PResult}; use rustc_index::interval::IntervalSet; use rustc_session::parse::ParseSess; @@ -97,21 +96,6 @@ pub enum ForceCollect { No, } -#[macro_export] -macro_rules! maybe_whole { - ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { - #[allow(irrefutable_let_patterns)] // FIXME: temporary - if let token::Interpolated(nt) = &$p.token.kind - && let token::$constructor(x) = &**nt - { - #[allow(unused_mut)] - let mut $x = x.clone(); - $p.bump(); - return Ok($e); - } - }; -} - /// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`. #[macro_export] macro_rules! maybe_recover_from_interpolated_ty_qpath { @@ -453,7 +437,6 @@ pub fn token_descr(token: &Token) -> String { (Some(TokenDescription::MetaVar(kind)), _) => format!("`{kind}` metavariable"), (None, TokenKind::NtIdent(..)) => format!("identifier `{s}`"), (None, TokenKind::NtLifetime(..)) => format!("lifetime `{s}`"), - (None, TokenKind::Interpolated(node)) => format!("{} `{s}`", node.descr()), (None, _) => format!("`{s}`"), } } @@ -826,8 +809,10 @@ impl<'a> Parser<'a> { fn check_inline_const(&self, dist: usize) -> bool { self.is_keyword_ahead(dist, &[kw::Const]) && self.look_ahead(dist + 1, |t| match &t.kind { - token::Interpolated(nt) => matches!(&**nt, token::NtBlock(..)), token::OpenDelim(Delimiter::Brace) => true, + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Block, + ))) => true, _ => false, }) } @@ -1379,7 +1364,7 @@ impl<'a> Parser<'a> { // Avoid const blocks and const closures to be parsed as const items if (self.check_const_closure() == is_closure) && !self - .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()) + .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block()) && self.eat_keyword_case(kw::Const, case) { Const::Yes(self.prev_token.uninterpolated_span()) @@ -1731,7 +1716,6 @@ impl<'a> Parser<'a> { pub fn uninterpolated_token_span(&self) -> Span { match &self.token.kind { - token::Interpolated(nt) => nt.use_span(), token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { self.look_ahead(1, |t| t.span) } @@ -1788,6 +1772,7 @@ pub enum ParseNtResult { Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), Item(P), + Block(P), Stmt(P), Pat(P, NtPatKind), Expr(P, NtExprKind), @@ -1796,7 +1781,4 @@ pub enum ParseNtResult { Meta(P), Path(P), Vis(P), - - /// This variant will eventually be removed, along with `Token::Interpolate`. - Nt(Lrc), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 0f32302f602e9..9fa2116db2c19 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,13 +1,7 @@ -use rustc_ast::HasTokens; use rustc_ast::ptr::P; -use rustc_ast::token::Nonterminal::*; use rustc_ast::token::NtExprKind::*; use rustc_ast::token::NtPatKind::*; -use rustc_ast::token::{ - self, Delimiter, InvisibleOrigin, MetaVarKind, Nonterminal, NonterminalKind, Token, -}; -use rustc_ast_pretty::pprust; -use rustc_data_structures::sync::Lrc; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, NonterminalKind, Token}; use rustc_errors::PResult; use rustc_span::symbol::{Ident, kw}; @@ -44,13 +38,6 @@ impl<'a> Parser<'a> { } } - /// Old variant of `may_be_ident`. Being phased out. - fn nt_may_be_ident(nt: &Nonterminal) -> bool { - match nt { - NtBlock(_) => false, - } - } - match kind { // `expr_2021` and earlier NonterminalKind::Expr(Expr2021 { .. }) => { @@ -82,16 +69,12 @@ impl<'a> Parser<'a> { | token::Ident(..) | token::NtIdent(..) | token::NtLifetime(..) - | token::Interpolated(_) | token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => true, _ => token.can_begin_type(), }, NonterminalKind::Block => match &token.kind { token::OpenDelim(Delimiter::Brace) => true, token::NtLifetime(..) => true, - token::Interpolated(nt) => match &**nt { - NtBlock(_) => true, - }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block | MetaVarKind::Stmt @@ -111,7 +94,6 @@ impl<'a> Parser<'a> { }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::PathSep | token::Ident(..) | token::NtIdent(..) => true, - token::Interpolated(nt) => nt_may_be_ident(nt), token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => { may_be_ident(*kind) } @@ -136,61 +118,51 @@ impl<'a> Parser<'a> { // which requires having captured tokens available. Since we cannot determine // in advance whether or not a proc-macro will be (transitively) invoked, // we always capture tokens for any `Nonterminal` which needs them. - let mut nt = match kind { + match kind { // Note that TT is treated differently to all the others. - NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())), + NonterminalKind::TT => Ok(ParseNtResult::Tt(self.parse_token_tree())), NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { - Some(item) => return Ok(ParseNtResult::Item(item)), - None => { - return Err(self - .dcx() - .create_err(UnexpectedNonterminal::Item(self.token.span))); - } + Some(item) => Ok(ParseNtResult::Item(item)), + None => Err(self.dcx().create_err(UnexpectedNonterminal::Item(self.token.span))), }, NonterminalKind::Block => { // While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`), // the ':block' matcher does not support them - NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) + Ok(ParseNtResult::Block(self.collect_tokens_no_attrs(|this| this.parse_block())?)) } NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { - Some(stmt) => return Ok(ParseNtResult::Stmt(P(stmt))), + Some(stmt) => Ok(ParseNtResult::Stmt(P(stmt))), None => { - return Err(self - .dcx() - .create_err(UnexpectedNonterminal::Statement(self.token.span))); + Err(self.dcx().create_err(UnexpectedNonterminal::Statement(self.token.span))) } }, - NonterminalKind::Pat(pat_kind) => { - return Ok(ParseNtResult::Pat( - self.collect_tokens_no_attrs(|this| match pat_kind { - PatParam { .. } => this.parse_pat_no_top_alt(None, None), - PatWithOr => this.parse_pat_allow_top_alt( - None, - RecoverComma::No, - RecoverColon::No, - CommaRecoveryMode::EitherTupleOrPipe, - ), - })?, - pat_kind, - )); - } + NonterminalKind::Pat(pat_kind) => Ok(ParseNtResult::Pat( + self.collect_tokens_no_attrs(|this| match pat_kind { + PatParam { .. } => this.parse_pat_no_top_alt(None, None), + PatWithOr => this.parse_pat_allow_top_alt( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::EitherTupleOrPipe, + ), + })?, + pat_kind, + )), NonterminalKind::Expr(expr_kind) => { - return Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind)); + Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind)) } NonterminalKind::Literal => { // The `:literal` matcher does not support attributes. - return Ok(ParseNtResult::Literal( + Ok(ParseNtResult::Literal( self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?, - )); - } - NonterminalKind::Ty => { - return Ok(ParseNtResult::Ty( - self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, - )); + )) } - // this could be handled like a token, since it is one + NonterminalKind::Ty => Ok(ParseNtResult::Ty( + self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, + )), + // This could be handled like a token, since it is one. NonterminalKind::Ident => { - return if let Some((ident, is_raw)) = get_macro_ident(&self.token) { + if let Some((ident, is_raw)) = get_macro_ident(&self.token) { self.bump(); Ok(ParseNtResult::Ident(ident, is_raw)) } else { @@ -198,25 +170,22 @@ impl<'a> Parser<'a> { span: self.token.span, token: self.token.clone(), })) - }; - } - NonterminalKind::Path => { - return Ok(ParseNtResult::Path(P( - self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))? - ))); + } } + NonterminalKind::Path => Ok(ParseNtResult::Path(P( + self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))? + ))), NonterminalKind::Meta => { - return Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?))); + Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?))) } NonterminalKind::Vis => { - return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| { - this.parse_visibility(FollowedByType::Yes) - })?))); + Ok(ParseNtResult::Vis(P(self + .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?))) } NonterminalKind::Lifetime => { // We want to keep `'keyword` parsing, just like `keyword` is still // an ident for nonterminal purposes. - return if let Some((ident, is_raw)) = self.token.lifetime() { + if let Some((ident, is_raw)) = self.token.lifetime() { self.bump(); Ok(ParseNtResult::Lifetime(ident, is_raw)) } else { @@ -224,21 +193,9 @@ impl<'a> Parser<'a> { span: self.token.span, token: self.token.clone(), })) - }; + } } - }; - - // If tokens are supported at all, they should be collected. - if matches!(nt.tokens_mut(), Some(None)) { - panic!( - "Missing tokens for nt {:?} at {:?}: {:?}", - nt, - nt.use_span(), - pprust::nonterminal_to_string(&nt) - ); } - - Ok(ParseNtResult::Nt(Lrc::new(nt))) } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1351af406b27c..59c3ee34de101 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -23,8 +23,7 @@ use super::{ AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, Trailing, UsePreAttrPos, }; -use crate::errors::MalformedLoopLabel; -use crate::{errors, maybe_whole}; +use crate::errors::{self, MalformedLoopLabel}; impl<'a> Parser<'a> { /// Parses a statement. This stops just before trailing semicolons on everything but items. @@ -657,7 +656,9 @@ impl<'a> Parser<'a> { blk_mode: BlockCheckMode, can_be_struct_literal: bool, ) -> PResult<'a, (AttrVec, P)> { - maybe_whole!(self, NtBlock, |block| (AttrVec::new(), block)); + if let Some(block) = self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block()) { + return Ok((AttrVec::new(), block)); + } let maybe_ident = self.prev_token.clone(); self.maybe_recover_unexpected_block_label(); @@ -833,7 +834,7 @@ impl<'a> Parser<'a> { { if self.token == token::Colon && self.look_ahead(1, |token| { - token.is_whole_block() + token.is_metavar_block() || matches!( token.kind, token::Ident( diff --git a/tests/ui/macros/macro-as-fn-body.rs b/tests/ui/macros/macro-as-fn-body.rs index e0542edc2a521..188c7f7f728c9 100644 --- a/tests/ui/macros/macro-as-fn-body.rs +++ b/tests/ui/macros/macro-as-fn-body.rs @@ -1,7 +1,7 @@ // //@ run-pass // -// Description - ensure Interpolated blocks can act as valid function bodies +// Description - ensure block metavariables can act as valid function bodies // Covered cases: free functions, struct methods, and default trait functions macro_rules! def_fn { From db50c0f0a929fc279ae613adfe84e9595a5b217d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 16 May 2024 09:22:37 +1000 Subject: [PATCH 11/12] Impl `Copy` for `Token` and `TokenKind`. --- compiler/rustc_ast/src/token.rs | 4 ++-- compiler/rustc_ast/src/tokenstream.rs | 2 +- compiler/rustc_expand/src/mbe/diagnostics.rs | 2 +- compiler/rustc_expand/src/mbe/macro_parser.rs | 4 ++-- compiler/rustc_expand/src/mbe/macro_rules.rs | 8 ++++---- compiler/rustc_expand/src/mbe/quoted.rs | 4 ++-- compiler/rustc_expand/src/mbe/transcribe.rs | 4 ++-- .../rustc_parse/src/lexer/unicode_chars.rs | 2 +- .../rustc_parse/src/parser/attr_wrapper.rs | 4 ++-- .../rustc_parse/src/parser/diagnostics.rs | 12 +++++------ compiler/rustc_parse/src/parser/expr.rs | 20 +++++++++---------- compiler/rustc_parse/src/parser/item.rs | 5 ++--- compiler/rustc_parse/src/parser/mod.rs | 10 +++++----- .../rustc_parse/src/parser/nonterminal.rs | 4 ++-- compiler/rustc_parse/src/parser/pat.rs | 6 +++--- compiler/rustc_parse/src/parser/path.rs | 4 ++-- compiler/rustc_parse/src/parser/stmt.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 4 ++-- src/tools/rustfmt/src/macros.rs | 14 ++++++------- 19 files changed, 57 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index d1761ce79c468..ad49683e85991 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -345,7 +345,7 @@ impl From for bool { } } -#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum TokenKind { /* Expression-operator symbols. */ /// `=` @@ -443,7 +443,7 @@ pub enum TokenKind { Eof, } -#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct Token { pub kind: TokenKind, pub span: Span, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 4a9b4adf85ca6..887475a1a6710 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -481,7 +481,7 @@ impl TokenStream { Delimiter::Invisible(InvisibleOrigin::FlattenToken), TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span), ), - _ => TokenTree::Token(token.clone(), spacing), + _ => TokenTree::Token(*token, spacing), } } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 91cc2f21018f1..296788f57798b 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -161,7 +161,7 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match .map_or(true, |failure| failure.is_better_position(*approx_position)) { self.best_failure = Some(BestFailure { - token: token.clone(), + token: *token, position_in_tokenstream: *approx_position, msg, remaining_matcher: self diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 2a8dddc1e004f..752d327e55d74 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -180,7 +180,7 @@ pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec { for tt in tts { match tt { TokenTree::Token(token) => { - locs.push(MatcherLoc::Token { token: token.clone() }); + locs.push(MatcherLoc::Token { token: *token }); } TokenTree::Delimited(span, _, delimited) => { let open_token = Token::new(token::OpenDelim(delimited.delim), span.open); @@ -649,7 +649,7 @@ impl TtParser { // There are no possible next positions AND we aren't waiting for the black-box // parser: syntax error. return Failure(T::build_failure( - parser.token.clone(), + parser.token, parser.approx_token_stream_pos(), "no rules expected this token in macro call", )); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index a373c753cc114..7cc4cc4969933 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -778,7 +778,7 @@ impl<'tt> FirstSets<'tt> { // token could be the separator token itself. if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { - first.add_one_maybe(TtHandle::from_token(sep.clone())); + first.add_one_maybe(TtHandle::from_token(*sep)); } // Reverse scan: Sequence comes before `first`. @@ -841,7 +841,7 @@ impl<'tt> FirstSets<'tt> { // If the sequence contents can be empty, then the first // token could be the separator token itself. if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { - first.add_one_maybe(TtHandle::from_token(sep.clone())); + first.add_one_maybe(TtHandle::from_token(*sep)); } assert!(first.maybe_empty); @@ -917,7 +917,7 @@ impl<'tt> Clone for TtHandle<'tt> { // This variant *must* contain a `mbe::TokenTree::Token`, and not // any other variant of `mbe::TokenTree`. TtHandle::Token(mbe::TokenTree::Token(tok)) => { - TtHandle::Token(mbe::TokenTree::Token(tok.clone())) + TtHandle::Token(mbe::TokenTree::Token(*tok)) } _ => unreachable!(), @@ -1093,7 +1093,7 @@ fn check_matcher_core<'tt>( let mut new; let my_suffix = if let Some(sep) = &seq_rep.separator { new = suffix_first.clone(); - new.add_one_maybe(TtHandle::from_token(sep.clone())); + new.add_one_maybe(TtHandle::from_token(*sep)); &new } else { &suffix_first diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 36094707faceb..d75940e5ae3a0 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -284,7 +284,7 @@ fn parse_tree<'a>( } // `tree` is an arbitrary token. Keep it. - tokenstream::TokenTree::Token(token, _) => TokenTree::Token(token.clone()), + tokenstream::TokenTree::Token(token, _) => TokenTree::Token(*token), // `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to // descend into the delimited set and further parse it. @@ -320,7 +320,7 @@ fn parse_kleene_op<'a>( match input.next() { Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(token) { Some(op) => Ok(Ok((op, token.span))), - None => Ok(Err(token.clone())), + None => Ok(Err(*token)), }, tree => Err(tree.map_or(span, tokenstream::TokenTree::span)), } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 4961ddbf30b52..75978a2df8688 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -163,7 +163,7 @@ pub(super) fn transcribe<'a>( if repeat_idx < repeat_len { frame.idx = 0; if let Some(sep) = sep { - result.push(TokenTree::Token(sep.clone(), Spacing::Alone)); + result.push(TokenTree::Token(*sep, Spacing::Alone)); } continue; } @@ -418,7 +418,7 @@ pub(super) fn transcribe<'a>( // Nothing much to do here. Just push the token to the result, being careful to // preserve syntax context. mbe::TokenTree::Token(token) => { - let mut token = token.clone(); + let mut token = *token; mut_visit::visit_token(&mut marker, &mut token); let tt = TokenTree::Token(token, Spacing::Alone); result.push(tt); diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index d78b3664b1ee8..0d1ea767ea7ee 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -377,7 +377,7 @@ pub(super) fn check_for_substitution( ascii_name, }) }; - (token.clone(), sugg) + (*token, sugg) } /// Extract string if found at current position with given delimiters diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 434f71beac243..856dcab5a1fec 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -120,7 +120,7 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { // produce an empty `TokenStream` if no calls were made, and omit the // final token otherwise. let mut cursor_snapshot = self.cursor_snapshot.clone(); - let tokens = iter::once(FlatToken::Token(self.start_token.clone())) + let tokens = iter::once(FlatToken::Token(self.start_token)) .chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next()))) .take(self.num_calls as usize); @@ -186,7 +186,7 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { impl<'a> Parser<'a> { pub(super) fn collect_pos(&self) -> CollectPos { CollectPos { - start_token: (self.token.clone(), self.token_spacing), + start_token: (self.token, self.token_spacing), cursor_snapshot: self.token_cursor.clone(), start_pos: self.num_bump_calls, } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index e4bba95eb03d7..d89ef10893346 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -320,7 +320,7 @@ impl<'a> Parser<'a> { let mut recovered_ident = None; // we take this here so that the correct original token is retained in // the diagnostic, regardless of eager recovery. - let bad_token = self.token.clone(); + let bad_token = self.token; // suggest prepending a keyword in identifier position with `r#` let suggest_raw = if let Some((ident, IdentIsRaw::No)) = self.token.ident() @@ -380,7 +380,7 @@ impl<'a> Parser<'a> { // if the previous token is a valid keyword // that might use a generic, then suggest a correct // generic placement (later on) - let maybe_keyword = self.prev_token.clone(); + let maybe_keyword = self.prev_token; if valid_prev_keywords.into_iter().any(|x| maybe_keyword.is_keyword(x)) { // if we have a valid keyword, attempt to parse generics // also obtain the keywords symbol @@ -496,7 +496,7 @@ impl<'a> Parser<'a> { false } - if **token != parser::TokenType::Token(self.token.kind.clone()) { + if **token != parser::TokenType::Token(self.token.kind) { let eq = is_ident_eq_keyword(&self.token.kind, &token); // If the suggestion is a keyword and the found token is an ident, // the content of which are equal to the suggestion's content, @@ -560,7 +560,7 @@ impl<'a> Parser<'a> { // let y = 42; let guar = self.dcx().emit_err(ExpectedSemi { span: self.token.span, - token: self.token.clone(), + token: self.token, unexpected_token_label: None, sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span), }); @@ -585,7 +585,7 @@ impl<'a> Parser<'a> { let span = self.prev_token.span.shrink_to_hi(); let guar = self.dcx().emit_err(ExpectedSemi { span, - token: self.token.clone(), + token: self.token, unexpected_token_label: Some(self.token.span), sugg: ExpectedSemiSugg::AddSemi(span), }); @@ -830,7 +830,7 @@ impl<'a> Parser<'a> { let span = self.prev_token.span.shrink_to_hi(); let mut err = self.dcx().create_err(ExpectedSemi { span, - token: self.token.clone(), + token: self.token, unexpected_token_label: Some(self.token.span), sugg: ExpectedSemiSugg::AddSemi(span), }); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 240f961115994..026b9cad4d2ce 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -381,7 +381,7 @@ impl<'a> Parser<'a> { fn error_found_expr_would_be_stmt(&self, lhs: &Expr) { self.dcx().emit_err(errors::FoundExprWouldBeStmt { span: self.token.span, - token: self.token.clone(), + token: self.token, suggestion: ExprParenthesesNeeded::surrounding(lhs.span), }); } @@ -456,7 +456,7 @@ impl<'a> Parser<'a> { cur_op_span: Span, ) -> PResult<'a, P> { let rhs = if self.is_at_start_of_range_notation_rhs() { - let maybe_lt = self.token.clone(); + let maybe_lt = self.token; let attrs = self.parse_outer_attributes()?; Some( self.parse_expr_assoc_with(prec + 1, attrs) @@ -650,7 +650,7 @@ impl<'a> Parser<'a> { /// Recover on `not expr` in favor of `!expr`. fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - let negated_token = self.look_ahead(1, |t| t.clone()); + let negated_token = self.look_ahead(1, |t| *t); let sub_diag = if negated_token.is_numeric_lit() { errors::NotAsNegationOperatorSub::SuggestNotBitwise @@ -1610,7 +1610,7 @@ impl<'a> Parser<'a> { } fn parse_expr_path_start(&mut self) -> PResult<'a, P> { - let maybe_eq_tok = self.prev_token.clone(); + let maybe_eq_tok = self.prev_token; let (qself, path) = if self.eat_lt() { let lt_span = self.prev_token.span; let (qself, path) = self.parse_qpath(PathStyle::Expr).map_err(|mut err| { @@ -2056,7 +2056,7 @@ impl<'a> Parser<'a> { &mut self, mk_lit_char: impl FnOnce(Symbol, Span) -> L, ) -> PResult<'a, L> { - let token = self.token.clone(); + let token = self.token; let err = |self_: &Self| { let msg = format!("unexpected token: {}", super::token_descr(&token)); self_.dcx().struct_span_err(token.span, msg) @@ -2364,7 +2364,7 @@ impl<'a> Parser<'a> { fn parse_expr_closure(&mut self) -> PResult<'a, P> { let lo = self.token.span; - let before = self.prev_token.clone(); + let before = self.prev_token; let binder = if self.check_keyword(kw::For) { let lo = self.token.span; let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; @@ -2395,8 +2395,8 @@ impl<'a> Parser<'a> { FnRetTy::Default(_) => { let restrictions = self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET; - let prev = self.prev_token.clone(); - let token = self.token.clone(); + let prev = self.prev_token; + let token = self.token; let attrs = self.parse_outer_attributes()?; match self.parse_expr_res(restrictions, attrs) { Ok((expr, _)) => expr, @@ -2595,7 +2595,7 @@ impl<'a> Parser<'a> { } } else { let attrs = self.parse_outer_attributes()?; // For recovery. - let maybe_fatarrow = self.token.clone(); + let maybe_fatarrow = self.token; let block = if self.check(&token::OpenDelim(Delimiter::Brace)) { self.parse_block()? } else if let Some(block) = recover_block_from_condition(self) { @@ -3812,7 +3812,7 @@ impl<'a> Parser<'a> { return Err(this.dcx().create_err(errors::ExpectedStructField { span: this.look_ahead(1, |t| t.span), ident_span: this.token.span, - token: this.look_ahead(1, |t| t.clone()), + token: this.look_ahead(1, |t| *t), })); } let (ident, expr) = if is_shorthand { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8cb5593e5e6d4..4a903274f45a9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1715,8 +1715,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; body } else { - let err = - errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token.clone()); + let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token); return Err(self.dcx().create_err(err)); }; @@ -2262,7 +2261,7 @@ impl<'a> Parser<'a> { || self.token.is_keyword(kw::Union)) && self.look_ahead(1, |t| t.is_ident()) { - let kw_token = self.token.clone(); + let kw_token = self.token; let kw_str = pprust::token_to_string(&kw_token); let item = self.parse_item(ForceCollect::No)?; let mut item = item.unwrap().span; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index c8bfb3c3bb791..399da82814ed0 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -294,12 +294,12 @@ impl TokenCursor { // below can be removed. if let Some(tree) = self.tree_cursor.next_ref() { match tree { - &TokenTree::Token(ref token, spacing) => { + &TokenTree::Token(token, spacing) => { debug_assert!(!matches!( token.kind, token::OpenDelim(_) | token::CloseDelim(_) )); - return (token.clone(), spacing); + return (token, spacing); } &TokenTree::Delimited(sp, spacing, delim, ref tts) => { let trees = tts.clone().into_trees(); @@ -589,7 +589,7 @@ impl<'a> Parser<'a> { fn check(&mut self, tok: &TokenKind) -> bool { let is_present = self.token == *tok; if !is_present { - self.expected_tokens.push(TokenType::Token(tok.clone())); + self.expected_tokens.push(TokenType::Token(*tok)); } is_present } @@ -1486,7 +1486,7 @@ impl<'a> Parser<'a> { _ => { let prev_spacing = self.token_spacing; self.bump(); - TokenTree::Token(self.prev_token.clone(), prev_spacing) + TokenTree::Token(self.prev_token, prev_spacing) } } } @@ -1679,7 +1679,7 @@ impl<'a> Parser<'a> { dbg_fmt.field("prev_token", &parser.prev_token); let mut tokens = vec![]; for i in 0..*lookahead { - let tok = parser.look_ahead(i, |tok| tok.kind.clone()); + let tok = parser.look_ahead(i, |tok| tok.kind); let is_eof = tok == TokenKind::Eof; tokens.push(tok); if is_eof { diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 9fa2116db2c19..3dfc8101d3e43 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -168,7 +168,7 @@ impl<'a> Parser<'a> { } else { Err(self.dcx().create_err(UnexpectedNonterminal::Ident { span: self.token.span, - token: self.token.clone(), + token: self.token, })) } } @@ -191,7 +191,7 @@ impl<'a> Parser<'a> { } else { Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime { span: self.token.span, - token: self.token.clone(), + token: self.token, })) } } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 7b7cf51bd6e04..b75a8f7ee362c 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -336,7 +336,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(TrailingVertNotAllowed { span: self.token.span, start: lo, - token: self.token.clone(), + token: self.token, note_double_vert: matches!(self.token.kind, token::OrOr), }); self.bump(); @@ -1507,8 +1507,8 @@ impl<'a> Parser<'a> { etc = PatFieldsRest::Rest; let mut etc_sp = self.token.span; if first_etc_and_maybe_comma_span.is_none() { - if let Some(comma_tok) = self - .look_ahead(1, |t| if *t == token::Comma { Some(t.clone()) } else { None }) + if let Some(comma_tok) = + self.look_ahead(1, |&t| if t == token::Comma { Some(t) } else { None }) { let nw_span = self .psess diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 518669d104336..40493e91d5780 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -388,8 +388,8 @@ impl<'a> Parser<'a> { } else { // `(T, U) -> R` - let prev_token_before_parsing = self.prev_token.clone(); - let token_before_parsing = self.token.clone(); + let prev_token_before_parsing = self.prev_token; + let token_before_parsing = self.token; let mut snapshot = None; if self.may_recover() && prev_token_before_parsing == token::PathSep diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 59c3ee34de101..62d1993672a02 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -660,7 +660,7 @@ impl<'a> Parser<'a> { return Ok((AttrVec::new(), block)); } - let maybe_ident = self.prev_token.clone(); + let maybe_ident = self.prev_token; self.maybe_recover_unexpected_block_label(); if !self.eat(&token::OpenDelim(Delimiter::Brace)) { return self.error_block_no_opening_brace(); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 865a75f9f3608..142d049deb32a 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -533,7 +533,7 @@ impl<'a> Parser<'a> { // Recovery mutbl = Mutability::Mut; - let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing); + let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing); self.bump(); self.bump_with((dyn_tok, dyn_tok_sp)); } @@ -834,7 +834,7 @@ impl<'a> Parser<'a> { /// ``` fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> { let lo = self.token.span; - let leading_token = self.prev_token.clone(); + let leading_token = self.prev_token; let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis)); let bound = if self.token.is_lifetime() { diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 4083d9398f6bc..2aea43d22e605 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -879,18 +879,18 @@ impl MacroArgParser { }; self.result.push(ParsedMacroArg { - kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()), + kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok), }); Some(()) } - fn update_buffer(&mut self, t: &Token) { + fn update_buffer(&mut self, t: Token) { if self.buf.is_empty() { - self.start_tok = t.clone(); + self.start_tok = t; } else { let needs_space = match next_space(&self.last_tok.kind) { - SpaceState::Ident => ident_like(t), - SpaceState::Punctuation => !ident_like(t), + SpaceState::Ident => ident_like(&t), + SpaceState::Punctuation => !ident_like(&t), SpaceState::Always => true, SpaceState::Never => false, }; @@ -899,7 +899,7 @@ impl MacroArgParser { } } - self.buf.push_str(&pprust::token_to_string(t)); + self.buf.push_str(&pprust::token_to_string(&t)); } fn need_space_prefix(&self) -> bool { @@ -958,7 +958,7 @@ impl MacroArgParser { ) if self.is_meta_var => { self.add_meta_variable(&mut iter)?; } - TokenTree::Token(ref t, _) => self.update_buffer(t), + &TokenTree::Token(t, _) => self.update_buffer(t), &TokenTree::Delimited(_dspan, _spacing, delimited, ref tts) => { if !self.buf.is_empty() { if next_space(&self.last_tok.kind) == SpaceState::Always { From 2479f6cb48989f85c89671cef5b7d553d6151068 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jul 2024 10:16:51 +1000 Subject: [PATCH 12/12] Remove `TokenStream::flattened` and `InvisibleOrigin::FlattenToken`. They are no longer needed. This does slightly worsen the error message for a single test, but that test contains code that is so badly broken that I'm not worried about it. --- compiler/rustc_ast/src/token.rs | 8 +--- compiler/rustc_ast/src/tokenstream.rs | 44 +------------------ compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_builtin_macros/src/cfg_eval.rs | 10 ++--- compiler/rustc_expand/src/config.rs | 6 --- tests/ui/macros/syntax-error-recovery.rs | 4 +- tests/ui/macros/syntax-error-recovery.stderr | 6 +-- 7 files changed, 11 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index ad49683e85991..fa264edd0c32e 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -47,10 +47,6 @@ pub enum InvisibleOrigin { // Converted from `proc_macro::Delimiter` in // `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro. ProcMacro, - - // Converted from `TokenKind::NtLifetime` in `TokenStream::flatten_token`. - // Treated similarly to `ProcMacro`. - FlattenToken, } impl PartialEq for InvisibleOrigin { @@ -142,9 +138,7 @@ impl Delimiter { match self { Delimiter::Parenthesis | Delimiter::Bracket | Delimiter::Brace => false, Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) => false, - Delimiter::Invisible(InvisibleOrigin::FlattenToken | InvisibleOrigin::ProcMacro) => { - true - } + Delimiter::Invisible(InvisibleOrigin::ProcMacro) => true, } } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 887475a1a6710..1f3b271fc6ed7 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -24,7 +24,7 @@ use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym}; use crate::ast::AttrStyle; use crate::ast_traits::{HasAttrs, HasTokens}; -use crate::token::{self, Delimiter, InvisibleOrigin, Token, TokenKind}; +use crate::token::{self, Delimiter, Token, TokenKind}; use crate::{AttrVec, Attribute}; /// Part of a `TokenStream`. @@ -470,48 +470,6 @@ impl TokenStream { TokenStream::new(tts) } - fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree { - match token.kind { - token::NtIdent(ident, is_raw) => { - TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing) - } - token::NtLifetime(ident, is_raw) => TokenTree::Delimited( - DelimSpan::from_single(token.span), - DelimSpacing::new(Spacing::JointHidden, spacing), - Delimiter::Invisible(InvisibleOrigin::FlattenToken), - TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span), - ), - _ => TokenTree::Token(*token, spacing), - } - } - - fn flatten_token_tree(tree: &TokenTree) -> TokenTree { - match tree { - TokenTree::Token(token, spacing) => TokenStream::flatten_token(token, *spacing), - TokenTree::Delimited(span, spacing, delim, tts) => { - TokenTree::Delimited(*span, *spacing, *delim, tts.flattened()) - } - } - } - - #[must_use] - pub fn flattened(&self) -> TokenStream { - fn can_skip(stream: &TokenStream) -> bool { - stream.trees().all(|tree| match tree { - TokenTree::Token(token, _) => { - !matches!(token.kind, token::NtIdent(..) | token::NtLifetime(..)) - } - TokenTree::Delimited(.., inner) => can_skip(inner), - }) - } - - if can_skip(self) { - return self.clone(); - } - - self.trees().map(|tree| TokenStream::flatten_token_tree(tree)).collect() - } - // If `vec` is not empty, try to glue `tt` onto its last token. The return // value indicates if gluing took place. fn try_glue_to_last(vec: &mut Vec, tt: &TokenTree) -> bool { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0b2969a49ba88..3dd0328f431d8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -934,7 +934,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs { - DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.flattened() } + DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.clone() } } /// Lower an associated item constraint. diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index b337de1c9e307..9431710924d10 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -93,11 +93,7 @@ impl CfgEval<'_> { // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // process is lossless, so this process is invisible to proc-macros. - // 'Flatten' all nonterminals (i.e. `TokenKind::Nt{Ident,Lifetime}`) - // to `None`-delimited groups containing the corresponding tokens. This - // is normally delayed until the proc-macro server actually needs to - // provide tokens to a proc-macro. We do this earlier, so that we can - // handle cases like: + // Interesting cases: // // ```rust // #[cfg_eval] #[cfg] $item @@ -105,8 +101,8 @@ impl CfgEval<'_> { // // where `$item` is `#[cfg_attr] struct Foo {}`. We want to make // sure to evaluate *all* `#[cfg]` and `#[cfg_attr]` attributes - the simplest - // way to do this is to do a single parse of a stream without any nonterminals. - let orig_tokens = annotatable.to_tokens().flattened(); + // way to do this is to do a single parse of the token stream. + let orig_tokens = annotatable.to_tokens(); // Re-parse the tokens, setting the `capture_cfg` flag to save extra information // to the captured `AttrTokenStream` (specifically, we capture diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 2847ea1232a2f..681abb9ac511f 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -225,12 +225,6 @@ impl<'a> StripUnconfigured<'a> { inner = self.configure_tokens(&inner); Some(AttrTokenTree::Delimited(sp, spacing, delim, inner)) } - AttrTokenTree::Token( - Token { kind: TokenKind::NtIdent(..) | TokenKind::NtLifetime(..), .. }, - _, - ) => { - panic!("Nonterminal should have been flattened: {:?}", tree); - } AttrTokenTree::Token( Token { kind: TokenKind::OpenDelim(_) | TokenKind::CloseDelim(_), .. }, _, diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs index 6cf9d54e82636..e1681ea32a2ee 100644 --- a/tests/ui/macros/syntax-error-recovery.rs +++ b/tests/ui/macros/syntax-error-recovery.rs @@ -5,14 +5,14 @@ macro_rules! values { $( #[$attr] $token $($inner)? = $value, + //~^ ERROR expected one of `!` or `::`, found `` )* } }; } -//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable +//~^^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable //~| ERROR macro expansion ignores `ty` metavariable and any tokens following values!(STRING(1) as (String) => cfg(test),); -//~^ ERROR expected one of `!` or `::`, found `` fn main() {} diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr index 61758fb9d7dc6..a2059aa1aa802 100644 --- a/tests/ui/macros/syntax-error-recovery.stderr +++ b/tests/ui/macros/syntax-error-recovery.stderr @@ -22,10 +22,10 @@ LL | values!(STRING(1) as (String) => cfg(test),); = note: the usage of `values!` is likely invalid in item context error: expected one of `!` or `::`, found `` - --> $DIR/syntax-error-recovery.rs:15:9 + --> $DIR/syntax-error-recovery.rs:7:17 | -LL | values!(STRING(1) as (String) => cfg(test),); - | ^^^^^^ expected one of `!` or `::` +LL | $token $($inner)? = $value, + | ^^^^^^ expected one of `!` or `::` error: aborting due to 3 previous errors