From eafd0dfd05cca581d66d83aab9549612ba2ed543 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 12 Aug 2022 12:20:10 +1000 Subject: Box the `MacCall` in various types. --- compiler/rustc_parse/src/parser/expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_parse/src/parser/expr.rs') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9d6d632c2e8..f7a9e3d163e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1492,11 +1492,11 @@ impl<'a> Parser<'a> { self.struct_span_err(path.span, "macros cannot use qualified paths").emit(); } let lo = path.span; - let mac = MacCall { + let mac = P(MacCall { path, args: self.parse_mac_args()?, prior_type_ascription: self.last_type_ascription, - }; + }); (lo.to(self.prev_token.span), ExprKind::MacCall(mac)) } else if self.check(&token::OpenDelim(Delimiter::Brace)) && let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path) { -- cgit 1.4.1-3-g733a5 From ffcaa0dee23f60637b74d389470a1d39cfda28ac Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 17 Aug 2022 19:05:49 +0200 Subject: Migrate diagnostics in parser/expr to SessionDiagnostic --- .../rustc_error_messages/locales/en-US/parser.ftl | 109 ++++++ compiler/rustc_parse/src/parser/diagnostics.rs | 343 +++++++++++++++++ compiler/rustc_parse/src/parser/expr.rs | 426 +++++++-------------- 3 files changed, 596 insertions(+), 282 deletions(-) (limited to 'compiler/rustc_parse/src/parser/expr.rs') diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 2d378013dd0..3b37a393846 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -41,3 +41,112 @@ parser_switch_mut_let_order = parser_missing_let_before_mut = missing keyword parser_use_let_not_auto = write `let` instead of `auto` to introduce a new variable parser_use_let_not_var = write `let` instead of `var` to introduce a new variable + +parser_invalid_comparison_operator = invalid comparison operator `{$invalid}` + .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}` + .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering` + +parser_invalid_logical_operator = `{$incorrect}` is not a logical operator + .note = unlike in e.g., python and PHP, `&&` and `||` are used for logical operators + .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction + .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction + +parser_tilde_is_not_unary_operator = `~` cannot be used as a unary operator + .suggestion = use `!` to perform bitwise not + +parser_unexpected_token_after_not = unexpected {$negated_desc} after identifier + .suggestion = use `!` to perform logical negation + +parser_malformed_loop_label = malformed loop label + .suggestion = use the correct loop label format + +parser_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes + .suggestion = remove the lifetime annotation + .label = annotated with lifetime here + +parser_field_expression_with_generic = field expressions cannot have generic arguments + +parser_macro_invocation_with_qualified_path = macros cannot use qualified paths + +parser_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label + +parser_require_colon_after_labeled_expression = labeled expression must be followed by `:` + .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them + .label = the label + .suggestion = add `:` after the label + +parser_do_catch_syntax_removed = found removed `do catch` syntax + .note = following RFC #2388, the new non-placeholder syntax is `try` + .suggestion = replace with the new syntax + +parser_float_literal_requires_integer_part = float literals must have an integer part + .suggestion = must have an integer part + +parser_invalid_int_literal_width = invalid width `{$width}` for integer literal + .help = valid widths are 8, 16, 32, 64 and 128 + +parser_invalid_num_literal_base_prefix = invalid base prefix for number literal + .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + .suggestion = try making the prefix lowercase + +parser_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal + .label = invalid suffix `{$suffix}` + .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +parser_invalid_float_literal_width = invalid width `{$width}` for float literal + .help = valid widths are 32 and 64 + +parser_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal + .label = invalid suffix `{$suffix}` + .help = valid suffixes are `f32` and `f64` + +parser_int_literal_too_large = integer literal is too large + +parser_missing_semicolon_before_array = expected `;`, found `[` + .suggestion = consider adding `;` here + +parser_invalid_block_macro_segment = cannot use a `block` macro fragment here + .label = the `block` fragment is within this context + +parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition + .add_then_block = add a block here + .condition_possibly_unfinished = this binary operation is possibly unfinished + +parser_if_expression_missing_condition = missing condition for `if` expression + .condition_label = expected condition here + .block_label = if this block is the condition of the `if` expression, then it must be followed by another block + +parser_expected_expression_found_let = expected expression, found `let` statement + +parser_expected_else_block = expected `{"{"}`, found {$first_tok} + .label = expected an `if` or a block after this `else` + .suggestion = add an `if` if this is the condition of a chained `else if` statement + +parser_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches + .branch_label = the attributes are attached to this branch + .ctx_label = the branch belongs to this `{$ctx}` + .suggestion = remove the attributes + +parser_missing_in_in_for_loop = missing `in` in `for` loop + .use_in_not_of = try using `in` here instead + .add_in = try adding `in` here + +parser_missing_comma_after_match_arm = expected `,` following `match` arm + .suggestion = missing a comma here to end this `match` arm + +parser_catch_after_try = keyword `catch` cannot follow a `try` block + .help = try using `match` on the result of the `try` block instead + +parser_comma_after_base_struct = cannot use a comma after the base struct + .note = the base struct must always be the last field + .suggestion = remove this comma + +parser_eq_field_init = expected `:`, found `=` + .suggestion = replace equals symbol with a colon + +parser_dotdotdot = unexpected token: `...` + .suggest_exclusive_range = use `..` for an exclusive range + .suggest_inclusive_range = or `..=` for an inclusive range + +parser_left_arrow_operator = unexpected token: `<-` + .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-` diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 7beec270e3b..cdf9f1d7cb9 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -363,6 +363,349 @@ pub enum InvalidVariableDeclarationSub { UseLetNotVar(#[primary_span] Span), } +#[derive(SessionDiagnostic)] +#[diag(parser::invalid_comparison_operator)] +pub(crate) struct InvalidComparisonOperator { + #[primary_span] + pub span: Span, + pub invalid: String, + #[subdiagnostic] + pub sub: InvalidComparisonOperatorSub, +} + +#[derive(SessionSubdiagnostic)] +pub(crate) enum InvalidComparisonOperatorSub { + #[suggestion_short( + parser::use_instead, + applicability = "machine-applicable", + code = "{correct}" + )] + Correctable { + #[primary_span] + span: Span, + invalid: String, + correct: String, + }, + #[label(parser::spaceship_operator_invalid)] + Spaceship(#[primary_span] Span), +} + +#[derive(SessionDiagnostic)] +#[diag(parser::invalid_logical_operator)] +#[note] +pub(crate) struct InvalidLogicalOperator { + #[primary_span] + pub span: Span, + pub incorrect: String, + #[subdiagnostic] + pub sub: InvalidLogicalOperatorSub, +} + +#[derive(SessionSubdiagnostic)] +pub(crate) enum InvalidLogicalOperatorSub { + #[suggestion_short( + parser::use_amp_amp_for_conjunction, + applicability = "machine-applicable", + code = "&&" + )] + Conjunction(#[primary_span] Span), + #[suggestion_short( + parser::use_pipe_pipe_for_disjunction, + applicability = "machine-applicable", + code = "||" + )] + Disjunction(#[primary_span] Span), +} + +#[derive(SessionDiagnostic)] +#[diag(parser::tilde_is_not_unary_operator)] +pub(crate) struct TildeAsUnaryOperator( + #[primary_span] + #[suggestion_short(applicability = "machine-applicable", code = "!")] + pub Span, +); + +#[derive(SessionDiagnostic)] +#[diag(parser::unexpected_token_after_not)] +pub(crate) struct NotAsNegationOperator { + #[primary_span] + pub negated: Span, + pub negated_desc: String, + #[suggestion_short(applicability = "machine-applicable", code = "!")] + pub not: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::malformed_loop_label)] +pub(crate) struct MalformedLoopLabel { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "{correct_label}")] + pub span: Span, + pub correct_label: Ident, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::lifetime_in_borrow_expression)] +pub(crate) struct LifetimeInBorrowExpression { + #[primary_span] + pub span: Span, + #[suggestion(applicability = "machine-applicable", code = "")] + #[label] + pub lifetime_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::field_expression_with_generic)] +pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span); + +#[derive(SessionDiagnostic)] +#[diag(parser::macro_invocation_with_qualified_path)] +pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span); + +#[derive(SessionDiagnostic)] +#[diag(parser::unexpected_token_after_label)] +pub(crate) struct UnexpectedTokenAfterLabel( + #[primary_span] + #[label(parser::unexpected_token_after_label)] + pub Span, +); + +#[derive(SessionDiagnostic)] +#[diag(parser::require_colon_after_labeled_expression)] +#[note] +pub(crate) struct RequireColonAfterLabeledExpression { + #[primary_span] + pub span: Span, + #[label] + pub label: Span, + #[suggestion_short(applicability = "machine-applicable", code = ": ")] + pub label_end: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::do_catch_syntax_removed)] +#[note] +pub(crate) struct DoCatchSyntaxRemoved { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "try")] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::float_literal_requires_integer_part)] +pub(crate) struct FloatLiteralRequiresIntegerPart { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "{correct}")] + pub span: Span, + pub correct: String, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::invalid_int_literal_width)] +#[help] +pub(crate) struct InvalidIntLiteralWidth { + #[primary_span] + pub span: Span, + pub width: String, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::invalid_num_literal_base_prefix)] +#[note] +pub(crate) struct InvalidNumLiteralBasePrefix { + #[primary_span] + #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")] + pub span: Span, + pub fixed: String, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::invalid_num_literal_suffix)] +#[help] +pub(crate) struct InvalidNumLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + pub suffix: String, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::invalid_float_literal_width)] +#[help] +pub(crate) struct InvalidFloatLiteralWidth { + #[primary_span] + pub span: Span, + pub width: String, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::invalid_float_literal_suffix)] +#[help] +pub(crate) struct InvalidFloatLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + pub suffix: String, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::int_literal_too_large)] +pub(crate) struct IntLiteralTooLarge { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::missing_semicolon_before_array)] +pub(crate) struct MissingSemicolonBeforeArray { + #[primary_span] + pub open_delim: Span, + #[suggestion_verbose(applicability = "maybe-incorrect", code = ";")] + pub semicolon: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::invalid_block_macro_segment)] +pub(crate) struct InvalidBlockMacroSegment { + #[primary_span] + pub span: Span, + #[label] + pub context: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::if_expression_missing_then_block)] +pub(crate) struct IfExpressionMissingThenBlock { + #[primary_span] + pub if_span: Span, + #[subdiagnostic] + pub sub: IfExpressionMissingThenBlockSub, +} + +#[derive(SessionSubdiagnostic)] +pub(crate) enum IfExpressionMissingThenBlockSub { + #[help(parser::condition_possibly_unfinished)] + UnfinishedCondition(#[primary_span] Span), + #[help(parser::add_then_block)] + AddThenBlock(#[primary_span] Span), +} + +#[derive(SessionDiagnostic)] +#[diag(parser::if_expression_missing_condition)] +pub(crate) struct IfExpressionMissingCondition { + #[primary_span] + #[label(parser::condition_label)] + pub if_span: Span, + #[label(parser::block_label)] + pub block_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::expected_expression_found_let)] +pub(crate) struct ExpectedExpressionFoundLet { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::expected_else_block)] +pub(crate) struct ExpectedElseBlock { + #[primary_span] + pub first_tok_span: Span, + pub first_tok: String, + #[label] + pub else_span: Span, + #[suggestion(applicability = "maybe-incorrect", code = "if ")] + pub condition_start: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::outer_attribute_not_allowed_on_if_else)] +pub(crate) struct OuterAttributeNotAllowedOnIfElse { + #[primary_span] + pub last: Span, + + #[label(parser::branch_label)] + pub branch_span: Span, + + #[label(parser::ctx_label)] + pub ctx_span: Span, + pub ctx: String, + + #[suggestion(applicability = "machine-applicable", code = "")] + pub attributes: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::missing_in_in_for_loop)] +pub(crate) struct MissingInInForLoop { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: MissingInInForLoopSub, +} + +#[derive(SessionSubdiagnostic)] +pub(crate) enum MissingInInForLoopSub { + // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect + #[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")] + InNotOf(#[primary_span] Span), + #[suggestion_short(parser::add_in, applicability = "maybe-incorrect", code = " in ")] + AddIn(#[primary_span] Span), +} + +#[derive(SessionDiagnostic)] +#[diag(parser::missing_comma_after_match_arm)] +pub(crate) struct MissingCommaAfterMatchArm { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = ",")] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::catch_after_try)] +#[help] +pub(crate) struct CatchAfterTry { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::comma_after_base_struct)] +#[note] +pub(crate) struct CommaAfterBaseStruct { + #[primary_span] + pub span: Span, + #[suggestion_short(applicability = "machine-applicable", code = "")] + pub comma: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::eq_field_init)] +pub(crate) struct EqFieldInit { + #[primary_span] + pub span: Span, + #[suggestion(applicability = "machine-applicable", code = ":")] + pub eq: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::dotdotdot)] +pub(crate) struct DotDotDot { + #[primary_span] + #[suggestion(parser::suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")] + #[suggestion(parser::suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(parser::left_arrow_operator)] +pub(crate) struct LeftArrowOperator { + #[primary_span] + #[suggestion(applicability = "maybe-incorrect", code = "< -")] + pub span: Span, +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index df092f55bfa..8645f179b15 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,4 +1,14 @@ -use super::diagnostics::SnapshotParser; +use super::diagnostics::{ + CatchAfterTry, CommaAfterBaseStruct, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, + ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric, + FloatLiteralRequiresIntegerPart, IfExpressionMissingCondition, IfExpressionMissingThenBlock, + IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator, + InvalidComparisonOperatorSub, InvalidLogicalOperator, InvalidLogicalOperatorSub, + LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, + MalformedLoopLabel, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, + NotAsNegationOperator, OuterAttributeNotAllowedOnIfElse, RequireColonAfterLabeledExpression, + SnapshotParser, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, +}; use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{ @@ -6,6 +16,11 @@ use super::{ SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken, }; use crate::maybe_recover_from_interpolated_ty_qpath; +use crate::parser::diagnostics::{ + IntLiteralTooLarge, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, + InvalidIntLiteralWidth, InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, + MissingCommaAfterMatchArm, +}; use core::mem; use rustc_ast::ptr::P; @@ -20,9 +35,10 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::{ClosureBinder, StmtKind}; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult}; +use rustc_errors::{Applicability, Diagnostic, PResult}; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_session::SessionDiagnostic; use rustc_span::source_map::{self, Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Pos}; @@ -216,15 +232,18 @@ impl<'a> Parser<'a> { AssocOp::Equal => "==", AssocOp::NotEqual => "!=", _ => unreachable!(), - }; - self.struct_span_err(sp, &format!("invalid comparison operator `{sugg}=`")) - .span_suggestion_short( - sp, - &format!("`{s}=` is not a valid comparison operator, use `{s}`", s = sugg), - sugg, - Applicability::MachineApplicable, - ) - .emit(); + } + .into(); + let invalid = format!("{}=", &sugg); + self.sess.emit_err(InvalidComparisonOperator { + span: sp, + invalid: invalid.clone(), + sub: InvalidComparisonOperatorSub::Correctable { + span: sp, + invalid, + correct: sugg, + }, + }); self.bump(); } @@ -234,14 +253,15 @@ impl<'a> Parser<'a> { && self.prev_token.span.hi() == self.token.span.lo() { let sp = op.span.to(self.token.span); - self.struct_span_err(sp, "invalid comparison operator `<>`") - .span_suggestion_short( - sp, - "`<>` is not a valid comparison operator, use `!=`", - "!=", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(InvalidComparisonOperator { + span: sp, + invalid: "<>".into(), + sub: InvalidComparisonOperatorSub::Correctable { + span: sp, + invalid: "<>".into(), + correct: "!=".into(), + }, + }); self.bump(); } @@ -251,12 +271,11 @@ impl<'a> Parser<'a> { && self.prev_token.span.hi() == self.token.span.lo() { let sp = op.span.to(self.token.span); - self.struct_span_err(sp, "invalid comparison operator `<=>`") - .span_label( - sp, - "`<=>` is not a valid comparison operator, use `std::cmp::Ordering`", - ) - .emit(); + self.sess.emit_err(InvalidComparisonOperator { + span: sp, + invalid: "<=>".into(), + sub: InvalidComparisonOperatorSub::Spaceship(sp), + }); self.bump(); } @@ -430,11 +449,19 @@ impl<'a> Parser<'a> { } (Some(op), _) => (op, self.token.span), (None, Some((Ident { name: sym::and, span }, false))) => { - self.error_bad_logical_op("and", "&&", "conjunction"); + self.sess.emit_err(InvalidLogicalOperator { + span: self.token.span, + incorrect: "and".into(), + sub: InvalidLogicalOperatorSub::Conjunction(self.token.span), + }); (AssocOp::LAnd, span) } (None, Some((Ident { name: sym::or, span }, false))) => { - self.error_bad_logical_op("or", "||", "disjunction"); + self.sess.emit_err(InvalidLogicalOperator { + span: self.token.span, + incorrect: "or".into(), + sub: InvalidLogicalOperatorSub::Disjunction(self.token.span), + }); (AssocOp::LOr, span) } _ => return None, @@ -442,19 +469,6 @@ impl<'a> Parser<'a> { Some(source_map::respan(span, op)) } - /// Error on `and` and `or` suggesting `&&` and `||` respectively. - fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) { - self.struct_span_err(self.token.span, &format!("`{bad}` is not a logical operator")) - .span_suggestion_short( - self.token.span, - &format!("use `{good}` to perform logical {english}"), - good, - Applicability::MachineApplicable, - ) - .note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators") - .emit(); - } - /// Checks if this expression is a successfully parsed statement. fn expr_is_complete(&self, e: &Expr) -> bool { self.restrictions.contains(Restrictions::STMT_EXPR) @@ -619,14 +633,7 @@ impl<'a> Parser<'a> { // Recover on `!` suggesting for bitwise negation instead. fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - self.struct_span_err(lo, "`~` cannot be used as a unary operator") - .span_suggestion_short( - lo, - "use `!` to perform bitwise not", - "!", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(TildeAsUnaryOperator(lo)); self.parse_unary_expr(lo, UnOp::Not) } @@ -652,20 +659,14 @@ impl<'a> Parser<'a> { /// Recover on `not expr` in favor of `!expr`. fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { // Emit the error... - let not_token = self.look_ahead(1, |t| t.clone()); - self.struct_span_err( - not_token.span, - &format!("unexpected {} after identifier", super::token_descr(¬_token)), - ) - .span_suggestion_short( + let negated_token = self.look_ahead(1, |t| t.clone()); + self.sess.emit_err(NotAsNegationOperator { + negated: negated_token.span, + negated_desc: super::token_descr(&negated_token), // Span the `not` plus trailing whitespace to avoid // trailing whitespace after the `!` in our suggestion - self.sess.source_map().span_until_non_whitespace(lo.to(not_token.span)), - "use `!` to perform logical negation", - "!", - Applicability::MachineApplicable, - ) - .emit(); + not: self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)), + }); // ...and recover! self.parse_unary_expr(lo, UnOp::Not) @@ -725,14 +726,10 @@ impl<'a> Parser<'a> { match self.parse_labeled_expr(label, false) { Ok(expr) => { type_err.cancel(); - self.struct_span_err(label.ident.span, "malformed loop label") - .span_suggestion( - label.ident.span, - "use the correct loop label format", - label.ident, - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(MalformedLoopLabel { + span: label.ident.span, + correct_label: label.ident, + }); return Ok(expr); } Err(err) => { @@ -910,15 +907,7 @@ impl<'a> Parser<'a> { } fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) { - self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes") - .span_label(lt_span, "annotated with lifetime here") - .span_suggestion( - lt_span, - "remove the lifetime annotation", - "", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span }); } /// Parse `mut?` or `raw [ const | mut ]`. @@ -1272,11 +1261,7 @@ impl<'a> Parser<'a> { } else { // Field access `expr.f` if let Some(args) = segment.args { - self.struct_span_err( - args.span(), - "field expressions cannot have generic arguments", - ) - .emit(); + self.sess.emit_err(FieldExpressionWithGeneric(args.span())); } let span = lo.to(self.prev_token.span); @@ -1489,7 +1474,7 @@ impl<'a> Parser<'a> { let (span, kind) = if self.eat(&token::Not) { // MACRO INVOCATION expression if qself.is_some() { - self.struct_span_err(path.span, "macros cannot use qualified paths").emit(); + self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span)); } let lo = path.span; let mac = P(MacCall { @@ -1535,11 +1520,11 @@ impl<'a> Parser<'a> { && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt)) { // We're probably inside of a `Path<'a>` that needs a turbofish - let msg = "expected `while`, `for`, `loop` or `{` after a label"; - self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); + self.sess.emit_err(UnexpectedTokenAfterLabel(self.token.span)); consume_colon = false; Ok(self.mk_expr_err(lo)) } else { + // FIXME: use UnexpectedTokenAfterLabel, needs multipart suggestions let msg = "expected `while`, `for`, `loop` or `{` after a label"; let mut err = self.struct_span_err(self.token.span, msg); @@ -1604,25 +1589,16 @@ impl<'a> Parser<'a> { }?; if !ate_colon && consume_colon { - self.error_labeled_expr_must_be_followed_by_colon(lo, expr.span); + self.sess.emit_err(RequireColonAfterLabeledExpression { + span: expr.span, + label: lo, + label_end: lo.shrink_to_hi(), + }); } Ok(expr) } - fn error_labeled_expr_must_be_followed_by_colon(&self, lo: Span, span: Span) { - self.struct_span_err(span, "labeled expression must be followed by `:`") - .span_label(lo, "the label") - .span_suggestion_short( - lo.shrink_to_hi(), - "add `:` after the label", - ": ", - Applicability::MachineApplicable, - ) - .note("labels are used before loops and blocks, allowing e.g., `break 'label` to them") - .emit(); - } - /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. fn recover_do_catch(&mut self) -> PResult<'a, P> { let lo = self.token.span; @@ -1630,16 +1606,8 @@ impl<'a> Parser<'a> { self.bump(); // `do` self.bump(); // `catch` - let span_dc = lo.to(self.prev_token.span); - self.struct_span_err(span_dc, "found removed `do catch` syntax") - .span_suggestion( - span_dc, - "replace with the new syntax", - "try", - Applicability::MachineApplicable, - ) - .note("following RFC #2388, the new non-placeholder syntax is `try`") - .emit(); + let span = lo.to(self.prev_token.span); + self.sess.emit_err(DoCatchSyntaxRemoved { span }); self.parse_try_block(lo) } @@ -1834,14 +1802,10 @@ impl<'a> Parser<'a> { } fn error_float_lits_must_have_int_part(&self, token: &Token) { - self.struct_span_err(token.span, "float literals must have an integer part") - .span_suggestion( - token.span, - "must have an integer part", - pprust::token_to_string(token), - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(FloatLiteralRequiresIntegerPart { + span: token.span, + correct: pprust::token_to_string(token).into_owned(), + }); } fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) { @@ -1883,28 +1847,11 @@ impl<'a> Parser<'a> { let suf = suf.as_str(); if looks_like_width_suffix(&['i', 'u'], &suf) { // If it looks like a width, try to be helpful. - let msg = format!("invalid width `{}` for integer literal", &suf[1..]); - self.struct_span_err(span, &msg) - .help("valid widths are 8, 16, 32, 64 and 128") - .emit(); + self.sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }); } else if let Some(fixed) = fix_base_capitalisation(suf) { - let msg = "invalid base prefix for number literal"; - - self.struct_span_err(span, msg) - .note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase") - .span_suggestion( - span, - "try making the prefix lowercase", - fixed, - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed }); } else { - let msg = format!("invalid suffix `{suf}` for number literal"); - self.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{suf}`")) - .help("the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)") - .emit(); + self.sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }); } } LitError::InvalidFloatSuffix => { @@ -1912,14 +1859,10 @@ impl<'a> Parser<'a> { let suf = suf.as_str(); if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. - let msg = format!("invalid width `{}` for float literal", &suf[1..]); - self.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit(); + self.sess + .emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }); } else { - let msg = format!("invalid suffix `{suf}` for float literal"); - self.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{suf}`")) - .help("valid suffixes are `f32` and `f64`") - .emit(); + self.sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }); } } LitError::NonDecimalFloat(base) => { @@ -1934,7 +1877,7 @@ impl<'a> Parser<'a> { .emit(); } LitError::IntTooLarge => { - self.struct_span_err(span, "integer literal is too large").emit(); + self.sess.emit_err(IntLiteralTooLarge { span }); } } } @@ -2046,14 +1989,10 @@ impl<'a> Parser<'a> { .span_to_snippet(snapshot.token.span) .map_or(false, |snippet| snippet == "]") => { - let mut err = self.struct_span_err(open_delim_span, "expected `;`, found `[`"); - err.span_suggestion_verbose( - prev_span.shrink_to_hi(), - "consider adding `;` here", - ';', - Applicability::MaybeIncorrect, - ); - return Err(err); + return Err(MissingSemicolonBeforeArray { + open_delim: open_delim_span, + semicolon: prev_span.shrink_to_hi(), + }.into_diagnostic(self.sess)); } Ok(_) => (), Err(err) => err.cancel(), @@ -2080,9 +2019,10 @@ impl<'a> Parser<'a> { } if self.token.is_whole_block() { - self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here") - .span_label(lo.to(self.token.span), "the `block` fragment is within this context") - .emit(); + self.sess.emit_err(InvalidBlockMacroSegment { + span: self.token.span, + context: lo.to(self.token.span), + }); } let (attrs, blk) = self.parse_block_common(lo, blk_mode)?; @@ -2252,11 +2192,19 @@ impl<'a> Parser<'a> { let block = match &mut cond.kind { ExprKind::Binary(Spanned { span: binop_span, .. }, _, right) if let ExprKind::Block(_, None) = right.kind => { - this.error_missing_if_then_block(lo, cond_span.shrink_to_lo().to(*binop_span), true).emit(); + self.sess.emit_err(IfExpressionMissingThenBlock { + if_span: lo, + sub: IfExpressionMissingThenBlockSub::UnfinishedCondition( + cond_span.shrink_to_lo().to(*binop_span) + ), + }); std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi())) }, ExprKind::Block(_, None) => { - this.error_missing_if_cond(lo, cond_span).emit(); + self.sess.emit_err(IfExpressionMissingCondition { + if_span: self.sess.source_map().next_point(lo), + block_span: self.sess.source_map().start_point(cond_span), + }); std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi())) } _ => { @@ -2274,7 +2222,10 @@ impl<'a> Parser<'a> { if let Some(block) = recover_block_from_condition(self) { block } else { - self.error_missing_if_then_block(lo, cond_span, false).emit(); + self.sess.emit_err(IfExpressionMissingThenBlock { + if_span: lo, + sub: IfExpressionMissingThenBlockSub::AddThenBlock(cond_span.shrink_to_hi()), + }); self.mk_block_err(cond_span.shrink_to_hi()) } } else { @@ -2302,39 +2253,6 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els))) } - fn error_missing_if_then_block( - &self, - if_span: Span, - cond_span: Span, - is_unfinished: bool, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = self.struct_span_err( - if_span, - "this `if` expression is missing a block after the condition", - ); - if is_unfinished { - err.span_help(cond_span, "this binary operation is possibly unfinished"); - } else { - err.span_help(cond_span.shrink_to_hi(), "add a block here"); - } - err - } - - fn error_missing_if_cond( - &self, - lo: Span, - span: Span, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let next_span = self.sess.source_map().next_point(lo); - let mut err = self.struct_span_err(next_span, "missing condition for `if` expression"); - err.span_label(next_span, "expected condition here"); - err.span_label( - self.sess.source_map().start_point(span), - "if this block is the condition of the `if` expression, then it must be followed by another block" - ); - err - } - /// Parses the condition of a `if` or `while` expression. fn parse_cond_expr(&mut self) -> PResult<'a, P> { self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None) @@ -2350,8 +2268,7 @@ impl<'a> Parser<'a> { TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _) ); if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain { - self.struct_span_err(self.token.span, "expected expression, found `let` statement") - .emit(); + self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span }); } self.bump(); // Eat `let` token @@ -2389,15 +2306,12 @@ impl<'a> Parser<'a> { if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) && classify::expr_requires_semi_to_be_stmt(&cond) => { - self.struct_span_err(first_tok_span, format!("expected `{{`, found {first_tok}")) - .span_label(else_span, "expected an `if` or a block after this `else`") - .span_suggestion( - cond.span.shrink_to_lo(), - "add an `if` if this is the condition of a chained `else if` statement", - "if ", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(ExpectedElseBlock { + first_tok_span, + first_tok, + else_span, + condition_start: cond.span.shrink_to_lo(), + }); self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)? } Err(e) => { @@ -2422,16 +2336,18 @@ impl<'a> Parser<'a> { branch_span: Span, attrs: &[ast::Attribute], ) { - let (span, last) = match attrs { + let (attributes, last) = match attrs { [] => return, [x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span), }; let ctx = if is_ctx_else { "else" } else { "if" }; - self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches") - .span_label(branch_span, "the attributes are attached to this branch") - .span_label(ctx_span, format!("the branch belongs to this `{ctx}`")) - .span_suggestion(span, "remove the attributes", "", Applicability::MachineApplicable) - .emit(); + self.sess.emit_err(OuterAttributeNotAllowedOnIfElse { + last, + branch_span, + ctx_span, + ctx: ctx.to_string(), + attributes, + }); } /// Parses `for in ` (`for` token already eaten). @@ -2465,23 +2381,16 @@ impl<'a> Parser<'a> { } fn error_missing_in_for_loop(&mut self) { - let (span, msg, sugg) = if self.token.is_ident_named(sym::of) { + let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) { // Possibly using JS syntax (#75311). let span = self.token.span; self.bump(); - (span, "try using `in` here instead", "in") + (span, MissingInInForLoopSub::InNotOf) } else { - (self.prev_token.span.between(self.token.span), "try adding `in` here", " in ") + (self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn) }; - self.struct_span_err(span, "missing `in` in `for` loop") - .span_suggestion_short( - span, - msg, - sugg, - // Has been misleading, at least in the past (closed Issue #48492). - Applicability::MaybeIncorrect, - ) - .emit(); + + self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) }); } /// Parses a `while` or `while let` expression (`while` token already eaten). @@ -2787,17 +2696,9 @@ impl<'a> Parser<'a> { .is_ok(); if pattern_follows && snapshot.check(&TokenKind::FatArrow) { err.cancel(); - this.struct_span_err( - hi.shrink_to_hi(), - "expected `,` following `match` arm", - ) - .span_suggestion( - hi.shrink_to_hi(), - "missing a comma here to end this `match` arm", - ",", - Applicability::MachineApplicable, - ) - .emit(); + this.sess.emit_err(MissingCommaAfterMatchArm { + span: hi.shrink_to_hi(), + }); return Ok(true); } } @@ -2827,13 +2728,7 @@ impl<'a> Parser<'a> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P> { let (attrs, body) = self.parse_inner_attrs_and_block()?; if self.eat_keyword(kw::Catch) { - let mut error = self.struct_span_err( - self.prev_token.span, - "keyword `catch` cannot follow a `try` block", - ); - error.help("try using `match` on the result of the `try` block instead"); - error.emit(); - Err(error) + Err(CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.sess)) } else { let span = span_lo.to(body.span); self.sess.gated_spans.gate(sym::try_blocks, span); @@ -3082,18 +2977,10 @@ impl<'a> Parser<'a> { if self.token != token::Comma { return; } - self.struct_span_err( - span.to(self.prev_token.span), - "cannot use a comma after the base struct", - ) - .span_suggestion_short( - self.token.span, - "remove this comma", - "", - Applicability::MachineApplicable, - ) - .note("the base struct must always be the last field") - .emit(); + self.sess.emit_err(CommaAfterBaseStruct { + span: span.to(self.prev_token.span), + comma: self.token.span, + }); self.recover_stmt(); } @@ -3139,43 +3026,18 @@ impl<'a> Parser<'a> { return; } - self.struct_span_err(self.token.span, "expected `:`, found `=`") - .span_suggestion( - field_name.span.shrink_to_hi().to(self.token.span), - "replace equals symbol with a colon", - ":", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(EqFieldInit { + span: self.token.span, + eq: field_name.span.shrink_to_hi().to(self.token.span), + }); } fn err_dotdotdot_syntax(&self, span: Span) { - self.struct_span_err(span, "unexpected token: `...`") - .span_suggestion( - span, - "use `..` for an exclusive range", - "..", - Applicability::MaybeIncorrect, - ) - .span_suggestion( - span, - "or `..=` for an inclusive range", - "..=", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(DotDotDot { span }); } fn err_larrow_operator(&self, span: Span) { - self.struct_span_err(span, "unexpected token: `<-`") - .span_suggestion( - span, - "if you meant to write a comparison against a negative value, add a \ - space in between `<` and `-`", - "< -", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(LeftArrowOperator { span }); } fn mk_assign_op(&self, binop: BinOp, lhs: P, rhs: P) -> ExprKind { -- cgit 1.4.1-3-g733a5 From 619b8abaa65efd7fcc05453381e532ed8b716cf0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Aug 2022 12:34:33 +1000 Subject: Use `AttrVec` in more places. In some places we use `Vec` and some places we use `ThinVec` (a.k.a. `AttrVec`). This results in various points where we have to convert between `Vec` and `ThinVec`. This commit changes the places that use `Vec` to use `AttrVec`. A lot of this is mechanical and boring, but there are some interesting parts: - It adds a few new methods to `ThinVec`. - It implements `MapInPlace` for `ThinVec`, and introduces a macro to avoid the repetition of this trait for `Vec`, `SmallVec`, and `ThinVec`. Overall, it makes the code a little nicer, and has little effect on performance. But it is a precursor to removing `rustc_data_structures::thin_vec::ThinVec` and replacing it with `thin_vec::ThinVec`, which is implemented more efficiently. --- compiler/rustc_ast/src/ast.rs | 12 +- compiler/rustc_ast/src/ast_traits.rs | 47 ++------ compiler/rustc_ast/src/attr/mod.rs | 3 +- compiler/rustc_ast/src/mut_visit.rs | 34 ++---- compiler/rustc_ast_lowering/src/expr.rs | 50 ++++---- compiler/rustc_builtin_macros/src/asm.rs | 2 +- .../rustc_builtin_macros/src/assert/context.rs | 3 +- .../rustc_builtin_macros/src/deriving/clone.rs | 2 +- .../rustc_builtin_macros/src/deriving/cmp/eq.rs | 2 +- .../rustc_builtin_macros/src/deriving/cmp/ord.rs | 2 +- .../src/deriving/cmp/partial_eq.rs | 2 +- .../src/deriving/cmp/partial_ord.rs | 2 +- .../rustc_builtin_macros/src/deriving/debug.rs | 2 +- .../rustc_builtin_macros/src/deriving/decodable.rs | 2 +- .../rustc_builtin_macros/src/deriving/default.rs | 6 +- .../rustc_builtin_macros/src/deriving/encodable.rs | 4 +- .../src/deriving/generic/mod.rs | 6 +- compiler/rustc_builtin_macros/src/deriving/hash.rs | 4 +- compiler/rustc_builtin_macros/src/deriving/mod.rs | 2 +- .../rustc_builtin_macros/src/global_allocator.rs | 6 +- .../rustc_builtin_macros/src/proc_macro_harness.rs | 2 +- .../src/standard_library_imports.rs | 4 +- compiler/rustc_builtin_macros/src/test.rs | 5 +- compiler/rustc_builtin_macros/src/test_harness.rs | 8 +- compiler/rustc_data_structures/src/map_in_place.rs | 127 ++++++++----------- compiler/rustc_data_structures/src/thin_vec.rs | 45 +++++++ compiler/rustc_driver/src/lib.rs | 2 +- compiler/rustc_expand/src/base.rs | 4 +- compiler/rustc_expand/src/build.rs | 6 +- compiler/rustc_expand/src/config.rs | 8 +- compiler/rustc_expand/src/expand.rs | 16 ++- compiler/rustc_expand/src/module.rs | 8 +- compiler/rustc_expand/src/placeholders.rs | 2 +- compiler/rustc_parse/src/lib.rs | 4 +- compiler/rustc_parse/src/parser/attr.rs | 8 +- compiler/rustc_parse/src/parser/attr_wrapper.rs | 17 +-- compiler/rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 24 ++-- compiler/rustc_parse/src/parser/generics.rs | 14 +-- compiler/rustc_parse/src/parser/item.rs | 57 ++++----- compiler/rustc_parse/src/parser/pat.rs | 8 +- compiler/rustc_parse/src/parser/stmt.rs | 16 ++- src/librustdoc/clean/types.rs | 4 +- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 5 +- src/test/ui/stats/hir-stats.stderr | 134 ++++++++++----------- src/tools/rustfmt/src/attr.rs | 5 +- src/tools/rustfmt/src/imports.rs | 4 +- src/tools/rustfmt/src/modules.rs | 8 +- src/tools/rustfmt/src/parse/parser.rs | 2 +- 49 files changed, 351 insertions(+), 391 deletions(-) (limited to 'compiler/rustc_parse/src/parser/expr.rs') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index d5180b46aaf..598bf771008 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -504,7 +504,7 @@ pub struct WhereEqPredicate { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Crate { - pub attrs: Vec, + pub attrs: AttrVec, pub items: Vec>, pub spans: ModSpans, /// Must be equal to `CRATE_NODE_ID` after the crate root is expanded, but may hold @@ -1268,7 +1268,7 @@ impl Expr { id: DUMMY_NODE_ID, kind: ExprKind::Err, span: DUMMY_SP, - attrs: ThinVec::new(), + attrs: AttrVec::new(), tokens: None, }, ) @@ -2669,7 +2669,7 @@ impl VariantData { /// An item definition. #[derive(Clone, Encodable, Decodable, Debug)] pub struct Item { - pub attrs: Vec, + pub attrs: AttrVec, pub id: NodeId, pub span: Span, pub vis: Visibility, @@ -3036,19 +3036,19 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. - static_assert_size!(AssocItem, 120); + static_assert_size!(AssocItem, 104); static_assert_size!(AssocItemKind, 32); static_assert_size!(Attribute, 32); static_assert_size!(Block, 48); static_assert_size!(Expr, 104); static_assert_size!(ExprKind, 72); static_assert_size!(Fn, 192); - static_assert_size!(ForeignItem, 112); + static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 72); static_assert_size!(Impl, 200); - static_assert_size!(Item, 200); + static_assert_size!(Item, 184); static_assert_size!(ItemKind, 112); static_assert_size!(Lit, 48); static_assert_size!(LitKind, 24); diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 1fc5e480215..0947a71b824 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -270,7 +270,7 @@ pub trait HasAttrs { /// during token collection. const SUPPORTS_CUSTOM_INNER_ATTRS: bool; fn attrs(&self) -> &[Attribute]; - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)); + fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)); } macro_rules! impl_has_attrs { @@ -283,8 +283,8 @@ macro_rules! impl_has_attrs { &self.attrs } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { - VecOrAttrVec::visit(&mut self.attrs, f) + fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { + f(&mut self.attrs) } } )+ @@ -299,7 +299,7 @@ macro_rules! impl_has_attrs_none { fn attrs(&self) -> &[Attribute] { &[] } - fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec)) {} + fn visit_attrs(&mut self, _f: impl FnOnce(&mut AttrVec)) {} } )+ }; @@ -330,7 +330,7 @@ impl> HasAttrs for T { fn attrs(&self) -> &[Attribute] { self.ast_deref().attrs() } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { self.ast_deref_mut().visit_attrs(f) } } @@ -340,7 +340,7 @@ impl HasAttrs for Option { fn attrs(&self) -> &[Attribute] { self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[]) } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { if let Some(inner) = self.as_mut() { inner.visit_attrs(f); } @@ -362,13 +362,13 @@ impl HasAttrs for StmtKind { } } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { match self { - StmtKind::Local(local) => visit_attrvec(&mut local.attrs, f), + StmtKind::Local(local) => f(&mut local.attrs), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), StmtKind::Item(item) => item.visit_attrs(f), StmtKind::Empty => {} - StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f), + StmtKind::MacCall(mac) => f(&mut mac.attrs), } } } @@ -378,38 +378,11 @@ impl HasAttrs for Stmt { fn attrs(&self) -> &[Attribute] { self.kind.attrs() } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { self.kind.visit_attrs(f); } } -/// Helper trait for the impls above. Abstracts over -/// the two types of attribute fields that AST nodes -/// may have (`Vec` or `AttrVec`). -trait VecOrAttrVec { - fn visit(&mut self, f: impl FnOnce(&mut Vec)); -} - -impl VecOrAttrVec for Vec { - fn visit(&mut self, f: impl FnOnce(&mut Vec)) { - f(self) - } -} - -impl VecOrAttrVec for AttrVec { - fn visit(&mut self, f: impl FnOnce(&mut Vec)) { - visit_attrvec(self, f) - } -} - -fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec)) { - crate::mut_visit::visit_clobber(attrs, |attrs| { - let mut vec = attrs.into(); - f(&mut vec); - vec.into() - }); -} - /// A newtype around an AST node that implements the traits above if the node implements them. pub struct AstNodeWrapper { pub wrapped: Wrapped, diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 0d114f1366c..5b72ec2b601 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -12,7 +12,6 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree}; use crate::tokenstream::{LazyTokenStream, TokenStream}; use crate::util::comments; -use rustc_data_structures::thin_vec::ThinVec; use rustc_index::bit_set::GrowableBitSet; use rustc_span::source_map::BytePos; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -487,7 +486,7 @@ impl MetaItemKind { id: ast::DUMMY_NODE_ID, kind: ast::ExprKind::Lit(lit.clone()), span: lit.span, - attrs: ThinVec::new(), + attrs: ast::AttrVec::new(), tokens: None, }); MacArgs::Eq(span, MacArgsEq::Ast(expr)) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 0520319e3be..458d1156ec2 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -14,7 +14,6 @@ use crate::tokenstream::*; use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::thin_vec::ThinVec; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -338,12 +337,7 @@ where } // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_attrs(attrs: &mut Vec, vis: &mut T) { - visit_vec(attrs, |attr| vis.visit_attribute(attr)); -} - -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_thin_attrs(attrs: &mut AttrVec, vis: &mut T) { +pub fn visit_attrs(attrs: &mut AttrVec, vis: &mut T) { for attr in attrs.iter_mut() { vis.visit_attribute(attr); } @@ -398,7 +392,7 @@ pub fn noop_flat_map_pat_field( vis.visit_ident(ident); vis.visit_pat(pat); vis.visit_span(span); - visit_thin_attrs(attrs, vis); + visit_attrs(attrs, vis); smallvec![fp] } @@ -424,7 +418,7 @@ pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { pub fn noop_flat_map_arm(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> { let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm; - visit_thin_attrs(attrs, vis); + visit_attrs(attrs, vis); vis.visit_id(id); vis.visit_pat(pat); visit_opt(guard, |guard| vis.visit_expr(guard)); @@ -507,7 +501,7 @@ pub fn noop_flat_map_variant( let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; visitor.visit_ident(ident); visitor.visit_vis(vis); - visit_thin_attrs(attrs, visitor); + visit_attrs(attrs, visitor); visitor.visit_id(id); visitor.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr)); @@ -589,7 +583,7 @@ pub fn noop_visit_local(local: &mut P, vis: &mut T) { } } vis.visit_span(span); - visit_thin_attrs(attrs, vis); + visit_attrs(attrs, vis); visit_lazy_tts(tokens, vis); } @@ -640,7 +634,7 @@ pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { pub fn noop_flat_map_param(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> { let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param; vis.visit_id(id); - visit_thin_attrs(attrs, vis); + visit_attrs(attrs, vis); vis.visit_pat(pat); vis.visit_span(span); vis.visit_ty(ty); @@ -882,7 +876,7 @@ pub fn noop_flat_map_generic_param( if let Some(ref mut colon_span) = colon_span { vis.visit_span(colon_span); } - visit_thin_attrs(attrs, vis); + visit_attrs(attrs, vis); visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); match kind { GenericParamKind::Lifetime => {} @@ -978,7 +972,7 @@ pub fn noop_flat_map_field_def( visitor.visit_vis(vis); visitor.visit_id(id); visitor.visit_ty(ty); - visit_thin_attrs(attrs, visitor); + visit_attrs(attrs, visitor); smallvec![fd] } @@ -991,7 +985,7 @@ pub fn noop_flat_map_expr_field( vis.visit_expr(expr); vis.visit_id(id); vis.visit_span(span); - visit_thin_attrs(attrs, vis); + visit_attrs(attrs, vis); smallvec![f] } @@ -1432,7 +1426,7 @@ pub fn noop_visit_expr( } vis.visit_id(id); vis.visit_span(span); - visit_thin_attrs(attrs, vis); + visit_attrs(attrs, vis); visit_lazy_tts(tokens, vis); } @@ -1478,7 +1472,7 @@ pub fn noop_flat_map_stmt_kind( StmtKind::MacCall(mut mac) => { let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut(); vis.visit_mac_call(mac_); - visit_thin_attrs(attrs, vis); + visit_attrs(attrs, vis); visit_lazy_tts(tokens, vis); smallvec![StmtKind::MacCall(mac)] } @@ -1513,12 +1507,6 @@ impl DummyAstNode for P { } } -impl DummyAstNode for ThinVec { - fn dummy() -> Self { - Default::default() - } -} - impl DummyAstNode for Item { fn dummy() -> Self { Item { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 32dbd2ff47d..bd61f4fa87a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -6,7 +6,6 @@ use rustc_ast::attr; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; @@ -448,12 +447,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond)); let new_cond = self.manage_let_cond(lowered_cond); let then = self.lower_block_expr(body); - let expr_break = self.expr_break(span, ThinVec::new()); + let expr_break = self.expr_break(span, AttrVec::new()); let stmt_break = self.stmt_expr(span, expr_break); let else_blk = self.block_all(span, arena_vec![self; stmt_break], None); - let else_expr = self.arena.alloc(self.expr_block(else_blk, ThinVec::new())); + let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new())); let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr)); - let if_expr = self.expr(span, if_kind, ThinVec::new()); + let if_expr = self.expr(span, if_kind, AttrVec::new()); let block = self.block_expr(self.arena.alloc(if_expr)); let span = self.lower_span(span.with_hi(cond.span.hi())); let opt_label = self.lower_label(opt_label); @@ -512,7 +511,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let constructor = self.arena.alloc(self.expr_lang_item_path( method_span, lang_item, - ThinVec::new(), + AttrVec::new(), None, )); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) @@ -635,7 +634,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let gen_future = self.expr_lang_item_path( unstable_span, hir::LangItem::FromGenerator, - ThinVec::new(), + AttrVec::new(), None, ); @@ -747,7 +746,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); - this.arena.alloc(this.expr(gen_future_span, expr_break, ThinVec::new())) + this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new())) }); self.arm(ready_pat, break_x) }; @@ -780,7 +779,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let yield_expr = self.expr( span, hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), - ThinVec::new(), + AttrVec::new(), ); let yield_expr = self.arena.alloc(yield_expr); @@ -987,7 +986,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AsyncGeneratorKind::Closure, |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), ); - this.expr(fn_decl_span, async_body, ThinVec::new()) + this.expr(fn_decl_span, async_body, AttrVec::new()) }); body_id }); @@ -1257,7 +1256,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.expr_ident(lhs.span, ident, binding); let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span)); - let expr = self.expr(lhs.span, assign, ThinVec::new()); + let expr = self.expr(lhs.span, assign, AttrVec::new()); assignments.push(self.stmt_expr(lhs.span, expr)); pat } @@ -1299,7 +1298,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); let fn_expr = - self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); + self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new())); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) } @@ -1472,7 +1471,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `None => break` let none_arm = { let break_expr = - self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, ThinVec::new())); + self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new())); let pat = self.pat_none(for_span); self.arm(pat, break_expr) }; @@ -1481,7 +1480,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let some_arm = { let some_pat = self.pat_some(pat_span, pat); let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); - let body_expr = self.arena.alloc(self.expr_block(body_block, ThinVec::new())); + let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new())); self.arm(some_pat, body_expr) }; @@ -1596,7 +1595,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; attr::mk_attr_outer(allow) }; - let attrs = vec![attr]; + let attrs: AttrVec = vec![attr].into(); // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,` let continue_arm = { @@ -1606,7 +1605,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, val_ident, val_pat_nid, - ThinVec::from(attrs.clone()), + attrs.clone(), )); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); self.arm(continue_pat, val_expr) @@ -1625,7 +1624,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(residual_expr), unstable_span, ); - let thin_attrs = ThinVec::from(attrs); let ret_expr = if let Some(catch_node) = self.catch_scope { let target_id = Ok(self.lower_node_id(catch_node)); self.arena.alloc(self.expr( @@ -1634,13 +1632,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Destination { label: None, target_id }, Some(from_residual_expr), ), - thin_attrs, + attrs, )) } else { self.arena.alloc(self.expr( try_span, hir::ExprKind::Ret(Some(from_residual_expr)), - thin_attrs, + attrs, )) }; @@ -1728,7 +1726,7 @@ impl<'hir> LoweringContext<'_, 'hir> { arms: &'hir [hir::Arm<'hir>], source: hir::MatchSource, ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new()) + self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new()) } fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> { @@ -1745,12 +1743,12 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr( span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e), - ThinVec::new(), + AttrVec::new(), ) } fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), ThinVec::new())) + self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new())) } fn expr_call_mut( @@ -1759,7 +1757,7 @@ impl<'hir> LoweringContext<'_, 'hir> { e: &'hir hir::Expr<'hir>, args: &'hir [hir::Expr<'hir>], ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new()) + self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new()) } fn expr_call( @@ -1779,7 +1777,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: Option, ) -> hir::Expr<'hir> { let path = - self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id)); + self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id)); self.expr_call_mut(span, path, args) } @@ -1822,7 +1820,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ident: Ident, binding: hir::HirId, ) -> hir::Expr<'hir> { - self.expr_ident_with_attrs(sp, ident, binding, ThinVec::new()) + self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new()) } fn expr_ident_with_attrs( @@ -1860,13 +1858,13 @@ impl<'hir> LoweringContext<'_, 'hir> { }), None, ), - ThinVec::new(), + AttrVec::new(), ) } fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> { let blk = self.block_all(span, &[], None); - let expr = self.expr_block(blk, ThinVec::new()); + let expr = self.expr_block(blk, AttrVec::new()); self.arena.alloc(expr) } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 1a0ea8f4160..a1051d990b1 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -852,7 +852,7 @@ pub(super) fn expand_global_asm<'cx>( if let Some(inline_asm) = expand_preparsed_asm(ecx, args) { MacEager::items(smallvec![P(ast::Item { ident: Ident::empty(), - attrs: Vec::new(), + attrs: ast::AttrVec::new(), id: ast::DUMMY_NODE_ID, kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), vis: ast::Visibility { diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index d30fd479015..d2ee4249989 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -119,7 +119,8 @@ impl<'cx, 'a> Context<'cx, 'a> { vec![self.cx.attribute(attr::mk_list_item( Ident::new(sym::allow, self.span), vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))], - ))], + ))] + .into(), ItemKind::Use(UseTree { prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])), kind: UseTreeKind::Nested(vec![ diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index ee4c5aea1a3..dd7989cf48c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -68,7 +68,7 @@ pub fn expand_deriving_clone( } let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(inline)]; + let attrs = vec![cx.attribute(inline)].into(); let trait_def = TraitDef { span, path: path_std!(clone::Clone), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index f99ee8cb2d5..9b6d3e5032f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -20,7 +20,7 @@ pub fn expand_deriving_eq( let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span)); let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]); let no_coverage = cx.meta_word(span, sym::no_coverage); - let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)]; + let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)].into(); let trait_def = TraitDef { span, path: path_std!(cmp::Eq), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 8aa16dfeb0f..0e17b951787 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -15,7 +15,7 @@ pub fn expand_deriving_ord( push: &mut dyn FnMut(Annotatable), ) { let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(inline)]; + let attrs = vec![cx.attribute(inline)].into(); let trait_def = TraitDef { span, path: path_std!(cmp::Ord), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 6f86092ba49..ac1325b92a6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -68,7 +68,7 @@ pub fn expand_deriving_partial_eq( // No need to generate `ne`, the default suffices, and not generating it is // faster. let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(inline)]; + let attrs = vec![cx.attribute(inline)].into(); let methods = vec![MethodDef { name: sym::eq, generics: Bounds::empty(), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 137c779f81b..7763e554017 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -19,7 +19,7 @@ pub fn expand_deriving_partial_ord( Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std)); let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(inline)]; + let attrs = vec![cx.attribute(inline)].into(); let partial_cmp_def = MethodDef { name: sym::partial_cmp, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index f82175af4f6..4af7fd81653 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -29,7 +29,7 @@ pub fn expand_deriving_debug( explicit_self: true, nonself_args: vec![(fmtr, sym::f)], ret_ty: Path(path_std!(fmt::Result)), - attributes: Vec::new(), + attributes: ast::AttrVec::new(), unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { show_substructure(a, b, c) diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 47da0862b52..7174dbbe7ea 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -47,7 +47,7 @@ pub fn expand_deriving_rustc_decodable( ], PathKind::Std, )), - attributes: Vec::new(), + attributes: ast::AttrVec::new(), unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { decodable_substructure(a, b, c, krate) diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index a431832080c..f316f01ef66 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -2,9 +2,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use rustc_ast as ast; -use rustc_ast::walk_list; -use rustc_ast::EnumDef; -use rustc_ast::VariantData; +use rustc_ast::{walk_list, EnumDef, VariantData}; use rustc_errors::Applicability; use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; use rustc_span::symbol::Ident; @@ -22,7 +20,7 @@ pub fn expand_deriving_default( item.visit_with(&mut DetectNonVariantDefaultAttr { cx }); let inline = cx.meta_word(span, sym::inline); - let attrs = vec![cx.attribute(inline)]; + let attrs = vec![cx.attribute(inline)].into(); let trait_def = TraitDef { span, path: Path::new(vec![kw::Default, sym::Default]), diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index d43c66a5fa6..b220e54238f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -89,7 +89,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::pathvec_std; -use rustc_ast::{ExprKind, MetaItem, Mutability}; +use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; @@ -131,7 +131,7 @@ pub fn expand_deriving_rustc_encodable( ], PathKind::Std, )), - attributes: Vec::new(), + attributes: AttrVec::new(), unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { encodable_substructure(a, b, c, krate) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index a39b97d07ef..c1bbc601560 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -217,7 +217,7 @@ pub struct MethodDef<'a> { /// Returns type pub ret_ty: Ty, - pub attributes: Vec, + pub attributes: ast::AttrVec, /// Can we combine fieldless variants for enums into a single match arm? /// If true, indicates that the trait operation uses the enum tag in some @@ -562,7 +562,7 @@ impl<'a> TraitDef<'a> { kind: ast::VisibilityKind::Inherited, tokens: None, }, - attrs: Vec::new(), + attrs: ast::AttrVec::new(), kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias { defaultness: ast::Defaultness::Final, generics: Generics::default(), @@ -716,7 +716,7 @@ impl<'a> TraitDef<'a> { let self_type = cx.ty_path(path); let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived)); - let attrs = vec![attr]; + let attrs = vec![attr].into(); let opt_trait_ref = Some(trait_ref); cx.item( diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 9aa170bec14..f1f02e7ce77 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -2,7 +2,7 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::{path_std, pathvec_std}; -use rustc_ast::{MetaItem, Mutability}; +use rustc_ast::{AttrVec, MetaItem, Mutability}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -31,7 +31,7 @@ pub fn expand_deriving_hash( explicit_self: true, nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], ret_ty: Unit, - attributes: vec![], + attributes: AttrVec::new(), unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { hash_substructure(a, b, c) diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index c1ca089da22..a65d0bad6de 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -164,7 +164,7 @@ fn inject_impl_of_structural_trait( // Keep the lint and stability attributes of the original item, to control // how the generated implementation is linted. - let mut attrs = Vec::new(); + let mut attrs = ast::AttrVec::new(); attrs.extend( item.attrs .iter() diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 36cfbba45da..2bad9bbce66 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -4,7 +4,7 @@ use rustc_ast::expand::allocator::{ AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS, }; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind}; +use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind}; use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -113,10 +113,10 @@ impl AllocFnFactory<'_, '_> { self.cx.expr_call(self.ty_span, method, args) } - fn attrs(&self) -> Vec { + fn attrs(&self) -> AttrVec { let special = sym::rustc_std_internal_symbol; let special = self.cx.meta_word(self.span, special); - vec![self.cx.attribute(special)] + vec![self.cx.attribute(special)].into() } fn arg_ty( diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 5cfda33491d..ebe1c3663e3 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -281,7 +281,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); let proc_macro = Ident::new(sym::proc_macro, span); - let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None)); + let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); let bridge = Ident::new(sym::bridge, span); let client = Ident::new(sym::client, span); diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 09ad5f9b3ea..90ea1e457ba 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -51,7 +51,7 @@ pub fn inject( cx.item( span, ident, - vec![cx.attribute(cx.meta_word(span, sym::macro_use))], + vec![cx.attribute(cx.meta_word(span, sym::macro_use))].into(), ast::ItemKind::ExternCrate(None), ), ); @@ -78,7 +78,7 @@ pub fn inject( let use_item = cx.item( span, Ident::empty(), - vec![cx.attribute(cx.meta_word(span, sym::prelude_import))], + vec![cx.attribute(cx.meta_word(span, sym::prelude_import))].into(), ast::ItemKind::Use(ast::UseTree { prefix: cx.path(span, import_path), kind: ast::UseTreeKind::Glob, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index e20375689f3..03c84f5ec2a 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -227,7 +227,8 @@ pub fn expand_test_or_bench( )), // #[rustc_test_marker] cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)), - ], + ] + .into(), // const $ident: test::TestDescAndFn = ast::ItemKind::Const( ast::Defaultness::Final, @@ -334,7 +335,7 @@ pub fn expand_test_or_bench( }); // extern crate test - let test_extern = cx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None)); + let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 0ebe29df95f..093f0f10a38 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -298,8 +298,10 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let call_test_main = ecx.stmt_expr(call_test_main); // extern crate test - let test_extern_stmt = - ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None))); + let test_extern_stmt = ecx.stmt_item( + sp, + ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)), + ); // #[rustc_main] let main_meta = ecx.meta_word(sp, sym::rustc_main); @@ -333,7 +335,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let main = P(ast::Item { ident: main_id, - attrs: vec![main_attr], + attrs: vec![main_attr].into(), id: ast::DUMMY_NODE_ID, kind: main, vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None }, diff --git a/compiler/rustc_data_structures/src/map_in_place.rs b/compiler/rustc_data_structures/src/map_in_place.rs index 874de03d37a..d912211443a 100644 --- a/compiler/rustc_data_structures/src/map_in_place.rs +++ b/compiler/rustc_data_structures/src/map_in_place.rs @@ -1,3 +1,4 @@ +use crate::thin_vec::ThinVec; use smallvec::{Array, SmallVec}; use std::ptr; @@ -15,94 +16,64 @@ pub trait MapInPlace: Sized { I: IntoIterator; } -impl MapInPlace for Vec { - fn flat_map_in_place(&mut self, mut f: F) - where - F: FnMut(T) -> I, - I: IntoIterator, - { - let mut read_i = 0; - let mut write_i = 0; - unsafe { - let mut old_len = self.len(); - self.set_len(0); // make sure we just leak elements in case of panic +// The implementation of this method is syntactically identical for all the +// different vector types. +macro_rules! flat_map_in_place { + () => { + fn flat_map_in_place(&mut self, mut f: F) + where + F: FnMut(T) -> I, + I: IntoIterator, + { + let mut read_i = 0; + let mut write_i = 0; + unsafe { + let mut old_len = self.len(); + self.set_len(0); // make sure we just leak elements in case of panic - while read_i < old_len { - // move the read_i'th item out of the vector and map it - // to an iterator - let e = ptr::read(self.as_ptr().add(read_i)); - let iter = f(e).into_iter(); - read_i += 1; + while read_i < old_len { + // move the read_i'th item out of the vector and map it + // to an iterator + let e = ptr::read(self.as_ptr().add(read_i)); + let iter = f(e).into_iter(); + read_i += 1; - for e in iter { - if write_i < read_i { - ptr::write(self.as_mut_ptr().add(write_i), e); - write_i += 1; - } else { - // If this is reached we ran out of space - // in the middle of the vector. - // However, the vector is in a valid state here, - // so we just do a somewhat inefficient insert. - self.set_len(old_len); - self.insert(write_i, e); + for e in iter { + if write_i < read_i { + ptr::write(self.as_mut_ptr().add(write_i), e); + write_i += 1; + } else { + // If this is reached we ran out of space + // in the middle of the vector. + // However, the vector is in a valid state here, + // so we just do a somewhat inefficient insert. + self.set_len(old_len); + self.insert(write_i, e); - old_len = self.len(); - self.set_len(0); + old_len = self.len(); + self.set_len(0); - read_i += 1; - write_i += 1; + read_i += 1; + write_i += 1; + } } } - } - // write_i tracks the number of actually written new items. - self.set_len(write_i); + // write_i tracks the number of actually written new items. + self.set_len(write_i); + } } - } + }; } -impl> MapInPlace for SmallVec { - fn flat_map_in_place(&mut self, mut f: F) - where - F: FnMut(T) -> I, - I: IntoIterator, - { - let mut read_i = 0; - let mut write_i = 0; - unsafe { - let mut old_len = self.len(); - self.set_len(0); // make sure we just leak elements in case of panic - - while read_i < old_len { - // move the read_i'th item out of the vector and map it - // to an iterator - let e = ptr::read(self.as_ptr().add(read_i)); - let iter = f(e).into_iter(); - read_i += 1; - - for e in iter { - if write_i < read_i { - ptr::write(self.as_mut_ptr().add(write_i), e); - write_i += 1; - } else { - // If this is reached we ran out of space - // in the middle of the vector. - // However, the vector is in a valid state here, - // so we just do a somewhat inefficient insert. - self.set_len(old_len); - self.insert(write_i, e); - - old_len = self.len(); - self.set_len(0); +impl MapInPlace for Vec { + flat_map_in_place!(); +} - read_i += 1; - write_i += 1; - } - } - } +impl> MapInPlace for SmallVec { + flat_map_in_place!(); +} - // write_i tracks the number of actually written new items. - self.set_len(write_i); - } - } +impl MapInPlace for ThinVec { + flat_map_in_place!(); } diff --git a/compiler/rustc_data_structures/src/thin_vec.rs b/compiler/rustc_data_structures/src/thin_vec.rs index 716259142d1..fce42e709ab 100644 --- a/compiler/rustc_data_structures/src/thin_vec.rs +++ b/compiler/rustc_data_structures/src/thin_vec.rs @@ -27,6 +27,51 @@ impl ThinVec { ThinVec(None) => *self = vec![item].into(), } } + + /// Note: if `set_len(0)` is called on a non-empty `ThinVec`, it will + /// remain in the `Some` form. This is required for some code sequences + /// (such as the one in `flat_map_in_place`) that call `set_len(0)` before + /// an operation that might panic, and then call `set_len(n)` again + /// afterwards. + pub unsafe fn set_len(&mut self, new_len: usize) { + match *self { + ThinVec(None) => { + // A prerequisite of `Vec::set_len` is that `new_len` must be + // less than or equal to capacity(). The same applies here. + if new_len != 0 { + panic!("unsafe ThinVec::set_len({})", new_len); + } + } + ThinVec(Some(ref mut vec)) => vec.set_len(new_len), + } + } + + pub fn insert(&mut self, index: usize, value: T) { + match *self { + ThinVec(None) => { + if index == 0 { + *self = vec![value].into(); + } else { + panic!("invalid ThinVec::insert"); + } + } + ThinVec(Some(ref mut vec)) => vec.insert(index, value), + } + } + + pub fn remove(&mut self, index: usize) -> T { + match self { + ThinVec(None) => panic!("invalid ThinVec::remove"), + ThinVec(Some(vec)) => vec.remove(index), + } + } + + pub fn as_slice(&self) -> &[T] { + match self { + ThinVec(None) => &[], + ThinVec(Some(vec)) => vec.as_slice(), + } + } } impl From> for ThinVec { diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 94639bf8e1e..dac8df7dc55 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1070,7 +1070,7 @@ pub fn handle_options(args: &[String]) -> Option { Some(matches) } -fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec> { +fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::AttrVec> { match input { Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess), Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str( diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 852ea806b20..df56e032988 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -6,7 +6,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Nonterminal}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{AssocCtxt, Visitor}; -use rustc_ast::{self as ast, Attribute, HasAttrs, Item, NodeId, PatKind}; +use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind}; use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::sync::{self, Lrc}; @@ -71,7 +71,7 @@ impl Annotatable { } } - pub fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + pub fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { match self { Annotatable::Item(item) => item.visit_attrs(f), Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f), diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 0440bca53b2..c4890b4a9c4 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -575,7 +575,7 @@ impl<'a> ExtCtxt<'a> { &self, span: Span, name: Ident, - attrs: Vec, + attrs: ast::AttrVec, kind: ast::ItemKind, ) -> P { // FIXME: Would be nice if our generated code didn't violate @@ -603,7 +603,7 @@ impl<'a> ExtCtxt<'a> { mutbl: ast::Mutability, expr: P, ) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr))) + self.item(span, name, AttrVec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr))) } pub fn item_const( @@ -614,7 +614,7 @@ impl<'a> ExtCtxt<'a> { expr: P, ) -> P { let def = ast::Defaultness::Final; - self.item(span, name, Vec::new(), ast::ItemKind::Const(def, ty, Some(expr))) + self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr))) } pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 3e1acf4382d..48ee23d2c3d 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -215,7 +215,7 @@ pub fn features( let features = match strip_unconfigured.configure_krate_attrs(krate.attrs) { None => { // The entire crate is unconfigured. - krate.attrs = Vec::new(); + krate.attrs = ast::AttrVec::new(); krate.items = Vec::new(); Features::default() } @@ -265,7 +265,7 @@ impl<'a> StripUnconfigured<'a> { } } - fn configure_krate_attrs(&self, mut attrs: Vec) -> Option> { + fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option { attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); if self.in_cfg(&attrs) { Some(attrs) } else { None } } @@ -292,9 +292,7 @@ impl<'a> StripUnconfigured<'a> { .iter() .flat_map(|(tree, spacing)| match tree.clone() { AttrAnnotatedTokenTree::Attributes(mut data) => { - let mut attrs: Vec<_> = std::mem::take(&mut data.attrs).into(); - attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); - data.attrs = attrs.into(); + data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); if self.in_cfg(&data.attrs) { data.tokens = LazyTokenStream::new( diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index cc72dab84af..c2add852a06 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -11,7 +11,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, ExprKind, ForeignItemKind}; +use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, AttrVec, ExprKind, ForeignItemKind}; use rustc_ast::{HasAttrs, HasNodeId}; use rustc_ast::{Inline, ItemKind, MacArgs, MacStmtStyle, MetaItemKind, ModKind}; use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind}; @@ -1001,7 +1001,7 @@ enum AddSemicolon { /// of functionality used by `InvocationCollector`. trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { type OutputTy = SmallVec<[Self; 1]>; - type AttrsTy: Deref = Vec; + type AttrsTy: Deref = ast::AttrVec; const KIND: AstFragmentKind; fn to_annotatable(self) -> Annotatable; fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy; @@ -1333,7 +1333,7 @@ impl InvocationCollectorNode for ast::Stmt { } StmtKind::Item(item) => match item.into_inner() { ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => { - (mac.args.need_semicolon(), mac, attrs.into()) + (mac.args.need_semicolon(), mac, attrs) } _ => unreachable!(), }, @@ -1390,7 +1390,7 @@ impl InvocationCollectorNode for P { fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { - TyKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No), + TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No), _ => unreachable!(), } } @@ -1414,7 +1414,7 @@ impl InvocationCollectorNode for P { fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { - PatKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No), + PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No), _ => unreachable!(), } } @@ -1646,7 +1646,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: ast::Attribute, pos: usize) { node.visit_attrs(|attrs| { - attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false)); + // Repeated `insert` calls is inefficient, but the number of + // insertions is almost always 0 or 1 in practice. + for cfg in self.cfg().expand_cfg_attr(attr, false).into_iter().rev() { + attrs.insert(pos, cfg) + } }); } diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 0315d11634c..9002a24e42f 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -1,6 +1,6 @@ use crate::base::ModuleData; use rustc_ast::ptr::P; -use rustc_ast::{token, Attribute, Inline, Item, ModSpans}; +use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans}; use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed}; use rustc_parse::new_parser_from_file; use rustc_parse::validate_attr; @@ -48,7 +48,7 @@ pub(crate) fn parse_external_mod( span: Span, // The span to blame on errors. module: &ModuleData, mut dir_ownership: DirOwnership, - attrs: &mut Vec, + attrs: &mut AttrVec, ) -> ParsedExternalMod { // We bail on the first error, but that error does not cause a fatal error... (1) let result: Result<_, ModError<'_>> = try { @@ -63,9 +63,9 @@ pub(crate) fn parse_external_mod( // Actually parse the external file as a module. let mut parser = new_parser_from_file(&sess.parse_sess, &mp.file_path, Some(span)); - let (mut inner_attrs, items, inner_span) = + let (inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?; - attrs.append(&mut inner_attrs); + attrs.extend(inner_attrs); (items, inner_span, mp.file_path) }; // (1) ...instead, we return a dummy module. diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 48918541e72..3b0d5ddb97b 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -24,7 +24,7 @@ pub fn placeholder( } let ident = Ident::empty(); - let attrs = Vec::new(); + let attrs = ast::AttrVec::new(); let vis = vis.unwrap_or(ast::Visibility { span: DUMMY_SP, kind: ast::VisibilityKind::Inherited, diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 5924eba9f8b..3691d82a835 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -62,7 +62,7 @@ pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<' pub fn parse_crate_attrs_from_file<'a>( input: &Path, sess: &'a ParseSess, -) -> PResult<'a, Vec> { +) -> PResult<'a, ast::AttrVec> { let mut parser = new_parser_from_file(sess, input, None); parser.parse_inner_attributes() } @@ -79,7 +79,7 @@ pub fn parse_crate_attrs_from_source_str( name: FileName, source: String, sess: &ParseSess, -) -> PResult<'_, Vec> { +) -> PResult<'_, ast::AttrVec> { new_parser_from_source_str(sess, name, source).parse_inner_attributes() } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index acdbddf4099..72ab96b5ca6 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -34,7 +34,7 @@ enum OuterAttributeType { impl<'a> Parser<'a> { /// Parses attributes that appear before an item. pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { - let mut outer_attrs: Vec = Vec::new(); + let mut outer_attrs = ast::AttrVec::new(); let mut just_parsed_doc_comment = false; let start_pos = self.token_cursor.num_next_calls; loop { @@ -106,7 +106,7 @@ impl<'a> Parser<'a> { break; } } - Ok(AttrWrapper::new(outer_attrs.into(), start_pos)) + Ok(AttrWrapper::new(outer_attrs, start_pos)) } /// Matches `attribute = # ! [ meta_item ]`. @@ -283,8 +283,8 @@ impl<'a> Parser<'a> { /// terminated by a semicolon. /// /// Matches `inner_attrs*`. - pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, Vec> { - let mut attrs: Vec = vec![]; + pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> { + let mut attrs = ast::AttrVec::new(); loop { let start_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap(); // Only try to parse if it is an inner attribute (has `!`). diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 6c750ff428f..ed54af9f53f 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -15,11 +15,11 @@ use std::ops::Range; /// for the attribute target. This allows us to perform cfg-expansion on /// a token stream before we invoke a derive proc-macro. /// -/// This wrapper prevents direct access to the underlying `Vec`. +/// This wrapper prevents direct access to the underlying `ast::AttrVec>`. /// Parsing code can only get access to the underlying attributes /// by passing an `AttrWrapper` to `collect_tokens_trailing_tokens`. /// This makes it difficult to accidentally construct an AST node -/// (which stores a `Vec`) without first collecting tokens. +/// (which stores an `ast::AttrVec`) without first collecting tokens. /// /// This struct has its own module, to ensure that the parser code /// cannot directly access the `attrs` field @@ -49,9 +49,10 @@ impl AttrWrapper { self.attrs } + // Prepend `self.attrs` to `attrs`. // FIXME: require passing an NT to prevent misuse of this method - pub(crate) fn prepend_to_nt_inner(self, attrs: &mut Vec) { - let mut self_attrs: Vec<_> = self.attrs.into(); + pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) { + let mut self_attrs = self.attrs.clone(); std::mem::swap(attrs, &mut self_attrs); attrs.extend(self_attrs); } @@ -196,7 +197,7 @@ impl<'a> Parser<'a> { &mut self, attrs: AttrWrapper, force_collect: ForceCollect, - f: impl FnOnce(&mut Self, Vec) -> PResult<'a, (R, TrailingToken)>, + f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, (R, TrailingToken)>, ) -> PResult<'a, R> { // We only bail out when nothing could possibly observe the collected tokens: // 1. We cannot be force collecting tokens (since force-collecting requires tokens @@ -212,7 +213,7 @@ impl<'a> Parser<'a> { // or `#[cfg_attr]` attributes. && !self.capture_cfg { - return Ok(f(self, attrs.attrs.into())?.0); + return Ok(f(self, attrs.attrs)?.0); } let start_token = (self.token.clone(), self.token_spacing); @@ -222,7 +223,7 @@ impl<'a> Parser<'a> { let prev_capturing = std::mem::replace(&mut self.capture_state.capturing, Capturing::Yes); let replace_ranges_start = self.capture_state.replace_ranges.len(); - let ret = f(self, attrs.attrs.into()); + let ret = f(self, attrs.attrs); self.capture_state.capturing = prev_capturing; @@ -352,7 +353,7 @@ impl<'a> Parser<'a> { // on the captured token stream. if self.capture_cfg && matches!(self.capture_state.capturing, Capturing::Yes) - && has_cfg_or_cfg_attr(&final_attrs) + && has_cfg_or_cfg_attr(final_attrs) { let attr_data = AttributesData { attrs: final_attrs.to_vec().into(), tokens }; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 7beec270e3b..d7facb29714 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2370,7 +2370,7 @@ impl<'a> Parser<'a> { fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option { let snapshot = self.create_snapshot_for_diagnostic(); - let param = match self.parse_const_param(vec![]) { + let param = match self.parse_const_param(AttrVec::new()) { Ok(param) => param, Err(err) => { err.cancel(); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index df092f55bfa..9fb9199231f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -950,15 +950,15 @@ impl<'a> Parser<'a> { &mut self, e0: P, lo: Span, - mut attrs: Vec, + mut attrs: ast::AttrVec, ) -> PResult<'a, P> { // Stitch the list of outer attributes onto the return value. // A little bit ugly, but the best way given the current code // structure self.parse_dot_or_call_expr_with_(e0, lo).map(|expr| { expr.map(|mut expr| { - attrs.extend::>(expr.attrs.into()); - expr.attrs = attrs.into(); + attrs.extend(expr.attrs); + expr.attrs = attrs; expr }) }) @@ -2224,7 +2224,7 @@ impl<'a> Parser<'a> { Ok(( Param { - attrs: attrs.into(), + attrs, ty, pat, span: lo.to(this.prev_token.span), @@ -2732,7 +2732,7 @@ impl<'a> Parser<'a> { let span = body.span; return Ok(( ast::Arm { - attrs: attrs.into(), + attrs, pat, guard, body, @@ -2810,7 +2810,7 @@ impl<'a> Parser<'a> { Ok(( ast::Arm { - attrs: attrs.into(), + attrs, pat, guard, body: expr, @@ -3123,7 +3123,7 @@ impl<'a> Parser<'a> { span: lo.to(expr.span), expr, is_shorthand, - attrs: attrs.into(), + attrs, id: DUMMY_NODE_ID, is_placeholder: false, }, @@ -3219,14 +3219,10 @@ impl<'a> Parser<'a> { await_expr } - pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: A) -> P - where - A: Into, - { - P(Expr { kind, span, attrs: attrs.into(), id: DUMMY_NODE_ID, tokens: None }) + pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P { + P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None }) } - // njn: rename pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P { P(Expr { kind, span, attrs: AttrVec::new(), id: DUMMY_NODE_ID, tokens: None }) } @@ -3248,7 +3244,7 @@ impl<'a> Parser<'a> { fn collect_tokens_for_expr( &mut self, attrs: AttrWrapper, - f: impl FnOnce(&mut Self, Vec) -> PResult<'a, P>, + f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P>, ) -> PResult<'a, P> { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let res = f(this, attrs)?; diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 5e5f2fd7d9f..4d0a8b05eb0 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -1,9 +1,7 @@ use super::{ForceCollect, Parser, TrailingToken}; use rustc_ast::token; -use rustc_ast::{ - self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause, -}; +use rustc_ast::{self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, WhereClause}; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::kw; @@ -26,7 +24,7 @@ impl<'a> Parser<'a> { } /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`. - fn parse_ty_param(&mut self, preceding_attrs: Vec) -> PResult<'a, GenericParam> { + fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> { let ident = self.parse_ident()?; // Parse optional colon and param bounds. @@ -43,7 +41,7 @@ impl<'a> Parser<'a> { Ok(GenericParam { ident, id: ast::DUMMY_NODE_ID, - attrs: preceding_attrs.into(), + attrs: preceding_attrs, bounds, kind: GenericParamKind::Type { default }, is_placeholder: false, @@ -53,7 +51,7 @@ impl<'a> Parser<'a> { pub(crate) fn parse_const_param( &mut self, - preceding_attrs: Vec, + preceding_attrs: AttrVec, ) -> PResult<'a, GenericParam> { let const_span = self.token.span; @@ -68,7 +66,7 @@ impl<'a> Parser<'a> { Ok(GenericParam { ident, id: ast::DUMMY_NODE_ID, - attrs: preceding_attrs.into(), + attrs: preceding_attrs, bounds: Vec::new(), kind: GenericParamKind::Const { ty, kw_span: const_span, default }, is_placeholder: false, @@ -109,7 +107,7 @@ impl<'a> Parser<'a> { Some(ast::GenericParam { ident: lifetime.ident, id: lifetime.id, - attrs: attrs.into(), + attrs, bounds, kind: ast::GenericParamKind::Lifetime, is_placeholder: false, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index cd3c982ce81..b743162a7e4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -32,7 +32,7 @@ impl<'a> Parser<'a> { } /// Parses a `mod { ... }` or `mod ;` item. - fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> { let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Mod)?; let id = self.parse_ident()?; @@ -40,9 +40,9 @@ impl<'a> Parser<'a> { ModKind::Unloaded } else { self.expect(&token::OpenDelim(Delimiter::Brace))?; - let (mut inner_attrs, items, inner_span) = + let (inner_attrs, items, inner_span) = self.parse_mod(&token::CloseDelim(Delimiter::Brace))?; - attrs.append(&mut inner_attrs); + attrs.extend(inner_attrs); ModKind::Loaded(items, Inline::Yes, inner_span) }; Ok((id, ItemKind::Mod(unsafety, mod_kind))) @@ -52,7 +52,7 @@ impl<'a> Parser<'a> { pub fn parse_mod( &mut self, term: &TokenKind, - ) -> PResult<'a, (Vec, Vec>, ModSpans)> { + ) -> PResult<'a, (AttrVec, Vec>, ModSpans)> { let lo = self.token.span; let attrs = self.parse_inner_attributes()?; @@ -134,7 +134,7 @@ impl<'a> Parser<'a> { fn parse_item_common_( &mut self, - mut attrs: Vec, + mut attrs: AttrVec, mac_allowed: bool, attrs_allowed: bool, fn_parse_mode: FnParseMode, @@ -198,7 +198,7 @@ impl<'a> Parser<'a> { /// Parses one of the items allowed by the flags. fn parse_item_kind( &mut self, - attrs: &mut Vec, + attrs: &mut AttrVec, macros_allowed: bool, lo: Span, vis: &Visibility, @@ -534,7 +534,7 @@ impl<'a> Parser<'a> { /// ``` fn parse_item_impl( &mut self, - attrs: &mut Vec, + attrs: &mut AttrVec, defaultness: Defaultness, ) -> PResult<'a, ItemInfo> { let unsafety = self.parse_unsafety(); @@ -661,12 +661,12 @@ impl<'a> Parser<'a> { fn parse_item_list( &mut self, - attrs: &mut Vec, + attrs: &mut AttrVec, mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option>>, ) -> PResult<'a, Vec> { let open_brace_span = self.token.span; self.expect(&token::OpenDelim(Delimiter::Brace))?; - attrs.append(&mut self.parse_inner_attributes()?); + attrs.extend(self.parse_inner_attributes()?); let mut items = Vec::new(); while !self.eat(&token::CloseDelim(Delimiter::Brace)) { @@ -775,7 +775,7 @@ impl<'a> Parser<'a> { } /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait(&mut self, attrs: &mut Vec, lo: Span) -> PResult<'a, ItemInfo> { + fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> { let unsafety = self.parse_unsafety(); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; @@ -1061,7 +1061,7 @@ impl<'a> Parser<'a> { /// ``` fn parse_item_foreign_mod( &mut self, - attrs: &mut Vec, + attrs: &mut AttrVec, mut unsafety: Unsafe, ) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? @@ -1179,7 +1179,7 @@ impl<'a> Parser<'a> { fn recover_const_impl( &mut self, const_span: Span, - attrs: &mut Vec, + attrs: &mut AttrVec, defaultness: Defaultness, ) -> PResult<'a, ItemInfo> { let impl_span = self.token.span; @@ -1337,7 +1337,7 @@ impl<'a> Parser<'a> { ident, vis, id: DUMMY_NODE_ID, - attrs: variant_attrs.into(), + attrs: variant_attrs, data: struct_def, disr_expr, span: vlo.to(this.prev_token.span), @@ -1494,7 +1494,7 @@ impl<'a> Parser<'a> { ident: None, id: DUMMY_NODE_ID, ty, - attrs: attrs.into(), + attrs, is_placeholder: false, }, TrailingToken::MaybeComma, @@ -1520,7 +1520,7 @@ impl<'a> Parser<'a> { adt_ty: &str, lo: Span, vis: Visibility, - attrs: Vec, + attrs: AttrVec, ) -> PResult<'a, FieldDef> { let mut seen_comma: bool = false; let a_var = self.parse_name_and_ty(adt_ty, lo, vis, attrs)?; @@ -1650,7 +1650,7 @@ impl<'a> Parser<'a> { adt_ty: &str, lo: Span, vis: Visibility, - attrs: Vec, + attrs: AttrVec, ) -> PResult<'a, FieldDef> { let name = self.parse_field_ident(adt_ty, lo)?; self.expect_field_ty_separator()?; @@ -1684,7 +1684,7 @@ impl<'a> Parser<'a> { vis, id: DUMMY_NODE_ID, ty, - attrs: attrs.into(), + attrs, is_placeholder: false, }) } @@ -1703,7 +1703,7 @@ impl<'a> Parser<'a> { // We use `parse_fn` to get a span for the function let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; if let Err(mut db) = - self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, &inherited_vis) + self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis) { db.delay_as_bug(); } @@ -1979,7 +1979,7 @@ impl<'a> Parser<'a> { /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`. fn parse_fn( &mut self, - attrs: &mut Vec, + attrs: &mut AttrVec, fn_parse_mode: FnParseMode, sig_lo: Span, vis: &Visibility, @@ -2002,7 +2002,7 @@ impl<'a> Parser<'a> { /// or e.g. a block when the function is a provided one. fn parse_fn_body( &mut self, - attrs: &mut Vec, + attrs: &mut AttrVec, ident: &Ident, sig_hi: &mut Span, req_body: bool, @@ -2017,7 +2017,7 @@ impl<'a> Parser<'a> { // Include the trailing semicolon in the span of the signature self.expect_semi()?; *sig_hi = self.prev_token.span; - (Vec::new(), None) + (AttrVec::new(), None) } else if self.check(&token::OpenDelim(Delimiter::Brace)) || self.token.is_whole_block() { self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))? } else if self.token.kind == token::Eq { @@ -2034,7 +2034,7 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ) .emit(); - (Vec::new(), Some(self.mk_block_err(span))) + (AttrVec::new(), Some(self.mk_block_err(span))) } else { let expected = if req_body { &[token::OpenDelim(Delimiter::Brace)][..] @@ -2051,7 +2051,7 @@ impl<'a> Parser<'a> { return Err(err); } } - (Vec::new(), None) + (AttrVec::new(), None) }; attrs.extend(inner_attrs); Ok(body) @@ -2280,7 +2280,7 @@ impl<'a> Parser<'a> { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. if let Some(mut param) = this.parse_self_param()? { - param.attrs = attrs.into(); + param.attrs = attrs; let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) }; return Ok((res?, TrailingToken::None)); } @@ -2341,14 +2341,7 @@ impl<'a> Parser<'a> { let span = lo.to(this.prev_token.span); Ok(( - Param { - attrs: attrs.into(), - id: ast::DUMMY_NODE_ID, - is_placeholder: false, - pat, - span, - ty, - }, + Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty }, TrailingToken::None, )) }) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 42bf8898447..8b3200d45fc 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -4,8 +4,8 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::{ - self as ast, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField, - PatKind, Path, QSelf, RangeEnd, RangeSyntax, + self as ast, AttrVec, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatKind, + Path, QSelf, RangeEnd, RangeSyntax, }; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; @@ -1093,7 +1093,7 @@ impl<'a> Parser<'a> { .emit(); } - fn parse_pat_field(&mut self, lo: Span, attrs: Vec) -> PResult<'a, PatField> { + fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> { // Check if a colon exists one ahead. This means we're parsing a fieldname. let hi; let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) { @@ -1134,7 +1134,7 @@ impl<'a> Parser<'a> { ident: fieldname, pat: subpat, is_shorthand, - attrs: attrs.into(), + attrs, id: ast::DUMMY_NODE_ID, span: lo.to(hi), is_placeholder: false, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 12b1a37e022..3d957406b19 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -130,7 +130,7 @@ impl<'a> Parser<'a> { let path = this.parse_path(PathStyle::Expr)?; if this.eat(&token::Not) { - let stmt_mac = this.parse_stmt_mac(lo, attrs.into(), path)?; + let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?; if this.token == token::Semi { return Ok((stmt_mac, TrailingToken::Semi)); } else { @@ -190,7 +190,7 @@ impl<'a> Parser<'a> { // Since none of the above applied, this is an expression statement macro. let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; - let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?; + let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?; let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; StmtKind::Expr(e) }; @@ -229,7 +229,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, Stmt> { self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { this.expect_keyword(kw::Let)?; - let local = this.parse_local(attrs.into())?; + let local = this.parse_local(attrs)?; let trailing = if capture_semi && this.token.kind == token::Semi { TrailingToken::Semi } else { @@ -241,7 +241,7 @@ impl<'a> Parser<'a> { fn recover_local_after_let(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { - let local = this.parse_local(attrs.into())?; + let local = this.parse_local(attrs)?; // FIXME - maybe capture semicolon in recovery? Ok(( this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), @@ -509,9 +509,7 @@ impl<'a> Parser<'a> { } /// Parses a block. Inner attributes are allowed. - pub(super) fn parse_inner_attrs_and_block( - &mut self, - ) -> PResult<'a, (Vec, P)> { + pub(super) fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (AttrVec, P)> { self.parse_block_common(self.token.span, BlockCheckMode::Default) } @@ -520,8 +518,8 @@ impl<'a> Parser<'a> { &mut self, lo: Span, blk_mode: BlockCheckMode, - ) -> PResult<'a, (Vec, P)> { - maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); + ) -> PResult<'a, (AttrVec, P)> { + maybe_whole!(self, NtBlock, |x| (AttrVec::new(), x)); self.maybe_recover_unexpected_block_label(); if !self.eat(&token::OpenDelim(Delimiter::Brace)) { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 51976a91cea..4c39021903c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1130,7 +1130,7 @@ pub struct RenderedLink { #[derive(Clone, Debug, Default)] pub(crate) struct Attributes { pub(crate) doc_strings: Vec, - pub(crate) other_attrs: Vec, + pub(crate) other_attrs: ast::AttrVec, } impl Attributes { @@ -1173,7 +1173,7 @@ impl Attributes { doc_only: bool, ) -> Attributes { let mut doc_strings = Vec::new(); - let mut other_attrs = Vec::new(); + let mut other_attrs = ast::AttrVec::new(); for (attr, parent_module) in attrs { if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() { trace!("got doc_str={doc_str:?}"); diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index 0d9c9350efc..117b798710c 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -30,7 +30,6 @@ use rustc_ast::mut_visit::{self, visit_clobber, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::*; use rustc_ast_pretty::pprust; -use rustc_data_structures::thin_vec::ThinVec; use rustc_parse::new_parser_from_source_str; use rustc_session::parse::ParseSess; use rustc_span::source_map::FilePathMapping; @@ -47,7 +46,7 @@ fn parse_expr(ps: &ParseSess, src: &str) -> Option> { // Helper functions for building exprs fn expr(kind: ExprKind) -> P { - P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: ThinVec::new(), tokens: None }) + P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: AttrVec::new(), tokens: None }) } fn make_x() -> P { @@ -196,7 +195,7 @@ impl MutVisitor for AddParens { id: DUMMY_NODE_ID, kind: ExprKind::Paren(e), span: DUMMY_SP, - attrs: ThinVec::new(), + attrs: AttrVec::new(), tokens: None, }) }); diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 61cb7b25e49..eb828bb9a2c 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -4,58 +4,58 @@ PRE EXPANSION AST STATS Name Accumulated Size Count Item Size ---------------------------------------------------------------- ExprField 48 ( 0.6%) 1 48 -Attribute 64 ( 0.7%) 2 32 +Crate 56 ( 0.7%) 1 56 +Attribute 64 ( 0.8%) 2 32 - Normal 32 ( 0.4%) 1 - DocComment 32 ( 0.4%) 1 -GenericArgs 64 ( 0.7%) 1 64 -- AngleBracketed 64 ( 0.7%) 1 -Local 72 ( 0.8%) 1 72 -WherePredicate 72 ( 0.8%) 1 72 -- BoundPredicate 72 ( 0.8%) 1 -Crate 72 ( 0.8%) 1 72 +GenericArgs 64 ( 0.8%) 1 64 +- AngleBracketed 64 ( 0.8%) 1 +Local 72 ( 0.9%) 1 72 +WherePredicate 72 ( 0.9%) 1 72 +- BoundPredicate 72 ( 0.9%) 1 Arm 96 ( 1.1%) 2 48 -ForeignItem 112 ( 1.3%) 1 112 -- Fn 112 ( 1.3%) 1 -FieldDef 160 ( 1.8%) 2 80 -Stmt 160 ( 1.8%) 5 32 +ForeignItem 96 ( 1.1%) 1 96 +- Fn 96 ( 1.1%) 1 +FieldDef 160 ( 1.9%) 2 80 +Stmt 160 ( 1.9%) 5 32 - Local 32 ( 0.4%) 1 - MacCall 32 ( 0.4%) 1 - Expr 96 ( 1.1%) 3 -Param 160 ( 1.8%) 4 40 -FnDecl 200 ( 2.3%) 5 40 +Param 160 ( 1.9%) 4 40 +FnDecl 200 ( 2.4%) 5 40 Variant 240 ( 2.8%) 2 120 -Block 288 ( 3.3%) 6 48 -GenericBound 352 ( 4.0%) 4 88 -- Trait 352 ( 4.0%) 4 -AssocItem 480 ( 5.5%) 4 120 -- TyAlias 240 ( 2.8%) 2 -- Fn 240 ( 2.8%) 2 -GenericParam 520 ( 6.0%) 5 104 -PathSegment 720 ( 8.3%) 30 24 -Expr 832 ( 9.6%) 8 104 +Block 288 ( 3.4%) 6 48 +GenericBound 352 ( 4.2%) 4 88 +- Trait 352 ( 4.2%) 4 +AssocItem 416 ( 4.9%) 4 104 +- TyAlias 208 ( 2.5%) 2 +- Fn 208 ( 2.5%) 2 +GenericParam 520 ( 6.1%) 5 104 +PathSegment 720 ( 8.5%) 30 24 +Expr 832 ( 9.8%) 8 104 - Path 104 ( 1.2%) 1 - Match 104 ( 1.2%) 1 - Struct 104 ( 1.2%) 1 -- Lit 208 ( 2.4%) 2 -- Block 312 ( 3.6%) 3 -Pat 840 ( 9.7%) 7 120 +- Lit 208 ( 2.5%) 2 +- Block 312 ( 3.7%) 3 +Pat 840 ( 9.9%) 7 120 - Struct 120 ( 1.4%) 1 - Wild 120 ( 1.4%) 1 -- Ident 600 ( 6.9%) 5 -Ty 1_344 (15.5%) 14 96 +- Ident 600 ( 7.1%) 5 +Ty 1_344 (15.9%) 14 96 - Rptr 96 ( 1.1%) 1 - Ptr 96 ( 1.1%) 1 -- ImplicitSelf 192 ( 2.2%) 2 -- Path 960 (11.0%) 10 -Item 1_800 (20.7%) 9 200 -- Trait 200 ( 2.3%) 1 -- Enum 200 ( 2.3%) 1 -- ForeignMod 200 ( 2.3%) 1 -- Impl 200 ( 2.3%) 1 -- Fn 400 ( 4.6%) 2 -- Use 600 ( 6.9%) 3 +- ImplicitSelf 192 ( 2.3%) 2 +- Path 960 (11.4%) 10 +Item 1_656 (19.6%) 9 184 +- Trait 184 ( 2.2%) 1 +- Enum 184 ( 2.2%) 1 +- ForeignMod 184 ( 2.2%) 1 +- Impl 184 ( 2.2%) 1 +- Fn 368 ( 4.4%) 2 +- Use 552 ( 6.5%) 3 ---------------------------------------------------------------- -Total 8_696 +Total 8_456 POST EXPANSION AST STATS @@ -63,15 +63,15 @@ POST EXPANSION AST STATS Name Accumulated Size Count Item Size ---------------------------------------------------------------- ExprField 48 ( 0.5%) 1 48 +Crate 56 ( 0.6%) 1 56 GenericArgs 64 ( 0.7%) 1 64 - AngleBracketed 64 ( 0.7%) 1 Local 72 ( 0.8%) 1 72 WherePredicate 72 ( 0.8%) 1 72 - BoundPredicate 72 ( 0.8%) 1 -Crate 72 ( 0.8%) 1 72 Arm 96 ( 1.0%) 2 48 -ForeignItem 112 ( 1.2%) 1 112 -- Fn 112 ( 1.2%) 1 +ForeignItem 96 ( 1.0%) 1 96 +- Fn 96 ( 1.0%) 1 InlineAsm 120 ( 1.3%) 1 120 Attribute 128 ( 1.4%) 4 32 - DocComment 32 ( 0.3%) 1 @@ -82,42 +82,42 @@ Stmt 160 ( 1.7%) 5 32 - Semi 32 ( 0.3%) 1 - Expr 96 ( 1.0%) 3 Param 160 ( 1.7%) 4 40 -FnDecl 200 ( 2.1%) 5 40 -Variant 240 ( 2.5%) 2 120 -Block 288 ( 3.0%) 6 48 -GenericBound 352 ( 3.7%) 4 88 -- Trait 352 ( 3.7%) 4 -AssocItem 480 ( 5.1%) 4 120 -- TyAlias 240 ( 2.5%) 2 -- Fn 240 ( 2.5%) 2 -GenericParam 520 ( 5.5%) 5 104 -PathSegment 792 ( 8.4%) 33 24 -Pat 840 ( 8.9%) 7 120 +FnDecl 200 ( 2.2%) 5 40 +Variant 240 ( 2.6%) 2 120 +Block 288 ( 3.1%) 6 48 +GenericBound 352 ( 3.8%) 4 88 +- Trait 352 ( 3.8%) 4 +AssocItem 416 ( 4.5%) 4 104 +- TyAlias 208 ( 2.3%) 2 +- Fn 208 ( 2.3%) 2 +GenericParam 520 ( 5.7%) 5 104 +PathSegment 792 ( 8.6%) 33 24 +Pat 840 ( 9.1%) 7 120 - Struct 120 ( 1.3%) 1 - Wild 120 ( 1.3%) 1 -- Ident 600 ( 6.3%) 5 -Expr 936 ( 9.9%) 9 104 +- Ident 600 ( 6.5%) 5 +Expr 936 (10.2%) 9 104 - Path 104 ( 1.1%) 1 - Match 104 ( 1.1%) 1 - Struct 104 ( 1.1%) 1 - InlineAsm 104 ( 1.1%) 1 -- Lit 208 ( 2.2%) 2 -- Block 312 ( 3.3%) 3 -Ty 1_344 (14.2%) 14 96 +- Lit 208 ( 2.3%) 2 +- Block 312 ( 3.4%) 3 +Ty 1_344 (14.6%) 14 96 - Rptr 96 ( 1.0%) 1 - Ptr 96 ( 1.0%) 1 -- ImplicitSelf 192 ( 2.0%) 2 -- Path 960 (10.2%) 10 -Item 2_200 (23.3%) 11 200 -- Trait 200 ( 2.1%) 1 -- Enum 200 ( 2.1%) 1 -- ExternCrate 200 ( 2.1%) 1 -- ForeignMod 200 ( 2.1%) 1 -- Impl 200 ( 2.1%) 1 -- Fn 400 ( 4.2%) 2 -- Use 800 ( 8.5%) 4 +- ImplicitSelf 192 ( 2.1%) 2 +- Path 960 (10.5%) 10 +Item 2_024 (22.0%) 11 184 +- Trait 184 ( 2.0%) 1 +- Enum 184 ( 2.0%) 1 +- ExternCrate 184 ( 2.0%) 1 +- ForeignMod 184 ( 2.0%) 1 +- Impl 184 ( 2.0%) 1 +- Fn 368 ( 4.0%) 2 +- Use 736 ( 8.0%) 4 ---------------------------------------------------------------- -Total 9_456 +Total 9_184 HIR STATS diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 41ba9a847e6..f5c1ee5fdd1 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -49,10 +49,7 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { } /// Returns attributes that are within `outer_span`. -pub(crate) fn filter_inline_attrs( - attrs: &[ast::Attribute], - outer_span: Span, -) -> Vec { +pub(crate) fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> ast::AttrVec { attrs .iter() .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi()) diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs index 8d41c881589..b6530c69243 100644 --- a/src/tools/rustfmt/src/imports.rs +++ b/src/tools/rustfmt/src/imports.rs @@ -116,7 +116,7 @@ pub(crate) struct UseTree { // Additional fields for top level use items. // Should we have another struct for top-level use items rather than reusing this? visibility: Option, - attrs: Option>, + attrs: Option, } impl PartialEq for UseTree { @@ -417,7 +417,7 @@ impl UseTree { list_item: Option, visibility: Option, opt_lo: Option, - attrs: Option>, + attrs: Option, ) -> UseTree { let span = if let Some(lo) = opt_lo { mk_sp(lo, a.span.hi()) diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index 81da724329f..7a0d1736c59 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -26,7 +26,7 @@ type FileModMap<'ast> = BTreeMap>; pub(crate) struct Module<'a> { ast_mod_kind: Option>, pub(crate) items: Cow<'a, Vec>>, - inner_attr: Vec, + inner_attr: ast::AttrVec, pub(crate) span: Span, } @@ -35,7 +35,7 @@ impl<'a> Module<'a> { mod_span: Span, ast_mod_kind: Option>, mod_items: Cow<'a, Vec>>, - mod_attrs: Cow<'a, Vec>, + mod_attrs: Cow<'a, ast::AttrVec>, ) -> Self { let inner_attr = mod_attrs .iter() @@ -158,7 +158,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { module_item.item.span, Some(Cow::Owned(sub_mod_kind.clone())), Cow::Owned(vec![]), - Cow::Owned(vec![]), + Cow::Owned(ast::AttrVec::new()), ), )?; } @@ -185,7 +185,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { span, Some(Cow::Owned(sub_mod_kind.clone())), Cow::Owned(vec![]), - Cow::Owned(vec![]), + Cow::Owned(ast::AttrVec::new()), ), )?; } diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs index 268c72649a6..e0bd065518b 100644 --- a/src/tools/rustfmt/src/parse/parser.rs +++ b/src/tools/rustfmt/src/parse/parser.rs @@ -109,7 +109,7 @@ impl<'a> Parser<'a> { sess: &'a ParseSess, path: &Path, span: Span, - ) -> Result<(Vec, Vec>, Span), ParserError> { + ) -> Result<(ast::AttrVec, Vec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), path, Some(span)); match parser.parse_mod(&TokenKind::Eof) { -- cgit 1.4.1-3-g733a5 From 31e39446ec2f251efbcaf9eb22c80e93021f9bbc Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 14 Jul 2022 08:30:38 -0500 Subject: Stabilize `#![feature(label_break_value)]` # Stabilization proposal The feature was implemented in https://github.com/rust-lang/rust/pull/50045 by est31 and has been in nightly since 2018-05-16 (over 4 years now). There are [no open issues][issue-label] other than the tracking issue. There is a strong consensus that `break` is the right keyword and we should not use `return`. There have been several concerns raised about this feature on the tracking issue (other than the one about tests, which has been fixed, and an interaction with try blocks, which has been fixed). 1. nrc's original comment about cost-benefit analysis: https://github.com/rust-lang/rust/issues/48594#issuecomment-422235234 2. joshtriplett's comments about seeing use cases: https://github.com/rust-lang/rust/issues/48594#issuecomment-422281176 3. withoutboats's comments that Rust does not need more control flow constructs: https://github.com/rust-lang/rust/issues/48594#issuecomment-450050630 Many different examples of code that's simpler using this feature have been provided: - A lexer by rpjohnst which must repeat code without label-break-value: https://github.com/rust-lang/rust/issues/48594#issuecomment-422502014 - A snippet by SergioBenitez which avoids using a new function and adding several new return points to a function: https://github.com/rust-lang/rust/issues/48594#issuecomment-427628251. This particular case would also work if `try` blocks were stabilized (at the cost of making the code harder to optimize). - Several examples by JohnBSmith: https://github.com/rust-lang/rust/issues/48594#issuecomment-434651395 - Several examples by Centril: https://github.com/rust-lang/rust/issues/48594#issuecomment-440154733 - An example by petrochenkov where this is used in the compiler itself to avoid duplicating error checking code: https://github.com/rust-lang/rust/issues/48594#issuecomment-443557569 - Amanieu recently provided another example related to complex conditions, where try blocks would not have helped: https://github.com/rust-lang/rust/issues/48594#issuecomment-1184213006 Additionally, petrochenkov notes that this is strictly more powerful than labelled loops due to macros which accidentally exit a loop instead of being consumed by the macro matchers: https://github.com/rust-lang/rust/issues/48594#issuecomment-450246249 nrc later resolved their concern, mostly because of the aforementioned macro problems. joshtriplett suggested that macros could be able to generate IR directly (https://github.com/rust-lang/rust/issues/48594#issuecomment-451685983) but there are no open RFCs, and the design space seems rather speculative. joshtriplett later resolved his concerns, due to a symmetry between this feature and existing labelled break: https://github.com/rust-lang/rust/issues/48594#issuecomment-632960804 withoutboats has regrettably left the language team. joshtriplett later posted that the lang team would consider starting an FCP given a stabilization report: https://github.com/rust-lang/rust/issues/48594#issuecomment-1111269353 [issue-label]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AF-label_break_value+ ## Report + Feature gate: - https://github.com/rust-lang/rust/blob/d695a497bbf4b20d2580b75075faa80230d41667/src/test/ui/feature-gates/feature-gate-label_break_value.rs + Diagnostics: - https://github.com/rust-lang/rust/blob/6b2d3d5f3cd1e553d87b5496632132565b6779d3/compiler/rustc_parse/src/parser/diagnostics.rs#L2629 - https://github.com/rust-lang/rust/blob/f65bf0b2bb1a99f73095c01a118f3c37d3ee614c/compiler/rustc_resolve/src/diagnostics.rs#L749 - https://github.com/rust-lang/rust/blob/f65bf0b2bb1a99f73095c01a118f3c37d3ee614c/compiler/rustc_resolve/src/diagnostics.rs#L1001 - https://github.com/rust-lang/rust/blob/111df9e6eda1d752233482c1309d00d20a4bbf98/compiler/rustc_passes/src/loops.rs#L254 - https://github.com/rust-lang/rust/blob/d695a497bbf4b20d2580b75075faa80230d41667/compiler/rustc_parse/src/parser/expr.rs#L2079 - https://github.com/rust-lang/rust/blob/d695a497bbf4b20d2580b75075faa80230d41667/compiler/rustc_parse/src/parser/expr.rs#L1569 + Tests: - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_continue.rs - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_unlabeled_break.rs - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_illegal_uses.rs - https://github.com/rust-lang/rust/blob/master/src/test/ui/lint/unused_labels.rs - https://github.com/rust-lang/rust/blob/master/src/test/ui/run-pass/for-loop-while/label_break_value.rs ## Interactions with other features Labels follow the hygiene of local variables. label-break-value is permitted within `try` blocks: ```rust let _: Result<(), ()> = try { 'foo: { Err(())?; break 'foo; } }; ``` label-break-value is disallowed within closures, generators, and async blocks: ```rust 'a: { || break 'a //~^ ERROR use of unreachable label `'a` //~| ERROR `break` inside of a closure } ``` label-break-value is disallowed on [_BlockExpression_]; it can only occur as a [_LoopExpression_]: ```rust fn labeled_match() { match false 'b: { //~ ERROR block label not supported here _ => {} } } macro_rules! m { ($b:block) => { 'lab: $b; //~ ERROR cannot use a `block` macro fragment here unsafe $b; //~ ERROR cannot use a `block` macro fragment here |x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here } } fn foo() { m!({}); } ``` [_BlockExpression_]: https://doc.rust-lang.org/nightly/reference/expressions/block-expr.html [_LoopExpression_]: https://doc.rust-lang.org/nightly/reference/expressions/loop-expr.html --- compiler/rustc_ast/src/lib.rs | 2 +- compiler/rustc_ast_passes/src/feature_gate.rs | 9 --------- compiler/rustc_error_codes/src/error_codes/E0695.md | 3 --- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/active.rs | 2 -- compiler/rustc_infer/src/lib.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 4 ---- compiler/rustc_trait_selection/src/lib.rs | 2 +- compiler/rustc_typeck/src/lib.rs | 2 +- library/std/src/lib.rs | 2 +- .../feature-gates/feature-gate-label_break_value.rs | 5 ----- .../feature-gate-label_break_value.stderr | 12 ------------ src/test/ui/for-loop-while/label_break_value.rs | 1 - .../ui/for-loop-while/label_break_value_invalid.rs | 1 - .../for-loop-while/label_break_value_invalid.stderr | 6 +++--- src/test/ui/issues/issue-62480.rs | 2 -- src/test/ui/issues/issue-62480.stderr | 4 ++-- src/test/ui/label/label_break_value_continue.rs | 1 - src/test/ui/label/label_break_value_continue.stderr | 6 +++--- .../ui/label/label_break_value_desugared_break.rs | 9 ++++++++- .../ui/label/label_break_value_illegal_uses.fixed | 1 - src/test/ui/label/label_break_value_illegal_uses.rs | 1 - .../ui/label/label_break_value_illegal_uses.stderr | 8 ++++---- .../ui/label/label_break_value_unlabeled_break.rs | 1 - .../label/label_break_value_unlabeled_break.stderr | 4 ++-- src/test/ui/lint/unused_labels.rs | 1 - src/test/ui/lint/unused_labels.stderr | 20 ++++++++++---------- src/test/ui/macros/stringify.rs | 1 - src/test/ui/parser/bad-interpolated-block.rs | 2 -- src/test/ui/parser/bad-interpolated-block.stderr | 6 +++--- src/test/ui/parser/labeled-no-colon-expr.rs | 2 -- src/test/ui/parser/labeled-no-colon-expr.stderr | 16 ++++++++-------- .../ui/parser/recover-labeled-non-block-expr.fixed | 1 - src/test/ui/parser/recover-labeled-non-block-expr.rs | 1 - .../ui/parser/recover-labeled-non-block-expr.stderr | 12 ++++++------ .../clippy/tests/ui/semicolon_if_nothing_returned.rs | 1 - .../tests/ui/semicolon_if_nothing_returned.stderr | 10 +++++----- src/tools/rustfmt/tests/source/issue-3217.rs | 2 -- src/tools/rustfmt/tests/target/issue-3217.rs | 2 -- 39 files changed, 61 insertions(+), 108 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-label_break_value.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-label_break_value.stderr (limited to 'compiler/rustc_parse/src/parser/expr.rs') diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 2426a0cb7dd..f9b4d76f28f 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -13,7 +13,7 @@ #![feature(const_default_impls)] #![feature(const_trait_impl)] #![feature(if_let_guard)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(slice_internals)] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 68fca081018..4ac96ec8b60 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -647,14 +647,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ExprKind::TryBlock(_) => { gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); } - ast::ExprKind::Block(_, Some(label)) => { - gate_feature_post!( - &self, - label_break_value, - label.ident.span, - "labels on blocks are unstable" - ); - } _ => {} } visit::walk_expr(self, e) @@ -823,7 +815,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(box_patterns, "box pattern syntax is experimental"); gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental"); gate_all!(try_blocks, "`try` blocks are unstable"); - gate_all!(label_break_value, "labels on blocks are unstable"); gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead"); gate_all!(type_ascription, "type ascription is experimental"); diff --git a/compiler/rustc_error_codes/src/error_codes/E0695.md b/compiler/rustc_error_codes/src/error_codes/E0695.md index 5013e83ca03..577f42ef301 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0695.md +++ b/compiler/rustc_error_codes/src/error_codes/E0695.md @@ -3,7 +3,6 @@ A `break` statement without a label appeared inside a labeled block. Erroneous code example: ```compile_fail,E0695 -# #![feature(label_break_value)] loop { 'a: { break; @@ -14,7 +13,6 @@ loop { Make sure to always label the `break`: ``` -# #![feature(label_break_value)] 'l: loop { 'a: { break 'l; @@ -25,7 +23,6 @@ Make sure to always label the `break`: Or if you want to `break` the labeled block: ``` -# #![feature(label_break_value)] loop { 'a: { break 'a; diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 2d24101b2d5..37b2b0ecad7 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -186,6 +186,8 @@ declare_features! ( /// Allows some increased flexibility in the name resolution rules, /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120), None), + /// Allows `'a: { break 'a; }`. + (accepted, label_break_value, "1.65.0", Some(48594), None), /// Allows `if/while p && let q = r && ...` chains. (accepted, let_chains, "1.64.0", Some(53667), None), /// Allows `break {expr}` with a value inside `loop`s. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1018facebae..22178dd2123 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -420,8 +420,6 @@ declare_features! ( (active, intra_doc_pointers, "1.51.0", Some(80896), None), /// Allows `#[instruction_set(_)]` attribute (active, isa_attribute, "1.48.0", Some(74727), None), - /// Allows `'a: { break 'a; }`. - (active, label_break_value, "1.28.0", Some(48594), None), // Allows setting the threshold for the `large_assignments` lint. (active, large_assignments, "1.52.0", Some(83518), None), /// Allows `let...else` statements. diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 1c515f5ee57..8f02a6cc4a1 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -17,7 +17,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(extend_one)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index df092f55bfa..94923d8ca76 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2075,10 +2075,6 @@ impl<'a> Parser<'a> { } } - if let Some(label) = opt_label { - self.sess.gated_spans.gate(sym::label_break_value, label.ident.span); - } - if self.token.is_whole_block() { self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here") .span_label(lo.to(self.token.span), "the `block` fragment is within this context") diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 9c252fcfe1c..059feb95643 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -16,7 +16,7 @@ #![feature(control_flow_enum)] #![feature(drain_filter)] #![feature(hash_drain_filter)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_else)] #![feature(if_let_guard)] #![feature(never_type)] diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 8c6fb6a7718..ffcd74858d3 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -64,7 +64,7 @@ This API is completely unstable and subject to change. #![feature(if_let_guard)] #![feature(is_sorted)] #![feature(iter_intersperse)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5029023121f..5047a58369e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -252,7 +252,7 @@ #![feature(dropck_eyepatch)] #![feature(exhaustive_patterns)] #![feature(intra_doc_pointers)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(lang_items)] #![feature(let_else)] #![feature(linkage)] diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.rs b/src/test/ui/feature-gates/feature-gate-label_break_value.rs deleted file mode 100644 index 6fc38f45517..00000000000 --- a/src/test/ui/feature-gates/feature-gate-label_break_value.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn main() { - 'a: { //~ ERROR labels on blocks are unstable - break 'a; - } -} diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr deleted file mode 100644 index 4b43fdc593f..00000000000 --- a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: labels on blocks are unstable - --> $DIR/feature-gate-label_break_value.rs:2:5 - | -LL | 'a: { - | ^^ - | - = note: see issue #48594 for more information - = help: add `#![feature(label_break_value)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/for-loop-while/label_break_value.rs b/src/test/ui/for-loop-while/label_break_value.rs index ca9d71a7a8b..10992c50597 100644 --- a/src/test/ui/for-loop-while/label_break_value.rs +++ b/src/test/ui/for-loop-while/label_break_value.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] #![allow(unused_assignments)] -#![feature(label_break_value)] // Test control flow to follow label_break_value semantics fn label_break(a: bool, b: bool) -> u32 { diff --git a/src/test/ui/for-loop-while/label_break_value_invalid.rs b/src/test/ui/for-loop-while/label_break_value_invalid.rs index 149bf17b83c..fcf2e0f294e 100644 --- a/src/test/ui/for-loop-while/label_break_value_invalid.rs +++ b/src/test/ui/for-loop-while/label_break_value_invalid.rs @@ -1,5 +1,4 @@ #![crate_type = "lib"] -#![feature(label_break_value)] fn lbv_macro_test_hygiene_respected() { macro_rules! mac2 { diff --git a/src/test/ui/for-loop-while/label_break_value_invalid.stderr b/src/test/ui/for-loop-while/label_break_value_invalid.stderr index 7182b8f598f..f6999c4ab11 100644 --- a/src/test/ui/for-loop-while/label_break_value_invalid.stderr +++ b/src/test/ui/for-loop-while/label_break_value_invalid.stderr @@ -1,5 +1,5 @@ error[E0426]: use of undeclared label `'a` - --> $DIR/label_break_value_invalid.rs:7:19 + --> $DIR/label_break_value_invalid.rs:6:19 | LL | break 'a $val; | ^^ undeclared label `'a` @@ -10,7 +10,7 @@ LL | mac2!(2); = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0426]: use of undeclared label `'a` - --> $DIR/label_break_value_invalid.rs:29:19 + --> $DIR/label_break_value_invalid.rs:28:19 | LL | let x: u8 = mac3!('b: { | -- a label with a similar name is reachable @@ -22,7 +22,7 @@ LL | break 'a 3; | help: try using similarly named label: `'b` error[E0426]: use of undeclared label `'a` - --> $DIR/label_break_value_invalid.rs:34:29 + --> $DIR/label_break_value_invalid.rs:33:29 | LL | let x: u8 = mac3!(break 'a 4); | ^^ undeclared label `'a` diff --git a/src/test/ui/issues/issue-62480.rs b/src/test/ui/issues/issue-62480.rs index 5c3be3e64ee..94a9c2ab8be 100644 --- a/src/test/ui/issues/issue-62480.rs +++ b/src/test/ui/issues/issue-62480.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() { // This used to ICE during liveness check because `target_id` passed to // `propagate_through_expr` would be the closure and not the `loop`, which wouldn't be found in diff --git a/src/test/ui/issues/issue-62480.stderr b/src/test/ui/issues/issue-62480.stderr index 17085ef908b..db230537037 100644 --- a/src/test/ui/issues/issue-62480.stderr +++ b/src/test/ui/issues/issue-62480.stderr @@ -1,5 +1,5 @@ error[E0767]: use of unreachable label `'a` - --> $DIR/issue-62480.rs:8:18 + --> $DIR/issue-62480.rs:6:18 | LL | 'a: { | -- unreachable label defined here @@ -9,7 +9,7 @@ LL | || break 'a = note: labels are unreachable through functions, closures, async blocks and modules error[E0267]: `break` inside of a closure - --> $DIR/issue-62480.rs:8:12 + --> $DIR/issue-62480.rs:6:12 | LL | || break 'a | -- ^^^^^^^^ cannot `break` inside of a closure diff --git a/src/test/ui/label/label_break_value_continue.rs b/src/test/ui/label/label_break_value_continue.rs index e0deb30c950..22172f4fd2e 100644 --- a/src/test/ui/label/label_break_value_continue.rs +++ b/src/test/ui/label/label_break_value_continue.rs @@ -1,4 +1,3 @@ -#![feature(label_break_value)] #![allow(unused_labels)] // Simple continue pointing to an unlabeled break should yield in an error diff --git a/src/test/ui/label/label_break_value_continue.stderr b/src/test/ui/label/label_break_value_continue.stderr index 9b8693dc584..284d213d65e 100644 --- a/src/test/ui/label/label_break_value_continue.stderr +++ b/src/test/ui/label/label_break_value_continue.stderr @@ -1,11 +1,11 @@ error[E0695]: unlabeled `continue` inside of a labeled block - --> $DIR/label_break_value_continue.rs:7:9 + --> $DIR/label_break_value_continue.rs:6:9 | LL | continue; | ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label error[E0696]: `continue` pointing to a labeled block - --> $DIR/label_break_value_continue.rs:14:9 + --> $DIR/label_break_value_continue.rs:13:9 | LL | / 'b: { LL | | continue 'b; @@ -14,7 +14,7 @@ LL | | } | |_____- labeled block the `continue` points to error[E0695]: unlabeled `continue` inside of a labeled block - --> $DIR/label_break_value_continue.rs:22:13 + --> $DIR/label_break_value_continue.rs:21:13 | LL | continue; | ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label diff --git a/src/test/ui/label/label_break_value_desugared_break.rs b/src/test/ui/label/label_break_value_desugared_break.rs index de883b61111..70227d86933 100644 --- a/src/test/ui/label/label_break_value_desugared_break.rs +++ b/src/test/ui/label/label_break_value_desugared_break.rs @@ -1,5 +1,5 @@ // compile-flags: --edition 2018 -#![feature(label_break_value, try_blocks)] +#![feature(try_blocks)] // run-pass fn main() { @@ -9,4 +9,11 @@ fn main() { break 'foo; } }; + + 'foo: { + let _: Result<(), ()> = try { + Err(())?; + break 'foo; + }; + } } diff --git a/src/test/ui/label/label_break_value_illegal_uses.fixed b/src/test/ui/label/label_break_value_illegal_uses.fixed index c1d2023a216..fb75276b4f4 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.fixed +++ b/src/test/ui/label/label_break_value_illegal_uses.fixed @@ -1,5 +1,4 @@ // run-rustfix -#![feature(label_break_value)] // These are forbidden occurrences of label-break-value diff --git a/src/test/ui/label/label_break_value_illegal_uses.rs b/src/test/ui/label/label_break_value_illegal_uses.rs index 5b20c95e581..3cbf41380e6 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.rs +++ b/src/test/ui/label/label_break_value_illegal_uses.rs @@ -1,5 +1,4 @@ // run-rustfix -#![feature(label_break_value)] // These are forbidden occurrences of label-break-value diff --git a/src/test/ui/label/label_break_value_illegal_uses.stderr b/src/test/ui/label/label_break_value_illegal_uses.stderr index 24b733fec53..15016ffd54a 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.stderr +++ b/src/test/ui/label/label_break_value_illegal_uses.stderr @@ -1,23 +1,23 @@ error: block label not supported here - --> $DIR/label_break_value_illegal_uses.rs:8:12 + --> $DIR/label_break_value_illegal_uses.rs:7:12 | LL | unsafe 'b: {} | ^^^ not supported here error: block label not supported here - --> $DIR/label_break_value_illegal_uses.rs:12:13 + --> $DIR/label_break_value_illegal_uses.rs:11:13 | LL | if true 'b: {} | ^^^ not supported here error: block label not supported here - --> $DIR/label_break_value_illegal_uses.rs:16:21 + --> $DIR/label_break_value_illegal_uses.rs:15:21 | LL | if true {} else 'b: {} | ^^^ not supported here error: block label not supported here - --> $DIR/label_break_value_illegal_uses.rs:20:17 + --> $DIR/label_break_value_illegal_uses.rs:19:17 | LL | match false 'b: { | ^^^ not supported here diff --git a/src/test/ui/label/label_break_value_unlabeled_break.rs b/src/test/ui/label/label_break_value_unlabeled_break.rs index fa0c70edc78..2a4f5d57493 100644 --- a/src/test/ui/label/label_break_value_unlabeled_break.rs +++ b/src/test/ui/label/label_break_value_unlabeled_break.rs @@ -1,4 +1,3 @@ -#![feature(label_break_value)] #![allow(unused_labels)] // Simple unlabeled break should yield in an error diff --git a/src/test/ui/label/label_break_value_unlabeled_break.stderr b/src/test/ui/label/label_break_value_unlabeled_break.stderr index 0c4f573d27d..a2ccd27b836 100644 --- a/src/test/ui/label/label_break_value_unlabeled_break.stderr +++ b/src/test/ui/label/label_break_value_unlabeled_break.stderr @@ -1,11 +1,11 @@ error[E0695]: unlabeled `break` inside of a labeled block - --> $DIR/label_break_value_unlabeled_break.rs:7:9 + --> $DIR/label_break_value_unlabeled_break.rs:6:9 | LL | break; | ^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label error[E0695]: unlabeled `break` inside of a labeled block - --> $DIR/label_break_value_unlabeled_break.rs:15:13 + --> $DIR/label_break_value_unlabeled_break.rs:14:13 | LL | break; | ^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label diff --git a/src/test/ui/lint/unused_labels.rs b/src/test/ui/lint/unused_labels.rs index 8a3568f65f6..87a5392fd30 100644 --- a/src/test/ui/lint/unused_labels.rs +++ b/src/test/ui/lint/unused_labels.rs @@ -4,7 +4,6 @@ // check-pass -#![feature(label_break_value)] #![warn(unused_labels)] fn main() { diff --git a/src/test/ui/lint/unused_labels.stderr b/src/test/ui/lint/unused_labels.stderr index 85adc9ab3bf..846da792bed 100644 --- a/src/test/ui/lint/unused_labels.stderr +++ b/src/test/ui/lint/unused_labels.stderr @@ -1,5 +1,5 @@ warning: label name `'many_used_shadowed` shadows a label name that is already in scope - --> $DIR/unused_labels.rs:62:9 + --> $DIR/unused_labels.rs:61:9 | LL | 'many_used_shadowed: for _ in 0..10 { | ------------------- first declared here @@ -8,55 +8,55 @@ LL | 'many_used_shadowed: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^^^ label `'many_used_shadowed` already in scope warning: unused label - --> $DIR/unused_labels.rs:11:5 + --> $DIR/unused_labels.rs:10:5 | LL | 'unused_while_label: while 0 == 0 { | ^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/unused_labels.rs:8:9 + --> $DIR/unused_labels.rs:7:9 | LL | #![warn(unused_labels)] | ^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:16:5 + --> $DIR/unused_labels.rs:15:5 | LL | 'unused_while_let_label: while let Some(_) = opt { | ^^^^^^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:20:5 + --> $DIR/unused_labels.rs:19:5 | LL | 'unused_for_label: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:36:9 + --> $DIR/unused_labels.rs:35:9 | LL | 'unused_loop_label_inner_2: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:42:5 + --> $DIR/unused_labels.rs:41:5 | LL | 'unused_loop_label_outer_3: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:60:5 + --> $DIR/unused_labels.rs:59:5 | LL | 'many_used_shadowed: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:72:5 + --> $DIR/unused_labels.rs:71:5 | LL | 'unused_loop_label: loop { | ^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:78:5 + --> $DIR/unused_labels.rs:77:5 | LL | 'unused_block_label: { | ^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index 082c1abb8f2..dd159cb5b6e 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -9,7 +9,6 @@ #![feature(decl_macro)] #![feature(generators)] #![feature(half_open_range_patterns)] -#![feature(label_break_value)] #![feature(more_qualified_paths)] #![feature(raw_ref_op)] #![feature(trait_alias)] diff --git a/src/test/ui/parser/bad-interpolated-block.rs b/src/test/ui/parser/bad-interpolated-block.rs index 38d53a14bc0..c6d7ae383b2 100644 --- a/src/test/ui/parser/bad-interpolated-block.rs +++ b/src/test/ui/parser/bad-interpolated-block.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() {} macro_rules! m { diff --git a/src/test/ui/parser/bad-interpolated-block.stderr b/src/test/ui/parser/bad-interpolated-block.stderr index 77933b1bcec..2a0999afdfa 100644 --- a/src/test/ui/parser/bad-interpolated-block.stderr +++ b/src/test/ui/parser/bad-interpolated-block.stderr @@ -1,5 +1,5 @@ error: cannot use a `block` macro fragment here - --> $DIR/bad-interpolated-block.rs:7:15 + --> $DIR/bad-interpolated-block.rs:5:15 | LL | 'lab: $b; | ------^^ @@ -12,7 +12,7 @@ LL | m!({}); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use a `block` macro fragment here - --> $DIR/bad-interpolated-block.rs:8:16 + --> $DIR/bad-interpolated-block.rs:6:16 | LL | unsafe $b; | -------^^ @@ -25,7 +25,7 @@ LL | m!({}); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use a `block` macro fragment here - --> $DIR/bad-interpolated-block.rs:9:23 + --> $DIR/bad-interpolated-block.rs:7:23 | LL | |x: u8| -> () $b; | ^^ the `block` fragment is within this context diff --git a/src/test/ui/parser/labeled-no-colon-expr.rs b/src/test/ui/parser/labeled-no-colon-expr.rs index db9ef52c1ae..d9ebd7473bc 100644 --- a/src/test/ui/parser/labeled-no-colon-expr.rs +++ b/src/test/ui/parser/labeled-no-colon-expr.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() { 'l0 while false {} //~ ERROR labeled expression must be followed by `:` 'l1 for _ in 0..1 {} //~ ERROR labeled expression must be followed by `:` diff --git a/src/test/ui/parser/labeled-no-colon-expr.stderr b/src/test/ui/parser/labeled-no-colon-expr.stderr index a258bd3ccde..62288fe152d 100644 --- a/src/test/ui/parser/labeled-no-colon-expr.stderr +++ b/src/test/ui/parser/labeled-no-colon-expr.stderr @@ -1,5 +1,5 @@ error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:4:5 + --> $DIR/labeled-no-colon-expr.rs:2:5 | LL | 'l0 while false {} | ----^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | 'l0 while false {} = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:5:5 + --> $DIR/labeled-no-colon-expr.rs:3:5 | LL | 'l1 for _ in 0..1 {} | ----^^^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | 'l1 for _ in 0..1 {} = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:6:5 + --> $DIR/labeled-no-colon-expr.rs:4:5 | LL | 'l2 loop {} | ----^^^^^^^ @@ -32,7 +32,7 @@ LL | 'l2 loop {} = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:7:5 + --> $DIR/labeled-no-colon-expr.rs:5:5 | LL | 'l3 {} | ----^^ @@ -43,7 +43,7 @@ LL | 'l3 {} = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/labeled-no-colon-expr.rs:8:9 + --> $DIR/labeled-no-colon-expr.rs:6:9 | LL | 'l4 0; | ^ expected `while`, `for`, `loop` or `{` after a label @@ -55,7 +55,7 @@ LL + 0; | error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:8:9 + --> $DIR/labeled-no-colon-expr.rs:6:9 | LL | 'l4 0; | ----^ @@ -66,7 +66,7 @@ LL | 'l4 0; = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: cannot use a `block` macro fragment here - --> $DIR/labeled-no-colon-expr.rs:13:17 + --> $DIR/labeled-no-colon-expr.rs:11:17 | LL | 'l5 $b; | ----^^ @@ -79,7 +79,7 @@ LL | m!({}); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:16:8 + --> $DIR/labeled-no-colon-expr.rs:14:8 | LL | 'l5 $b; | ---- help: add `:` after the label diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.fixed b/src/test/ui/parser/recover-labeled-non-block-expr.fixed index fe546a71971..c2e76444d11 100644 --- a/src/test/ui/parser/recover-labeled-non-block-expr.fixed +++ b/src/test/ui/parser/recover-labeled-non-block-expr.fixed @@ -1,5 +1,4 @@ // run-rustfix -#![feature(label_break_value)] fn main() { let _ = 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.rs b/src/test/ui/parser/recover-labeled-non-block-expr.rs index 35862e2eef9..fc11c646a8c 100644 --- a/src/test/ui/parser/recover-labeled-non-block-expr.rs +++ b/src/test/ui/parser/recover-labeled-non-block-expr.rs @@ -1,5 +1,4 @@ // run-rustfix -#![feature(label_break_value)] fn main() { let _ = 'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.stderr b/src/test/ui/parser/recover-labeled-non-block-expr.stderr index 04fc1203e90..d66ce695090 100644 --- a/src/test/ui/parser/recover-labeled-non-block-expr.stderr +++ b/src/test/ui/parser/recover-labeled-non-block-expr.stderr @@ -1,5 +1,5 @@ error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:4:21 + --> $DIR/recover-labeled-non-block-expr.rs:3:21 | LL | let _ = 'label: 1 + 1; | ^ expected `while`, `for`, `loop` or `{` after a label @@ -11,7 +11,7 @@ LL + let _ = 1 + 1; | error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:6:13 + --> $DIR/recover-labeled-non-block-expr.rs:5:13 | LL | 'label: match () { () => {}, }; | ^^^^^ expected `while`, `for`, `loop` or `{` after a label @@ -23,7 +23,7 @@ LL + match () { () => {}, }; | error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:7:13 + --> $DIR/recover-labeled-non-block-expr.rs:6:13 | LL | 'label: match () { () => break 'label, }; | ^^^^^ expected `while`, `for`, `loop` or `{` after a label @@ -34,7 +34,7 @@ LL | 'label: { match () { () => break 'label, } }; | + + error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:9:13 + --> $DIR/recover-labeled-non-block-expr.rs:8:13 | LL | 'label: match () { () => 'lp: loop { break 'lp 0 }, }; | ^^^^^ expected `while`, `for`, `loop` or `{` after a label @@ -45,7 +45,7 @@ LL | 'label: { match () { () => 'lp: loop { break 'lp 0 }, } }; | + + error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:12:22 + --> $DIR/recover-labeled-non-block-expr.rs:11:22 | LL | let _i = 'label: match x { | ^^^^^ expected `while`, `for`, `loop` or `{` after a label @@ -60,7 +60,7 @@ LL ~ } }; | error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:26:24 + --> $DIR/recover-labeled-non-block-expr.rs:25:24 | LL | let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other }); | ^ expected `while`, `for`, `loop` or `{` after a label diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs index 91916e7480f..c3235f06779 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs @@ -1,6 +1,5 @@ #![warn(clippy::semicolon_if_nothing_returned)] #![allow(clippy::redundant_closure)] -#![feature(label_break_value)] #![feature(let_else)] fn get_unit() {} diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr index 41d2c1cfb87..78813e7cc1c 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr @@ -1,5 +1,5 @@ error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:10:5 + --> $DIR/semicolon_if_nothing_returned.rs:9:5 | LL | println!("Hello") | ^^^^^^^^^^^^^^^^^ help: add a `;` here: `println!("Hello");` @@ -7,25 +7,25 @@ LL | println!("Hello") = note: `-D clippy::semicolon-if-nothing-returned` implied by `-D warnings` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:14:5 + --> $DIR/semicolon_if_nothing_returned.rs:13:5 | LL | get_unit() | ^^^^^^^^^^ help: add a `;` here: `get_unit();` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:19:5 + --> $DIR/semicolon_if_nothing_returned.rs:18:5 | LL | y = x + 1 | ^^^^^^^^^ help: add a `;` here: `y = x + 1;` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:25:9 + --> $DIR/semicolon_if_nothing_returned.rs:24:9 | LL | hello() | ^^^^^^^ help: add a `;` here: `hello();` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:36:9 + --> $DIR/semicolon_if_nothing_returned.rs:35:9 | LL | ptr::drop_in_place(s.as_mut_ptr()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());` diff --git a/src/tools/rustfmt/tests/source/issue-3217.rs b/src/tools/rustfmt/tests/source/issue-3217.rs index 176c702002a..e68ca2c5907 100644 --- a/src/tools/rustfmt/tests/source/issue-3217.rs +++ b/src/tools/rustfmt/tests/source/issue-3217.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() { let mut res = 0; 's_39: { if res == 0i32 { println!("Hello, world!"); } } diff --git a/src/tools/rustfmt/tests/target/issue-3217.rs b/src/tools/rustfmt/tests/target/issue-3217.rs index 5121320a097..403bf4c340a 100644 --- a/src/tools/rustfmt/tests/target/issue-3217.rs +++ b/src/tools/rustfmt/tests/target/issue-3217.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() { let mut res = 0; 's_39: { -- cgit 1.4.1-3-g733a5 From d1ef8180f956c9f1a7267e32491d65188f0aefd7 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 20 Aug 2022 20:40:08 +0200 Subject: Revert let_chains stabilization This reverts commit 326646074940222d602f3683d0559088690830f4. This is the revert against master, the beta revert was already done in #100538. --- compiler/rustc_ast/src/lib.rs | 1 + compiler/rustc_ast_lowering/src/lib.rs | 1 + compiler/rustc_ast_passes/src/ast_validation.rs | 28 +- compiler/rustc_ast_passes/src/feature_gate.rs | 1 + compiler/rustc_ast_passes/src/lib.rs | 1 + compiler/rustc_attr/src/lib.rs | 1 + compiler/rustc_borrowck/src/lib.rs | 1 + compiler/rustc_builtin_macros/src/lib.rs | 1 + compiler/rustc_codegen_llvm/src/lib.rs | 1 + compiler/rustc_const_eval/src/lib.rs | 1 + compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_errors/src/lib.rs | 1 + compiler/rustc_expand/src/lib.rs | 1 + compiler/rustc_feature/src/accepted.rs | 2 - compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_infer/src/lib.rs | 1 + compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_metadata/src/lib.rs | 1 + compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_mir_build/src/lib.rs | 1 + compiler/rustc_mir_transform/src/lib.rs | 1 + compiler/rustc_parse/src/lib.rs | 1 + compiler/rustc_parse/src/parser/expr.rs | 28 +- compiler/rustc_passes/src/lib.rs | 1 + compiler/rustc_resolve/src/lib.rs | 1 + compiler/rustc_session/src/lib.rs | 1 + compiler/rustc_trait_selection/src/lib.rs | 1 + compiler/rustc_typeck/src/lib.rs | 1 + library/std/src/lib.rs | 1 + src/librustdoc/lib.rs | 1 + src/test/ui/expr/if/attrs/let-chains-attr.rs | 2 + src/test/ui/expr/if/bad-if-let-suggestion.rs | 1 + src/test/ui/expr/if/bad-if-let-suggestion.stderr | 21 +- src/test/ui/mir/issue-92893.rs | 1 + src/test/ui/mir/issue-92893.stderr | 12 +- src/test/ui/mir/mir_let_chains_drop_order.rs | 1 + src/test/ui/rfc-2294-if-let-guard/feature-gate.rs | 30 +- .../ui/rfc-2294-if-let-guard/feature-gate.stderr | 178 ++++++- .../ui/rfc-2497-if-let-chains/allowed-syntax.rs | 30 -- .../ast-lowering-does-not-wrap-let-chains.rs | 1 + .../rfc-2497-if-let-chains/disallowed-positions.rs | 11 +- .../disallowed-positions.stderr | 564 ++++++++++----------- ...t-let-else-does-not-interact-with-let-chains.rs | 2 +- src/test/ui/rfc-2497-if-let-chains/feature-gate.rs | 62 +++ .../ui/rfc-2497-if-let-chains/feature-gate.stderr | 114 +++++ .../invalid-let-in-a-valid-let-context.rs | 2 + .../invalid-let-in-a-valid-let-context.stderr | 12 +- .../ui/rfc-2497-if-let-chains/irrefutable-lets.rs | 2 +- src/test/ui/rfc-2497-if-let-chains/issue-90722.rs | 2 + src/test/ui/rfc-2497-if-let-chains/issue-92145.rs | 2 + src/test/ui/rfc-2497-if-let-chains/issue-93150.rs | 1 + .../ui/rfc-2497-if-let-chains/issue-93150.stderr | 11 +- .../ui/rfc-2497-if-let-chains/then-else-blocks.rs | 2 +- src/tools/clippy/clippy_dev/src/lib.rs | 1 + src/tools/clippy/clippy_lints/src/lib.rs | 1 + src/tools/clippy/clippy_utils/src/lib.rs | 1 + src/tools/clippy/tests/ui/needless_late_init.fixed | 1 + src/tools/clippy/tests/ui/needless_late_init.rs | 1 + .../clippy/tests/ui/needless_late_init.stderr | 32 +- 59 files changed, 791 insertions(+), 396 deletions(-) delete mode 100644 src/test/ui/rfc-2497-if-let-chains/allowed-syntax.rs create mode 100644 src/test/ui/rfc-2497-if-let-chains/feature-gate.rs create mode 100644 src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr (limited to 'compiler/rustc_parse/src/parser/expr.rs') diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index f9b4d76f28f..27061f300a2 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -14,6 +14,7 @@ #![feature(const_trait_impl)] #![feature(if_let_guard)] #![cfg_attr(bootstrap, feature(label_break_value))] +#![feature(let_chains)] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(slice_internals)] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index becb67d1165..5e9e8aa553d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -31,6 +31,7 @@ //! in the HIR, especially for multiple identifiers. #![feature(box_patterns)] +#![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] #![recursion_limit = "256"] diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b337e5328c5..b46274e4a76 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -119,7 +119,33 @@ impl<'a> AstValidator<'a> { /// Emits an error banning the `let` expression provided in the given location. fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) { - self.session.emit_err(ForbiddenLet { span: expr.span, reason: forbidden_let_reason }); + let sess = &self.session; + if sess.opts.unstable_features.is_nightly_build() { + let err = "`let` expressions are not supported here"; + let mut diag = sess.struct_span_err(expr.span, err); + diag.note("only supported directly in conditions of `if` and `while` expressions"); + match forbidden_let_reason { + ForbiddenLetReason::GenericForbidden => {} + ForbiddenLetReason::NotSupportedOr(span) => { + diag.span_note( + span, + "`||` operators are not supported in let chain expressions", + ); + } + ForbiddenLetReason::NotSupportedParentheses(span) => { + diag.span_note( + span, + "`let`s wrapped in parentheses are not supported in a context with let \ + chains", + ); + } + } + diag.emit(); + } else { + sess.struct_span_err(expr.span, "expected expression, found statement (`let`)") + .note("variable declaration using `let` is a statement") + .emit(); + } } fn check_gat_where( diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 4ac96ec8b60..6f7e88eb86f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -777,6 +777,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { "`if let` guards are experimental", "you can write `if matches!(, )` instead of `if let = `" ); + gate_all!(let_chains, "`let` expressions in this position are unstable"); gate_all!( async_closure, "async closures are unstable", diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 6a826298985..f282ff251bd 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -8,6 +8,7 @@ #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_is_partitioned)] +#![feature(let_chains)] #![feature(let_else)] #![recursion_limit = "256"] diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 3a43f1aad02..053f848aacb 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -4,6 +4,7 @@ //! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax` //! to this crate. +#![feature(let_chains)] #![feature(let_else)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 0f8afb038f4..66fe49e9d12 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2,6 +2,7 @@ #![allow(rustc::potential_query_instability)] #![feature(box_patterns)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 48e81eb13c0..11565ba72d7 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -8,6 +8,7 @@ #![feature(decl_macro)] #![feature(if_let_guard)] #![feature(is_sorted)] +#![feature(let_chains)] #![feature(let_else)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index c80ad692000..636d689a34b 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(hash_raw_entry)] +#![feature(let_chains)] #![feature(let_else)] #![feature(extern_types)] #![feature(once_cell)] diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 7272ae5aa09..72ac6af685d 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -9,6 +9,7 @@ Rust MIR: a lowered representation of Rust. #![feature(control_flow_enum)] #![feature(decl_macro)] #![feature(exact_size_is_empty)] +#![feature(let_chains)] #![feature(let_else)] #![feature(map_try_insert)] #![feature(min_specialization)] diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index b17668dc0ae..d1ac326a72c 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(let_chains)] #![feature(once_cell)] #![feature(rustc_attrs)] #![feature(type_alias_impl_trait)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9b9c334d4df..7b0f4354afd 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,6 +6,7 @@ #![feature(drain_filter)] #![feature(if_let_guard)] #![feature(adt_const_params)] +#![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] #![feature(result_option_inspect)] diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index e1dde1672c1..75dcbd69674 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -2,6 +2,7 @@ #![feature(associated_type_bounds)] #![feature(associated_type_defaults)] #![feature(if_let_guard)] +#![feature(let_chains)] #![feature(let_else)] #![feature(macro_metavar_expr)] #![feature(proc_macro_diagnostic)] diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index fb1ad8d6beb..c22adf77a27 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -188,8 +188,6 @@ declare_features! ( (accepted, item_like_imports, "1.15.0", Some(35120), None), /// Allows `'a: { break 'a; }`. (accepted, label_break_value, "CURRENT_RUSTC_VERSION", Some(48594), None), - /// Allows `if/while p && let q = r && ...` chains. - (accepted, let_chains, "1.64.0", Some(53667), None), /// Allows `break {expr}` with a value inside `loop`s. (accepted, loop_break_value, "1.19.0", Some(37339), None), /// Allows use of `?` as the Kleene "at most one" operator in macros. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 22178dd2123..a5091621f66 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -422,6 +422,8 @@ declare_features! ( (active, isa_attribute, "1.48.0", Some(74727), None), // Allows setting the threshold for the `large_assignments` lint. (active, large_assignments, "1.52.0", Some(83518), None), + /// Allows `if/while p && let q = r && ...` chains. + (active, let_chains, "1.37.0", Some(53667), None), /// Allows `let...else` statements. (active, let_else, "1.56.0", Some(87335), None), /// Allows `#[link(..., cfg(..))]`. diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 602a9ab13f3..931ebca7d01 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -18,6 +18,7 @@ #![feature(control_flow_enum)] #![feature(extend_one)] #![cfg_attr(bootstrap, feature(label_break_value))] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index f34e062fd12..c3065e4a2d9 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -33,6 +33,7 @@ #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(iter_order_by)] +#![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] #![recursion_limit = "256"] diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 75069a5f0dc..6440f3e390c 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -4,6 +4,7 @@ #![feature(generators)] #![feature(generic_associated_types)] #![feature(iter_from_generator)] +#![feature(let_chains)] #![feature(let_else)] #![feature(once_cell)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 6a6505d0256..be9e5865e54 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -39,6 +39,7 @@ #![feature(extern_types)] #![feature(new_uninit)] #![feature(once_cell)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(trusted_len)] diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index e51ca65dc16..11cd2a9aa4d 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -5,6 +5,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(if_let_guard)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(once_cell)] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 56fb601d2b5..75851bf9dfd 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,5 +1,6 @@ #![allow(rustc::potential_query_instability)] #![feature(box_patterns)] +#![feature(let_chains)] #![feature(let_else)] #![feature(map_try_insert)] #![feature(min_specialization)] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 3691d82a835..3c88e1ef377 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -3,6 +3,7 @@ #![feature(array_windows)] #![feature(box_patterns)] #![feature(if_let_guard)] +#![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 18aa109d7a6..c8541609514 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2251,7 +2251,15 @@ impl<'a> Parser<'a> { /// Parses the condition of a `if` or `while` expression. fn parse_cond_expr(&mut self) -> PResult<'a, P> { - self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None) + let cond = + self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?; + + if let ExprKind::Let(..) = cond.kind { + // Remove the last feature gating of a `let` expression since it's stable. + self.sess.gated_spans.ungate_last(sym::let_chains, cond.span); + } + + Ok(cond) } /// Parses a `let $pat = $expr` pseudo-expression. @@ -2280,6 +2288,7 @@ impl<'a> Parser<'a> { this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) })?; let span = lo.to(expr.span); + self.sess.gated_spans.gate(sym::let_chains, span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span))) } @@ -2571,13 +2580,15 @@ impl<'a> Parser<'a> { pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { // Used to check the `let_chains` and `if_let_guard` features mostly by scaning // `&&` tokens. - fn check_let_expr(expr: &Expr) -> bool { + fn check_let_expr(expr: &Expr) -> (bool, bool) { match expr.kind { ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, ref lhs, ref rhs) => { - check_let_expr(lhs) || check_let_expr(rhs) + let lhs_rslt = check_let_expr(lhs); + let rhs_rslt = check_let_expr(rhs); + (lhs_rslt.0 || rhs_rslt.0, false) } - ExprKind::Let(..) => true, - _ => false, + ExprKind::Let(..) => (true, true), + _ => (false, true), } } let attrs = self.parse_outer_attributes()?; @@ -2592,7 +2603,12 @@ impl<'a> Parser<'a> { let guard = if this.eat_keyword(kw::If) { let if_span = this.prev_token.span; let cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?; - if check_let_expr(&cond) { + let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond); + if has_let_expr { + if does_not_have_bin_op { + // Remove the last feature gating of a `let` expression since it's stable. + this.sess.gated_spans.ungate_last(sym::let_chains, cond.span); + } let span = if_span.to(cond.span); this.sess.gated_spans.gate(sym::if_let_guard, span); } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 4af041dac0d..7b2f83958af 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -7,6 +7,7 @@ #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(iter_intersperse)] +#![feature(let_chains)] #![feature(let_else)] #![feature(map_try_insert)] #![feature(min_specialization)] diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index eb727debc91..d91a58b13ff 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -11,6 +11,7 @@ #![feature(drain_filter)] #![feature(if_let_guard)] #![feature(iter_intersperse)] +#![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] #![recursion_limit = "256"] diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 0617bd5fae7..7353c1ca0e2 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,4 +1,5 @@ #![feature(if_let_guard)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index e0dd28bee30..77cc2c164c3 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -17,6 +17,7 @@ #![feature(drain_filter)] #![feature(hash_drain_filter)] #![cfg_attr(bootstrap, feature(label_break_value))] +#![feature(let_chains)] #![feature(let_else)] #![feature(if_let_guard)] #![feature(never_type)] diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 5699f642baf..8e910441a5d 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -65,6 +65,7 @@ This API is completely unstable and subject to change. #![feature(is_sorted)] #![feature(iter_intersperse)] #![cfg_attr(bootstrap, feature(label_break_value))] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f5dcdab4cd5..b0fef492d92 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -254,6 +254,7 @@ #![feature(intra_doc_pointers)] #![cfg_attr(bootstrap, feature(label_break_value))] #![feature(lang_items)] +#![feature(let_chains)] #![feature(let_else)] #![feature(linkage)] #![feature(link_cfg)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8aede1e77a2..92380d12429 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -8,6 +8,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(drain_filter)] +#![feature(let_chains)] #![feature(let_else)] #![feature(test)] #![feature(never_type)] diff --git a/src/test/ui/expr/if/attrs/let-chains-attr.rs b/src/test/ui/expr/if/attrs/let-chains-attr.rs index d62c2cb403f..2cd8731141a 100644 --- a/src/test/ui/expr/if/attrs/let-chains-attr.rs +++ b/src/test/ui/expr/if/attrs/let-chains-attr.rs @@ -1,5 +1,7 @@ // check-pass +#![feature(let_chains)] + #[cfg(FALSE)] fn foo() { #[attr] diff --git a/src/test/ui/expr/if/bad-if-let-suggestion.rs b/src/test/ui/expr/if/bad-if-let-suggestion.rs index 070a5b20128..a8b2a283039 100644 --- a/src/test/ui/expr/if/bad-if-let-suggestion.rs +++ b/src/test/ui/expr/if/bad-if-let-suggestion.rs @@ -4,6 +4,7 @@ fn a() { if let x = 1 && i = 2 {} //~^ ERROR cannot find value `i` in this scope + //~| ERROR `let` expressions in this position are unstable //~| ERROR mismatched types //~| ERROR `let` expressions are not supported here } diff --git a/src/test/ui/expr/if/bad-if-let-suggestion.stderr b/src/test/ui/expr/if/bad-if-let-suggestion.stderr index 9f7a21c7d1a..60d286fedf5 100644 --- a/src/test/ui/expr/if/bad-if-let-suggestion.stderr +++ b/src/test/ui/expr/if/bad-if-let-suggestion.stderr @@ -13,7 +13,7 @@ LL | if let x = 1 && i = 2 {} | ^ not found in this scope error[E0425]: cannot find value `i` in this scope - --> $DIR/bad-if-let-suggestion.rs:12:9 + --> $DIR/bad-if-let-suggestion.rs:13:9 | LL | fn a() { | ------ similarly named function `a` defined here @@ -22,7 +22,7 @@ LL | if (i + j) = i {} | ^ help: a function with a similar name exists: `a` error[E0425]: cannot find value `j` in this scope - --> $DIR/bad-if-let-suggestion.rs:12:13 + --> $DIR/bad-if-let-suggestion.rs:13:13 | LL | fn a() { | ------ similarly named function `a` defined here @@ -31,7 +31,7 @@ LL | if (i + j) = i {} | ^ help: a function with a similar name exists: `a` error[E0425]: cannot find value `i` in this scope - --> $DIR/bad-if-let-suggestion.rs:12:18 + --> $DIR/bad-if-let-suggestion.rs:13:18 | LL | fn a() { | ------ similarly named function `a` defined here @@ -40,7 +40,7 @@ LL | if (i + j) = i {} | ^ help: a function with a similar name exists: `a` error[E0425]: cannot find value `x` in this scope - --> $DIR/bad-if-let-suggestion.rs:19:8 + --> $DIR/bad-if-let-suggestion.rs:20:8 | LL | fn a() { | ------ similarly named function `a` defined here @@ -48,13 +48,22 @@ LL | fn a() { LL | if x[0] = 1 {} | ^ help: a function with a similar name exists: `a` +error[E0658]: `let` expressions in this position are unstable + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + error[E0308]: mismatched types --> $DIR/bad-if-let-suggestion.rs:5:8 | LL | if let x = 1 && i = 2 {} | ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0308, E0425. +Some errors have detailed explanations: E0308, E0425, E0658. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mir/issue-92893.rs b/src/test/ui/mir/issue-92893.rs index c2827c7e37f..635050f376c 100644 --- a/src/test/ui/mir/issue-92893.rs +++ b/src/test/ui/mir/issue-92893.rs @@ -1,5 +1,6 @@ struct Bug { //~^ `let` expressions are not supported here + //~| `let` expressions in this position are unstable [E0658] //~| expected expression, found `let` statement a: A } diff --git a/src/test/ui/mir/issue-92893.stderr b/src/test/ui/mir/issue-92893.stderr index bd4654edf4b..4a0fcce31d7 100644 --- a/src/test/ui/mir/issue-92893.stderr +++ b/src/test/ui/mir/issue-92893.stderr @@ -12,5 +12,15 @@ LL | struct Bug { | = note: only supported directly in conditions of `if` and `while` expressions -error: aborting due to 2 previous errors +error[E0658]: `let` expressions in this position are unstable + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mir/mir_let_chains_drop_order.rs b/src/test/ui/mir/mir_let_chains_drop_order.rs index 21e7b5070af..6498a519571 100644 --- a/src/test/ui/mir/mir_let_chains_drop_order.rs +++ b/src/test/ui/mir/mir_let_chains_drop_order.rs @@ -4,6 +4,7 @@ // See `mir_drop_order.rs` for more information +#![feature(let_chains)] #![allow(irrefutable_let_patterns)] use std::cell::RefCell; diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs index 0fe50932b4b..f0105e08e27 100644 --- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs +++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs @@ -8,35 +8,49 @@ fn _if_let_guard() { //~^ ERROR `if let` guards are experimental () if (let 0 = 1) => {} - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if (((let 0 = 1))) => {} - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if true && let 0 = 1 => {} //~^ ERROR `if let` guards are experimental + //~| ERROR `let` expressions in this position are unstable () if let 0 = 1 && true => {} //~^ ERROR `if let` guards are experimental + //~| ERROR `let` expressions in this position are unstable () if (let 0 = 1) && true => {} - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if true && (let 0 = 1) => {} - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement () if (let 0 = 1) && (let 0 = 1) => {} - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} //~^ ERROR `if let` guards are experimental + //~| ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable //~| ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement () if let Range { start: _, end: _ } = (true..true) && false => {} //~^ ERROR `if let` guards are experimental + //~| ERROR `let` expressions in this position are unstable _ => {} } @@ -52,9 +66,11 @@ fn _macros() { } } use_expr!((let 0 = 1 && 0 == 0)); - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); - //~^ ERROR expected expression, found `let` statement + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement match () { #[cfg(FALSE)] () if let 0 = 1 => {} diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr index 35db84a6cb7..e017d04a5c9 100644 --- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr +++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr @@ -5,67 +5,67 @@ LL | () if (let 0 = 1) => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:13:18 + --> $DIR/feature-gate.rs:14:18 | LL | () if (((let 0 = 1))) => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:22:16 + --> $DIR/feature-gate.rs:26:16 | LL | () if (let 0 = 1) && true => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:25:24 + --> $DIR/feature-gate.rs:30:24 | LL | () if true && (let 0 = 1) => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:28:16 + --> $DIR/feature-gate.rs:34:16 | LL | () if (let 0 = 1) && (let 0 = 1) => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:28:31 + --> $DIR/feature-gate.rs:34:31 | LL | () if (let 0 = 1) && (let 0 = 1) => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:32:42 + --> $DIR/feature-gate.rs:40:42 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:32:55 + --> $DIR/feature-gate.rs:40:55 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:32:68 + --> $DIR/feature-gate.rs:40:68 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:54:16 + --> $DIR/feature-gate.rs:68:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:56:16 + --> $DIR/feature-gate.rs:71:16 | LL | use_expr!((let 0 = 1)); | ^^^ error: no rules expected the token `let` - --> $DIR/feature-gate.rs:64:15 + --> $DIR/feature-gate.rs:80:15 | LL | macro_rules! use_expr { | --------------------- when calling this macro @@ -84,7 +84,7 @@ LL | () if let 0 = 1 => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:16:12 + --> $DIR/feature-gate.rs:18:12 | LL | () if true && let 0 = 1 => {} | ^^^^^^^^^^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | () if true && let 0 = 1 => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:19:12 + --> $DIR/feature-gate.rs:22:12 | LL | () if let 0 = 1 && true => {} | ^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | () if let 0 = 1 && true => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:32:12 + --> $DIR/feature-gate.rs:40:12 | LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -114,7 +114,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:38:12 + --> $DIR/feature-gate.rs:51:12 | LL | () if let Range { start: _, end: _ } = (true..true) && false => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,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:60:12 + --> $DIR/feature-gate.rs:76:12 | LL | () if let 0 = 1 => {} | ^^^^^^^^^^^^ @@ -133,6 +133,150 @@ LL | () if let 0 = 1 => {} = help: add `#![feature(if_let_guard)]` to the crate attributes to enable = help: you can write `if matches!(, )` instead of `if let = ` -error: aborting due to 18 previous errors +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:10:16 + | +LL | () if (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:14:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:18:23 + | +LL | () if true && let 0 = 1 => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:22:15 + | +LL | () if let 0 = 1 && true => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:26:16 + | +LL | () if (let 0 = 1) && true => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:30:24 + | +LL | () if true && (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:34:16 + | +LL | () if (let 0 = 1) && (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:34:31 + | +LL | () if (let 0 = 1) && (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:15 + | +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 + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:28 + | +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 + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:42 + | +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 + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:55 + | +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 + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:68 + | +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 + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:51:15 + | +LL | () if let Range { start: _, end: _ } = (true..true) && false => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:68:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:71:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 34 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2497-if-let-chains/allowed-syntax.rs b/src/test/ui/rfc-2497-if-let-chains/allowed-syntax.rs deleted file mode 100644 index ffe0499fda2..00000000000 --- a/src/test/ui/rfc-2497-if-let-chains/allowed-syntax.rs +++ /dev/null @@ -1,30 +0,0 @@ -// check-pass - -#![allow(irrefutable_let_patterns)] - -use std::ops::Range; - -fn _if() { - if let 0 = 1 {} - - if true && let 0 = 1 {} - - if let 0 = 1 && true {} - - if let Range { start: _, end: _ } = (true..true) && false {} - - if let 1 = 1 && let true = { true } && false { - } -} - -fn _while() { - while let 0 = 1 {} - - while true && let 0 = 1 {} - - while let 0 = 1 && true {} - - while let Range { start: _, end: _ } = (true..true) && false {} -} - -fn main() {} diff --git a/src/test/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs b/src/test/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs index 82164bda489..d851fac8e64 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs +++ b/src/test/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs @@ -1,5 +1,6 @@ // run-pass +#![feature(let_chains)] #![allow(irrefutable_let_patterns)] fn main() { diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs index e8f1ff9c3fd..2a9a5472b2e 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs @@ -17,6 +17,8 @@ // // To that end, we check some positions which is not part of the language above. +#![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test. + #![allow(irrefutable_let_patterns)] use std::ops::Range; @@ -102,12 +104,6 @@ fn _macros() { //~^ ERROR `let` expressions are not supported here //~| ERROR `let` expressions are not supported here //~| ERROR expected expression, found `let` statement - use_expr!(true && let 0 = 1); - //~^ ERROR expected expression, found `let` statement - - macro_rules! noop_expr { ($e:expr) => {}; } - noop_expr!((let 0 = 1)); - //~^ ERROR expected expression, found `let` statement } fn nested_within_if_expr() { @@ -481,7 +477,4 @@ fn with_parenthesis() { ([1, 2, 3][let _ = ()]) //~^ ERROR expected expression, found `let` statement } - - #[cfg(FALSE)] (let 0 = 1); - //~^ ERROR expected expression, found `let` statement } diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index d5d82166a4a..fce0cdfe0d5 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -1,413 +1,413 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:27:9 + --> $DIR/disallowed-positions.rs:29:9 | LL | if (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:31:11 + --> $DIR/disallowed-positions.rs:33:11 | LL | if (((let 0 = 1))) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:35:9 + --> $DIR/disallowed-positions.rs:37:9 | LL | if (let 0 = 1) && true {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:39:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:43:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:43:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:51: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:49:48 + --> $DIR/disallowed-positions.rs:51:48 | 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:49:61 + --> $DIR/disallowed-positions.rs:51:61 | 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:59:12 + --> $DIR/disallowed-positions.rs:61:12 | LL | while (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:63:14 + --> $DIR/disallowed-positions.rs:65:14 | LL | while (((let 0 = 1))) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:67:12 + --> $DIR/disallowed-positions.rs:69:12 | LL | while (let 0 = 1) && true {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:71:20 + --> $DIR/disallowed-positions.rs:73:20 | LL | while true && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:12 + --> $DIR/disallowed-positions.rs:77:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:75:27 + --> $DIR/disallowed-positions.rs:77:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:81:38 + --> $DIR/disallowed-positions.rs:83: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:81:51 + --> $DIR/disallowed-positions.rs:83:51 | 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:81:64 + --> $DIR/disallowed-positions.rs:83:64 | 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:114:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if &let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:9 + --> $DIR/disallowed-positions.rs:115:9 | LL | if !let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:122:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if *let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:126:9 + --> $DIR/disallowed-positions.rs:122:9 | LL | if -let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:136:9 + --> $DIR/disallowed-positions.rs:132:9 | LL | if (let 0 = 0)? {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:16 + --> $DIR/disallowed-positions.rs:138:16 | LL | if true || let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:145:17 + --> $DIR/disallowed-positions.rs:141:17 | LL | if (true || let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:25 + --> $DIR/disallowed-positions.rs:144:25 | LL | if true && (true || let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:151:25 + --> $DIR/disallowed-positions.rs:147:25 | LL | if true || (true && let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:156:12 + --> $DIR/disallowed-positions.rs:152:12 | LL | if x = let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:157:15 | LL | if true..(let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:165:11 + --> $DIR/disallowed-positions.rs:161:11 | LL | if ..(let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:169:9 + --> $DIR/disallowed-positions.rs:165:9 | LL | if (let 0 = 0).. {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:200:19 + --> $DIR/disallowed-positions.rs:196:19 | LL | if let true = let true = true {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:206:12 + --> $DIR/disallowed-positions.rs:202:12 | LL | while &let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:211:12 + --> $DIR/disallowed-positions.rs:207:12 | LL | while !let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:12 + --> $DIR/disallowed-positions.rs:210:12 | LL | while *let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:12 + --> $DIR/disallowed-positions.rs:214:12 | LL | while -let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:228:12 + --> $DIR/disallowed-positions.rs:224:12 | LL | while (let 0 = 0)? {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:234:19 + --> $DIR/disallowed-positions.rs:230:19 | LL | while true || let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:237:20 + --> $DIR/disallowed-positions.rs:233:20 | LL | while (true || let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:240:28 + --> $DIR/disallowed-positions.rs:236:28 | LL | while true && (true || let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:243:28 + --> $DIR/disallowed-positions.rs:239:28 | LL | while true || (true && let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:248:15 + --> $DIR/disallowed-positions.rs:244:15 | LL | while x = let 0 = 0 {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:253:18 + --> $DIR/disallowed-positions.rs:249:18 | LL | while true..(let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:257:14 + --> $DIR/disallowed-positions.rs:253:14 | LL | while ..(let 0 = 0) {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:257:12 | LL | while (let 0 = 0).. {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:22 + --> $DIR/disallowed-positions.rs:288:22 | LL | while let true = let true = true {} | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:308:6 + --> $DIR/disallowed-positions.rs:304:6 | LL | &let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:6 + --> $DIR/disallowed-positions.rs:308:6 | LL | !let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:315:6 + --> $DIR/disallowed-positions.rs:311:6 | LL | *let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:319:6 + --> $DIR/disallowed-positions.rs:315:6 | LL | -let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:329:6 + --> $DIR/disallowed-positions.rs:325:6 | LL | (let 0 = 0)?; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:335:13 + --> $DIR/disallowed-positions.rs:331:13 | LL | true || let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:338:14 + --> $DIR/disallowed-positions.rs:334:14 | LL | (true || let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:341:22 + --> $DIR/disallowed-positions.rs:337:22 | LL | true && (true || let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:9 + --> $DIR/disallowed-positions.rs:342:9 | LL | x = let 0 = 0; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:350:12 + --> $DIR/disallowed-positions.rs:346:12 | LL | true..(let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:353:8 + --> $DIR/disallowed-positions.rs:349:8 | LL | ..(let 0 = 0); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:356:6 + --> $DIR/disallowed-positions.rs:352:6 | LL | (let 0 = 0)..; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:360:6 + --> $DIR/disallowed-positions.rs:356:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:365:6 + --> $DIR/disallowed-positions.rs:361:6 | LL | (let true = let true = true); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:365:17 + --> $DIR/disallowed-positions.rs:361:17 | LL | (let true = let true = true); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:25 + --> $DIR/disallowed-positions.rs:368:25 | LL | let x = true && let y = 1; | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:378:19 + --> $DIR/disallowed-positions.rs:374:19 | LL | [1, 2, 3][let _ = ()] | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:6 + --> $DIR/disallowed-positions.rs:379:6 | LL | &let 0 = 0 | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:395:17 + --> $DIR/disallowed-positions.rs:391:17 | LL | true && let 1 = 1 | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:401:17 + --> $DIR/disallowed-positions.rs:397:17 | LL | true && let 1 = 1 | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:407:17 + --> $DIR/disallowed-positions.rs:403:17 | LL | true && let 1 = 1 | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:419:17 + --> $DIR/disallowed-positions.rs:415:17 | LL | true && let 1 = 1 | ^^^ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:419:9 + --> $DIR/disallowed-positions.rs:415:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -418,389 +418,371 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:429:9 + --> $DIR/disallowed-positions.rs:425:9 | LL | if (let Some(a) = opt && true) { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:434:9 + --> $DIR/disallowed-positions.rs:430:9 | LL | if (let Some(a) = opt) && true { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:438:9 + --> $DIR/disallowed-positions.rs:434:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:438:32 + --> $DIR/disallowed-positions.rs:434:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:447:9 + --> $DIR/disallowed-positions.rs:443:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:447:31 + --> $DIR/disallowed-positions.rs:443:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:453:9 + --> $DIR/disallowed-positions.rs:449:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:453:31 + --> $DIR/disallowed-positions.rs:449:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:459:9 + --> $DIR/disallowed-positions.rs:455:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:476:22 + --> $DIR/disallowed-positions.rs:472:22 | LL | let x = (true && let y = 1); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:481:20 + --> $DIR/disallowed-positions.rs:477:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:485:20 - | -LL | #[cfg(FALSE)] (let 0 = 1); - | ^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:97:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:101:16 + --> $DIR/disallowed-positions.rs:103:16 | LL | use_expr!((let 0 = 1)); | ^^^ -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:105:23 - | -LL | use_expr!(true && let 0 = 1); - | ^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:109:17 - | -LL | noop_expr!((let 0 = 1)); - | ^^^ - error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:27:9 + --> $DIR/disallowed-positions.rs:29: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:27:9 + --> $DIR/disallowed-positions.rs:29:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:31:11 + --> $DIR/disallowed-positions.rs:33: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:31:11 + --> $DIR/disallowed-positions.rs:33:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:35:9 + --> $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:35:9 + --> $DIR/disallowed-positions.rs:37:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:39:17 + --> $DIR/disallowed-positions.rs:41: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:39:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:43:9 + --> $DIR/disallowed-positions.rs:45: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 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:43:24 + --> $DIR/disallowed-positions.rs:45: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 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:49:35 + --> $DIR/disallowed-positions.rs:51: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:49:35 + --> $DIR/disallowed-positions.rs:51:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:49:48 + --> $DIR/disallowed-positions.rs:51: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:49:35 + --> $DIR/disallowed-positions.rs:51:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:49:61 + --> $DIR/disallowed-positions.rs:51: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:49:35 + --> $DIR/disallowed-positions.rs:51:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:59:12 + --> $DIR/disallowed-positions.rs:61: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:59:12 + --> $DIR/disallowed-positions.rs:61:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:63:14 + --> $DIR/disallowed-positions.rs:65: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:63:14 + --> $DIR/disallowed-positions.rs:65:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:67:12 + --> $DIR/disallowed-positions.rs:69: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:67:12 + --> $DIR/disallowed-positions.rs:69:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:71:20 + --> $DIR/disallowed-positions.rs:73: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:71:20 + --> $DIR/disallowed-positions.rs:73:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:75:12 + --> $DIR/disallowed-positions.rs:77: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:75:12 + --> $DIR/disallowed-positions.rs:77:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:75:27 + --> $DIR/disallowed-positions.rs:77: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:75:27 + --> $DIR/disallowed-positions.rs:77:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:81:38 + --> $DIR/disallowed-positions.rs:83: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:81:38 + --> $DIR/disallowed-positions.rs:83:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:81:51 + --> $DIR/disallowed-positions.rs:83: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:81:38 + --> $DIR/disallowed-positions.rs:83:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:81:64 + --> $DIR/disallowed-positions.rs:83: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:81:38 + --> $DIR/disallowed-positions.rs:83:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:97:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^ | = 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:97:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:97:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^ | = 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:97:16 + --> $DIR/disallowed-positions.rs:99:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:101:16 + --> $DIR/disallowed-positions.rs:103:16 | LL | use_expr!((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:101:16 + --> $DIR/disallowed-positions.rs:103:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:101:16 + --> $DIR/disallowed-positions.rs:103:16 | LL | use_expr!((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:101:16 + --> $DIR/disallowed-positions.rs:103:16 | LL | use_expr!((let 0 = 1)); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -808,7 +790,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:119:9 + --> $DIR/disallowed-positions.rs:115:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -816,7 +798,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:122:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -824,7 +806,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:126:9 + --> $DIR/disallowed-positions.rs:122:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -832,72 +814,72 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:136:9 + --> $DIR/disallowed-positions.rs:132:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ | = 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:136:9 + --> $DIR/disallowed-positions.rs:132:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:142:16 + --> $DIR/disallowed-positions.rs:138: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:142:13 + --> $DIR/disallowed-positions.rs:138:13 | LL | if true || let 0 = 0 {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:145:17 + --> $DIR/disallowed-positions.rs:141:17 | 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:145:14 + --> $DIR/disallowed-positions.rs:141:14 | LL | if (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:148:25 + --> $DIR/disallowed-positions.rs:144:25 | LL | if true && (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:148:22 + --> $DIR/disallowed-positions.rs:144:22 | LL | if true && (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:151:25 + --> $DIR/disallowed-positions.rs:147:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ | = 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:151:17 + --> $DIR/disallowed-positions.rs:147:17 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:156:12 + --> $DIR/disallowed-positions.rs:152:12 | LL | if x = let 0 = 0 {} | ^^^^^^^^^ @@ -905,46 +887,46 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:157:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ | = 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:161:15 + --> $DIR/disallowed-positions.rs:157:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:165:11 + --> $DIR/disallowed-positions.rs:161:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ | = 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:165:11 + --> $DIR/disallowed-positions.rs:161:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:169:9 + --> $DIR/disallowed-positions.rs:165:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ | = 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:169:9 + --> $DIR/disallowed-positions.rs:165:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:175:8 + --> $DIR/disallowed-positions.rs:171:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -952,7 +934,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:179:8 + --> $DIR/disallowed-positions.rs:175:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -960,7 +942,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:186:8 + --> $DIR/disallowed-positions.rs:182:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -968,7 +950,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:194:8 + --> $DIR/disallowed-positions.rs:190:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -976,7 +958,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:200:19 + --> $DIR/disallowed-positions.rs:196:19 | LL | if let true = let true = true {} | ^^^^^^^^^^^^^^^ @@ -984,7 +966,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:206:12 + --> $DIR/disallowed-positions.rs:202:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -992,7 +974,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:211:12 + --> $DIR/disallowed-positions.rs:207:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -1000,7 +982,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:214:12 + --> $DIR/disallowed-positions.rs:210:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -1008,7 +990,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:218:12 + --> $DIR/disallowed-positions.rs:214:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -1016,72 +998,72 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:228:12 + --> $DIR/disallowed-positions.rs:224:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ | = 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:228:12 + --> $DIR/disallowed-positions.rs:224:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:234:19 + --> $DIR/disallowed-positions.rs:230: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:234:16 + --> $DIR/disallowed-positions.rs:230:16 | LL | while true || let 0 = 0 {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:237:20 + --> $DIR/disallowed-positions.rs:233:20 | 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:237:17 + --> $DIR/disallowed-positions.rs:233:17 | LL | while (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:240:28 + --> $DIR/disallowed-positions.rs:236:28 | LL | while true && (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:240:25 + --> $DIR/disallowed-positions.rs:236:25 | LL | while true && (true || let 0 = 0) {} | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:243:28 + --> $DIR/disallowed-positions.rs:239:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ | = 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:243:20 + --> $DIR/disallowed-positions.rs:239:20 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:248:15 + --> $DIR/disallowed-positions.rs:244:15 | LL | while x = let 0 = 0 {} | ^^^^^^^^^ @@ -1089,46 +1071,46 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:253:18 + --> $DIR/disallowed-positions.rs:249:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ | = 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:253:18 + --> $DIR/disallowed-positions.rs:249:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:257:14 + --> $DIR/disallowed-positions.rs:253:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ | = 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:257:14 + --> $DIR/disallowed-positions.rs:253:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:257:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ | = 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:261:12 + --> $DIR/disallowed-positions.rs:257:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:267:11 + --> $DIR/disallowed-positions.rs:263:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1136,7 +1118,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:271:11 + --> $DIR/disallowed-positions.rs:267:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1144,7 +1126,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:278:11 + --> $DIR/disallowed-positions.rs:274:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1152,7 +1134,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:286:11 + --> $DIR/disallowed-positions.rs:282:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1160,7 +1142,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:292:22 + --> $DIR/disallowed-positions.rs:288:22 | LL | while let true = let true = true {} | ^^^^^^^^^^^^^^^ @@ -1168,7 +1150,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:308:6 + --> $DIR/disallowed-positions.rs:304:6 | LL | &let 0 = 0; | ^^^^^^^^^ @@ -1176,7 +1158,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:312:6 + --> $DIR/disallowed-positions.rs:308:6 | LL | !let 0 = 0; | ^^^^^^^^^ @@ -1184,7 +1166,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:315:6 + --> $DIR/disallowed-positions.rs:311:6 | LL | *let 0 = 0; | ^^^^^^^^^ @@ -1192,7 +1174,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:319:6 + --> $DIR/disallowed-positions.rs:315:6 | LL | -let 0 = 0; | ^^^^^^^^^ @@ -1200,59 +1182,59 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:329:6 + --> $DIR/disallowed-positions.rs:325:6 | LL | (let 0 = 0)?; | ^^^^^^^^^ | = 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:329:6 + --> $DIR/disallowed-positions.rs:325:6 | LL | (let 0 = 0)?; | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:335:13 + --> $DIR/disallowed-positions.rs:331:13 | LL | 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:335:10 + --> $DIR/disallowed-positions.rs:331:10 | LL | true || let 0 = 0; | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:338:14 + --> $DIR/disallowed-positions.rs:334:14 | LL | (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:338:11 + --> $DIR/disallowed-positions.rs:334:11 | LL | (true || let 0 = 0); | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:341:22 + --> $DIR/disallowed-positions.rs:337:22 | LL | true && (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:341:19 + --> $DIR/disallowed-positions.rs:337:19 | LL | true && (true || let 0 = 0); | ^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:346:9 + --> $DIR/disallowed-positions.rs:342:9 | LL | x = let 0 = 0; | ^^^^^^^^^ @@ -1260,46 +1242,46 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:350:12 + --> $DIR/disallowed-positions.rs:346:12 | LL | true..(let 0 = 0); | ^^^^^^^^^ | = 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:350:12 + --> $DIR/disallowed-positions.rs:346:12 | LL | true..(let 0 = 0); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:353:8 + --> $DIR/disallowed-positions.rs:349:8 | LL | ..(let 0 = 0); | ^^^^^^^^^ | = 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:353:8 + --> $DIR/disallowed-positions.rs:349:8 | LL | ..(let 0 = 0); | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:356:6 + --> $DIR/disallowed-positions.rs:352:6 | LL | (let 0 = 0)..; | ^^^^^^^^^ | = 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:356:6 + --> $DIR/disallowed-positions.rs:352:6 | LL | (let 0 = 0)..; | ^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:360:6 + --> $DIR/disallowed-positions.rs:356:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1307,20 +1289,20 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:365:6 + --> $DIR/disallowed-positions.rs:361:6 | LL | (let true = let 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:365:6 + --> $DIR/disallowed-positions.rs:361:6 | LL | (let true = let true = true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:383:6 + --> $DIR/disallowed-positions.rs:379:6 | LL | &let 0 = 0 | ^^^^^^^^^ @@ -1328,7 +1310,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:395:17 + --> $DIR/disallowed-positions.rs:391:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -1336,7 +1318,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:401:17 + --> $DIR/disallowed-positions.rs:397:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -1344,7 +1326,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:407:17 + --> $DIR/disallowed-positions.rs:403:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -1352,7 +1334,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:419:17 + --> $DIR/disallowed-positions.rs:415:17 | LL | true && let 1 = 1 | ^^^^^^^^^ @@ -1360,124 +1342,124 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:429:9 + --> $DIR/disallowed-positions.rs:425: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:429:9 + --> $DIR/disallowed-positions.rs:425:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:434:9 + --> $DIR/disallowed-positions.rs:430: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:434:9 + --> $DIR/disallowed-positions.rs:430:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:438:9 + --> $DIR/disallowed-positions.rs:434: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:438:9 + --> $DIR/disallowed-positions.rs:434:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:438:32 + --> $DIR/disallowed-positions.rs:434: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:438:32 + --> $DIR/disallowed-positions.rs:434:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:447:9 + --> $DIR/disallowed-positions.rs:443: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:447:9 + --> $DIR/disallowed-positions.rs:443:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:447:31 + --> $DIR/disallowed-positions.rs:443: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:447:31 + --> $DIR/disallowed-positions.rs:443:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:453:9 + --> $DIR/disallowed-positions.rs:449: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:453:9 + --> $DIR/disallowed-positions.rs:449:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:453:31 + --> $DIR/disallowed-positions.rs:449: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:453:31 + --> $DIR/disallowed-positions.rs:449:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: `let` expressions are not supported here - --> $DIR/disallowed-positions.rs:459:9 + --> $DIR/disallowed-positions.rs:455: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:459:9 + --> $DIR/disallowed-positions.rs:455:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:114:8 + --> $DIR/disallowed-positions.rs:110:8 | LL | if &let 0 = 0 {} | ^^^^^^^^^^ expected `bool`, found `&bool` @@ -1489,19 +1471,19 @@ LL + if let 0 = 0 {} | error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:122:8 + --> $DIR/disallowed-positions.rs:118:8 | LL | if *let 0 = 0 {} | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:126:8 + --> $DIR/disallowed-positions.rs:122:8 | LL | if -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:136:8 + --> $DIR/disallowed-positions.rs:132:8 | LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1509,7 +1491,7 @@ LL | if (let 0 = 0)? {} = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:136:19 + --> $DIR/disallowed-positions.rs:132:19 | LL | / fn nested_within_if_expr() { LL | | if &let 0 = 0 {} @@ -1526,7 +1508,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:156:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if x = let 0 = 0 {} | ^^^^^^^^^^^^^ expected `bool`, found `()` @@ -1537,7 +1519,7 @@ LL | if x == let 0 = 0 {} | ~~ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:161:8 + --> $DIR/disallowed-positions.rs:157:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1546,7 +1528,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:165:8 + --> $DIR/disallowed-positions.rs:161:8 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo` @@ -1555,7 +1537,7 @@ LL | if ..(let 0 = 0) {} found struct `RangeTo` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:169:8 + --> $DIR/disallowed-positions.rs:165:8 | LL | if (let 0 = 0).. {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom` @@ -1564,7 +1546,7 @@ LL | if (let 0 = 0).. {} found struct `RangeFrom` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:175:12 + --> $DIR/disallowed-positions.rs:171:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1575,7 +1557,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:175:8 + --> $DIR/disallowed-positions.rs:171:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1584,7 +1566,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:179:12 + --> $DIR/disallowed-positions.rs:175:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1595,7 +1577,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:179:8 + --> $DIR/disallowed-positions.rs:175:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1604,7 +1586,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:186:12 + --> $DIR/disallowed-positions.rs:182:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1615,20 +1597,20 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:186:41 + --> $DIR/disallowed-positions.rs:182:41 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/disallowed-positions.rs:186:41: 186:43]` + found closure `[closure@$DIR/disallowed-positions.rs:182:41: 182:43]` help: use parentheses to call this closure | LL | if let Range { start: F, end } = F..(|| true)() {} | + +++ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:186:8 + --> $DIR/disallowed-positions.rs:182:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1637,7 +1619,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:194:12 + --> $DIR/disallowed-positions.rs:190:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1648,7 +1630,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:194:44 + --> $DIR/disallowed-positions.rs:190:44 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^ expected `bool`, found `&&bool` @@ -1660,7 +1642,7 @@ LL + if let Range { start: true, end } = t..false {} | error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:194:8 + --> $DIR/disallowed-positions.rs:190:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1669,7 +1651,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:132:20 + --> $DIR/disallowed-positions.rs:128:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1677,7 +1659,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:206:11 + --> $DIR/disallowed-positions.rs:202:11 | LL | while &let 0 = 0 {} | ^^^^^^^^^^ expected `bool`, found `&bool` @@ -1689,19 +1671,19 @@ LL + while let 0 = 0 {} | error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:214:11 + --> $DIR/disallowed-positions.rs:210:11 | LL | while *let 0 = 0 {} | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:218:11 + --> $DIR/disallowed-positions.rs:214:11 | LL | while -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:228:11 + --> $DIR/disallowed-positions.rs:224:11 | LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1709,7 +1691,7 @@ LL | while (let 0 = 0)? {} = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:228:22 + --> $DIR/disallowed-positions.rs:224:22 | LL | / fn nested_within_while_expr() { LL | | while &let 0 = 0 {} @@ -1726,7 +1708,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:248:11 + --> $DIR/disallowed-positions.rs:244:11 | LL | while x = let 0 = 0 {} | ^^^^^^^^^^^^^ expected `bool`, found `()` @@ -1737,7 +1719,7 @@ LL | while x == let 0 = 0 {} | ~~ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:253:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1746,7 +1728,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:257:11 + --> $DIR/disallowed-positions.rs:253:11 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo` @@ -1755,7 +1737,7 @@ LL | while ..(let 0 = 0) {} found struct `RangeTo` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:261:11 + --> $DIR/disallowed-positions.rs:257:11 | LL | while (let 0 = 0).. {} | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom` @@ -1764,7 +1746,7 @@ LL | while (let 0 = 0).. {} found struct `RangeFrom` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:267:15 + --> $DIR/disallowed-positions.rs:263:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1775,7 +1757,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:267:11 + --> $DIR/disallowed-positions.rs:263:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1784,7 +1766,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:271:15 + --> $DIR/disallowed-positions.rs:267:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1795,7 +1777,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:271:11 + --> $DIR/disallowed-positions.rs:267:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1804,7 +1786,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:278:15 + --> $DIR/disallowed-positions.rs:274:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1815,20 +1797,20 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:278:44 + --> $DIR/disallowed-positions.rs:274:44 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^ expected `bool`, found closure | = note: expected type `bool` - found closure `[closure@$DIR/disallowed-positions.rs:278:44: 278:46]` + found closure `[closure@$DIR/disallowed-positions.rs:274:44: 274:46]` help: use parentheses to call this closure | LL | while let Range { start: F, end } = F..(|| true)() {} | + +++ error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:278:11 + --> $DIR/disallowed-positions.rs:274:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1837,7 +1819,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:286:15 + --> $DIR/disallowed-positions.rs:282:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1848,7 +1830,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:286:47 + --> $DIR/disallowed-positions.rs:282:47 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^ expected `bool`, found `&&bool` @@ -1860,7 +1842,7 @@ LL + while let Range { start: true, end } = t..false {} | error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:286:11 + --> $DIR/disallowed-positions.rs:282:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` @@ -1869,7 +1851,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:224:23 + --> $DIR/disallowed-positions.rs:220:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1877,19 +1859,19 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0614]: type `bool` cannot be dereferenced - --> $DIR/disallowed-positions.rs:315:5 + --> $DIR/disallowed-positions.rs:311:5 | LL | *let 0 = 0; | ^^^^^^^^^^ error[E0600]: cannot apply unary operator `-` to type `bool` - --> $DIR/disallowed-positions.rs:319:5 + --> $DIR/disallowed-positions.rs:315:5 | LL | -let 0 = 0; | ^^^^^^^^^^ cannot apply unary operator `-` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:329:5 + --> $DIR/disallowed-positions.rs:325:5 | LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` @@ -1897,7 +1879,7 @@ LL | (let 0 = 0)?; = help: the trait `Try` is not implemented for `bool` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/disallowed-positions.rs:329:16 + --> $DIR/disallowed-positions.rs:325:16 | LL | / fn outside_if_and_while_expr() { LL | | &let 0 = 0; @@ -1914,7 +1896,7 @@ LL | | } = help: the trait `FromResidual<_>` is not implemented for `()` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:360:10 + --> $DIR/disallowed-positions.rs:356:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1925,7 +1907,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:383:5 + --> $DIR/disallowed-positions.rs:379:5 | LL | fn outside_if_and_while_expr() { | - help: try adding a return type: `-> &bool` @@ -1934,14 +1916,14 @@ LL | &let 0 = 0 | ^^^^^^^^^^ expected `()`, found `&bool` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:325:17 + --> $DIR/disallowed-positions.rs:321: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 218 previous errors +error: aborting due to 215 previous errors Some errors have detailed explanations: E0277, E0308, E0600, E0614. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs index deef4240d4d..12befc637c7 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs +++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs @@ -1,4 +1,4 @@ -#![feature(let_else)] +#![feature(let_chains, let_else)] fn main() { let opt = Some(1i32); diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs new file mode 100644 index 00000000000..2b407ef510c --- /dev/null +++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs @@ -0,0 +1,62 @@ +// gate-test-let_chains + +// Here we test feature gating for ´let_chains`. +// See `disallowed-positions.rs` for the grammar +// defining the language for gated allowed positions. + +#![allow(irrefutable_let_patterns)] + +use std::ops::Range; + +fn _if() { + if let 0 = 1 {} // Stable! + + if true && let 0 = 1 {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + if let 0 = 1 && true {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + if let Range { start: _, end: _ } = (true..true) && false {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + if let 1 = 1 && let true = { true } && false { + //~^ ERROR `let` expressions in this position are unstable [E0658] + //~| ERROR `let` expressions in this position are unstable [E0658] + } +} + +fn _while() { + while let 0 = 1 {} // Stable! + + while true && let 0 = 1 {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + while let 0 = 1 && true {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + while let Range { start: _, end: _ } = (true..true) && false {} + //~^ ERROR `let` expressions in this position are unstable [E0658] +} + +fn _macros() { + macro_rules! noop_expr { ($e:expr) => {}; } + + noop_expr!((let 0 = 1)); + //~^ ERROR `let` expressions in this position are unstable [E0658] + //~| ERROR expected expression, found `let` statement + + macro_rules! use_expr { + ($e:expr) => { + if $e {} + while $e {} + } + } + #[cfg(FALSE)] (let 0 = 1); + //~^ ERROR `let` expressions in this position are unstable [E0658] + //~| ERROR expected expression, found `let` statement + use_expr!(let 0 = 1); + //~^ ERROR no rules expected the token `let` +} + +fn main() {} diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr new file mode 100644 index 00000000000..feea1c254d8 --- /dev/null +++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr @@ -0,0 +1,114 @@ +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:55:20 + | +LL | #[cfg(FALSE)] (let 0 = 1); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:45:17 + | +LL | noop_expr!((let 0 = 1)); + | ^^^ + +error: no rules expected the token `let` + --> $DIR/feature-gate.rs:58:15 + | +LL | macro_rules! use_expr { + | --------------------- when calling this macro +... +LL | use_expr!(let 0 = 1); + | ^^^ no rules expected this token in macro call + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:14:16 + | +LL | if true && let 0 = 1 {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:17:8 + | +LL | if let 0 = 1 && true {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:20:8 + | +LL | if let Range { start: _, end: _ } = (true..true) && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:23:8 + | +LL | if let 1 = 1 && let true = { true } && false { + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:23:21 + | +LL | if let 1 = 1 && let true = { true } && false { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:32:19 + | +LL | while true && let 0 = 1 {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:35:11 + | +LL | while let 0 = 1 && true {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:38:11 + | +LL | while let Range { start: _, end: _ } = (true..true) && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:55:20 + | +LL | #[cfg(FALSE)] (let 0 = 1); + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:45:17 + | +LL | noop_expr!((let 0 = 1)); + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs index 7bc6d43a727..a942d1f4caf 100644 --- a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs +++ b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs @@ -1,3 +1,5 @@ +#![feature(let_chains)] + fn main() { let _opt = Some(1i32); diff --git a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr index d1552a0b2d5..d1ce83c7233 100644 --- a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr @@ -1,35 +1,35 @@ error: expected expression, found `let` statement - --> $DIR/invalid-let-in-a-valid-let-context.rs:6:19 + --> $DIR/invalid-let-in-a-valid-let-context.rs:8:19 | LL | let _ = &&let Some(x) = Some(42); | ^^^ error: expected expression, found `let` statement - --> $DIR/invalid-let-in-a-valid-let-context.rs:11:47 + --> $DIR/invalid-let-in-a-valid-let-context.rs:13:47 | LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { | ^^^ error: expected expression, found `let` statement - --> $DIR/invalid-let-in-a-valid-let-context.rs:11:57 + --> $DIR/invalid-let-in-a-valid-let-context.rs:13:57 | LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { | ^^^ error: expected expression, found `let` statement - --> $DIR/invalid-let-in-a-valid-let-context.rs:21:23 + --> $DIR/invalid-let-in-a-valid-let-context.rs:23:23 | LL | [1, 2, 3][let _ = ()]; | ^^^ error: expected expression, found `let` statement - --> $DIR/invalid-let-in-a-valid-let-context.rs:30:47 + --> $DIR/invalid-let-in-a-valid-let-context.rs:32:47 | LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 { | ^^^ error: expected expression, found `let` statement - --> $DIR/invalid-let-in-a-valid-let-context.rs:38:21 + --> $DIR/invalid-let-in-a-valid-let-context.rs:40:21 | LL | let x = let y = 1; | ^^^ diff --git a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs index 1ef4bc56e52..3d1626e8ffb 100644 --- a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs +++ b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs @@ -1,7 +1,7 @@ // revisions: allowed disallowed //[allowed] check-pass -#![feature(if_let_guard)] +#![feature(if_let_guard, let_chains)] #![cfg_attr(allowed, allow(irrefutable_let_patterns))] #![cfg_attr(disallowed, deny(irrefutable_let_patterns))] diff --git a/src/test/ui/rfc-2497-if-let-chains/issue-90722.rs b/src/test/ui/rfc-2497-if-let-chains/issue-90722.rs index 34302ba96d3..6b7d8835650 100644 --- a/src/test/ui/rfc-2497-if-let-chains/issue-90722.rs +++ b/src/test/ui/rfc-2497-if-let-chains/issue-90722.rs @@ -1,5 +1,7 @@ // check-pass +#![feature(let_chains)] + fn main() { let x = Some(vec!["test"]); diff --git a/src/test/ui/rfc-2497-if-let-chains/issue-92145.rs b/src/test/ui/rfc-2497-if-let-chains/issue-92145.rs index 6938062fa35..7c7e31f4db4 100644 --- a/src/test/ui/rfc-2497-if-let-chains/issue-92145.rs +++ b/src/test/ui/rfc-2497-if-let-chains/issue-92145.rs @@ -1,5 +1,7 @@ // check-pass +#![feature(let_chains)] + fn main() { let opt = Some("foo bar"); diff --git a/src/test/ui/rfc-2497-if-let-chains/issue-93150.rs b/src/test/ui/rfc-2497-if-let-chains/issue-93150.rs index f6de37867d8..f90b9ab0d40 100644 --- a/src/test/ui/rfc-2497-if-let-chains/issue-93150.rs +++ b/src/test/ui/rfc-2497-if-let-chains/issue-93150.rs @@ -2,6 +2,7 @@ fn main() { match true { _ if let true = true && true => {} //~^ ERROR `if let` guards are + //~| ERROR `let` expressions in this _ => {} } } diff --git a/src/test/ui/rfc-2497-if-let-chains/issue-93150.stderr b/src/test/ui/rfc-2497-if-let-chains/issue-93150.stderr index 0d620df96f6..b25f299a219 100644 --- a/src/test/ui/rfc-2497-if-let-chains/issue-93150.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/issue-93150.stderr @@ -8,6 +8,15 @@ LL | _ if let true = true && true => {} = help: add `#![feature(if_let_guard)]` to the crate attributes to enable = help: you can write `if matches!(, )` instead of `if let = ` -error: aborting due to previous error +error[E0658]: `let` expressions in this position are unstable + --> $DIR/issue-93150.rs:3:14 + | +LL | _ if let true = true && true => {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2497-if-let-chains/then-else-blocks.rs b/src/test/ui/rfc-2497-if-let-chains/then-else-blocks.rs index beaca33d563..e061174f667 100644 --- a/src/test/ui/rfc-2497-if-let-chains/then-else-blocks.rs +++ b/src/test/ui/rfc-2497-if-let-chains/then-else-blocks.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(if_let_guard)] +#![feature(if_let_guard, let_chains)] fn check_if_let(opt: Option>>, value: i32) -> bool { if let Some(first) = opt diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index 8a6bd1cbdf5..82574a8e64b 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(let_chains)] #![feature(let_else)] #![feature(once_cell)] #![feature(rustc_private)] diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index e6a405f8170..ec5c73c1357 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -4,6 +4,7 @@ #![feature(control_flow_enum)] #![feature(drain_filter)] #![feature(iter_intersperse)] +#![feature(let_chains)] #![feature(let_else)] #![feature(lint_reasons)] #![feature(never_type)] diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index f716f009ff3..313f1f1d9a6 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2,6 +2,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(let_else)] +#![feature(let_chains)] #![feature(lint_reasons)] #![feature(once_cell)] #![feature(rustc_private)] diff --git a/src/tools/clippy/tests/ui/needless_late_init.fixed b/src/tools/clippy/tests/ui/needless_late_init.fixed index 4c98e1827bd..fee8e3030b8 100644 --- a/src/tools/clippy/tests/ui/needless_late_init.fixed +++ b/src/tools/clippy/tests/ui/needless_late_init.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![feature(let_chains)] #![allow( unused, clippy::assign_op_pattern, diff --git a/src/tools/clippy/tests/ui/needless_late_init.rs b/src/tools/clippy/tests/ui/needless_late_init.rs index 25e1e0214fb..402d9f9ef7f 100644 --- a/src/tools/clippy/tests/ui/needless_late_init.rs +++ b/src/tools/clippy/tests/ui/needless_late_init.rs @@ -1,4 +1,5 @@ // run-rustfix +#![feature(let_chains)] #![allow( unused, clippy::assign_op_pattern, diff --git a/src/tools/clippy/tests/ui/needless_late_init.stderr b/src/tools/clippy/tests/ui/needless_late_init.stderr index 97f0f7019a9..313cdbbeba1 100644 --- a/src/tools/clippy/tests/ui/needless_late_init.stderr +++ b/src/tools/clippy/tests/ui/needless_late_init.stderr @@ -1,5 +1,5 @@ error: unneeded late initialization - --> $DIR/needless_late_init.rs:22:5 + --> $DIR/needless_late_init.rs:23:5 | LL | let a; | ^^^^^^ created here @@ -13,7 +13,7 @@ LL | let a = "zero"; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:25:5 + --> $DIR/needless_late_init.rs:26:5 | LL | let b; | ^^^^^^ created here @@ -27,7 +27,7 @@ LL | let b = 1; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:26:5 + --> $DIR/needless_late_init.rs:27:5 | LL | let c; | ^^^^^^ created here @@ -41,7 +41,7 @@ LL | let c = 2; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:30:5 + --> $DIR/needless_late_init.rs:31:5 | LL | let d: usize; | ^^^^^^^^^^^^^ created here @@ -54,7 +54,7 @@ LL | let d: usize = 1; | ~~~~~~~~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:33:5 + --> $DIR/needless_late_init.rs:34:5 | LL | let e; | ^^^^^^ created here @@ -67,7 +67,7 @@ LL | let e = format!("{}", d); | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:38:5 + --> $DIR/needless_late_init.rs:39:5 | LL | let a; | ^^^^^^ @@ -88,7 +88,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:47:5 + --> $DIR/needless_late_init.rs:48:5 | LL | let b; | ^^^^^^ @@ -109,7 +109,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:54:5 + --> $DIR/needless_late_init.rs:55:5 | LL | let d; | ^^^^^^ @@ -130,7 +130,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:62:5 + --> $DIR/needless_late_init.rs:63:5 | LL | let e; | ^^^^^^ @@ -151,7 +151,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:69:5 + --> $DIR/needless_late_init.rs:70:5 | LL | let f; | ^^^^^^ @@ -167,7 +167,7 @@ LL + 1 => "three", | error: unneeded late initialization - --> $DIR/needless_late_init.rs:75:5 + --> $DIR/needless_late_init.rs:76:5 | LL | let g: usize; | ^^^^^^^^^^^^^ @@ -187,7 +187,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:83:5 + --> $DIR/needless_late_init.rs:84:5 | LL | let x; | ^^^^^^ created here @@ -201,7 +201,7 @@ LL | let x = 1; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:87:5 + --> $DIR/needless_late_init.rs:88:5 | LL | let x; | ^^^^^^ created here @@ -215,7 +215,7 @@ LL | let x = SignificantDrop; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:91:5 + --> $DIR/needless_late_init.rs:92:5 | LL | let x; | ^^^^^^ created here @@ -229,7 +229,7 @@ LL | let x = SignificantDrop; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:110:5 + --> $DIR/needless_late_init.rs:111:5 | LL | let a; | ^^^^^^ @@ -250,7 +250,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:127:5 + --> $DIR/needless_late_init.rs:128:5 | LL | let a; | ^^^^^^ -- cgit 1.4.1-3-g733a5