diff --git a/Cargo.lock b/Cargo.lock index 0b47aae128338..27ebe6d13c2c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5178,7 +5178,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.11.0" +version = "1.12.0" dependencies = [ "annotate-snippets 0.12.16", "anyhow", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index b3b85655bb261..ffe9b79b4942d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1779,7 +1779,7 @@ pub enum ExprKind { Lit(token::Lit), /// A cast (e.g., `foo as f64`). Cast(Box, Box), - /// A type ascription (e.g., `builtin # type_ascribe(42, usize)`). + /// A type ascription (e.g., `k#type_ascribe(42, usize)`). /// /// Usually not written directly in user code but /// indirectly via the macro `type_ascribe!(...)`. @@ -1871,7 +1871,7 @@ pub enum ExprKind { /// Output of the `asm!()` macro. InlineAsm(Box), - /// An `offset_of` expression (e.g., `builtin # offset_of(Struct, field)`). + /// An `offset_of` expression (e.g., `k#offset_of(Struct, field)`). /// /// Usually not written directly in user code but /// indirectly via the macro `core::mem::offset_of!(...)`. @@ -2570,7 +2570,7 @@ pub enum TyKind { /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero`, /// just as part of the type system. Pat(Box, Box), - /// A `field_of` expression (e.g., `builtin # field_of(Struct, field)`). + /// A `field_of` expression (e.g., `k#field_of(Struct, field)`). /// /// Usually not written directly in user code but indirectly via the macro /// `core::field::field_of!(...)`. diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 20079dd039f6f..4ec5fe2a8bd84 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -313,6 +313,8 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, kind: IdentKind) -> bool { // WARNING: Take care when modifying this function! It will change the stable(!) set of // tokens that are allowed to match an `expr` nonterminal which is user observable. + // NOTE: We don't care about forced keywords that are gated behind `internal_syntax`. + let ident_token = Token::new(Ident(name, kind), span); // FIXME: Remove `box` from this list given we officially no longer support box expressions @@ -350,6 +352,8 @@ fn ident_can_begin_type(name: Symbol, span: Span, kind: IdentKind) -> bool { // WARNING: Take care when modifying this function! It will change the stable(!) set of // tokens that are allowed to match an `ty` nonterminal which is user observable. + // NOTE: We don't care about forced keywords that are gated behind `internal_syntax`. + let ident_token = Token::new(Ident(name, kind), span); !ident_token.is_reserved_ident() @@ -936,6 +940,10 @@ impl Token { self.non_raw_ident().is_some_and(|id| id.name == kw) } + pub fn is_forced_keyword(&self, kw: Symbol) -> bool { + self.ident().is_some_and(|(id, kind)| kind == IdentKind::ForcedKeyword && id.name == kw) + } + /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this /// token is an identifier equal to `kw` ignoring the case. pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index bc0604cf96e95..862d4736ca33c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -431,7 +431,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { // tidy-alphabetical-start gate_all!(async_for_loop, "`for await` loops are experimental"); - gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); gate_all!(const_block_items, "const block items are experimental"); gate_all!(const_closures, "const closures are experimental"); gate_all!(const_trait_impl, "const trait impls are experimental"); @@ -452,6 +451,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(global_registration, "global registration is experimental"); gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards"); gate_all!(impl_restriction, "`impl` restrictions are experimental"); + gate_all!(internal_syntax, "this syntax is internal"); gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); gate_all!(move_expr, "`move(expr)` syntax is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a082300bb47ed..a5dbaf81376c1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1442,7 +1442,7 @@ impl<'a> State<'a> { self.print_ty_pat(pat); } ast::TyKind::FieldOf(ty, variant, field) => { - self.word("builtin # field_of"); + self.word("k#field_of"); self.popen(); let ib = self.ibox(0); self.print_type(ty); @@ -2012,6 +2012,11 @@ impl<'a> State<'a> { self.pclose(); } PatKind::Deref(inner) => { + // FIXME(deref_patterns, internal_syntax, forced_keywords, clippy): + // This should render `k#deref(...)` but unfortunately Clippy uses `pat_to_string` + // for the suggestions of its lint `unnested_or_patterns`. Smh fix Clippy to not + // rely on AST pretty printing `deref!(…)` for `Deref` patterns and please don't + // think about adding a flag to AST pretty to control the output. self.word("deref!"); self.popen(); self.print_pat(inner); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index d6e8f69dbfa03..51e3988577827 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -497,7 +497,7 @@ impl<'a> State<'a> { self.print_type(ty); } ast::ExprKind::Type(expr, ty) => { - self.word("builtin # type_ascribe"); + self.word("k#type_ascribe"); self.popen(); let ib = self.ibox(0); self.print_expr(expr, FixupContext::default()); @@ -777,12 +777,12 @@ impl<'a> State<'a> { self.print_expr(result, fixup.rightmost_subexpression()); } ast::ExprKind::InlineAsm(a) => { - // FIXME: Print `builtin # asm` once macro `asm` uses `builtin_syntax`. + // FIXME: Print `k#asm` once macro `asm` uses `internal_syntax`. self.word(format!("{}!", a.asm_macro.macro_name())); self.print_inline_asm(a); } ast::ExprKind::FormatArgs(fmt) => { - // FIXME: Print `builtin # format_args` once macro `format_args` uses `builtin_syntax`. + // FIXME: Print `k#format_args` once macro `format_args` uses `internal_syntax`. self.word("format_args!"); self.popen(); let ib = self.ibox(0); @@ -795,7 +795,7 @@ impl<'a> State<'a> { self.pclose(); } ast::ExprKind::OffsetOf(container, fields) => { - self.word("builtin # offset_of"); + self.word("k#offset_of"); self.popen(); let ib = self.ibox(0); self.print_type(container); @@ -855,10 +855,9 @@ impl<'a> State<'a> { self.print_block_with_attrs(blk, attrs, cb, ib) } ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => { - self.word("builtin # "); match kind { - ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"), - ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"), + ast::UnsafeBinderCastKind::Wrap => self.word("k#wrap_binder"), + ast::UnsafeBinderCastKind::Unwrap => self.word("k#unwrap_binder"), } self.popen(); let ib = self.ibox(0); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 6ce34cecc7e97..84d620b9b5250 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -288,7 +288,7 @@ impl<'a> State<'a> { self.bclose(item.span, empty, cb); } ast::ItemKind::GlobalAsm(asm) => { - // FIXME: Print `builtin # global_asm` once macro `global_asm` uses `builtin_syntax`. + // FIXME: Print `k#global_asm` once macro `global_asm` uses `internal_syntax`. let (cb, ib) = self.head(visibility_qualified(&item.vis, "global_asm!")); self.print_inline_asm(asm); self.word(";"); diff --git a/compiler/rustc_attr_ir/src/lang_items.rs b/compiler/rustc_attr_ir/src/lang_items.rs index d715a6d3af8c5..56fb1a4b6c865 100644 --- a/compiler/rustc_attr_ir/src/lang_items.rs +++ b/compiler/rustc_attr_ir/src/lang_items.rs @@ -163,7 +163,7 @@ language_item_table! { Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); AlignOf, sym::mem_align_const, align_const, Target::AssocConst(AssocCtxt::Trait), GenericRequirement::Exact(0); SizeOf, sym::mem_size_const, size_const, Target::AssocConst(AssocCtxt::Trait), GenericRequirement::Exact(0); - OffsetOf, sym::offset_of, offset_of, Target::Fn, GenericRequirement::Exact(1); + OffsetOf, kw::OffsetOf, offset_of, Target::Fn, GenericRequirement::Exact(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None; Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0); @@ -239,7 +239,7 @@ language_item_table! { Complex, sym::complex, complex, Target::Struct, GenericRequirement::Exact(1); PpcF128, sym::ppcf128, ppcf128, Target::Struct, GenericRequirement::None; - Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); + Deref, kw::Deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0); DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0); DerefTarget, sym::deref_target, deref_target, Target::AssocTy(AssocCtxt::Trait), GenericRequirement::None; diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 941af4a4ab01d..95ca582e011df 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_targ use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{Symbol, bug, span_bug, sym}; +use rustc_span::{Symbol, bug, kw, span_bug, sym}; use tracing::trace; use super::memory::MemoryKind; @@ -231,7 +231,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = layout.align.bytes(); self.write_scalar(Scalar::from_target_usize(val, self), dest)?; } - sym::offset_of => { + kw::OffsetOf => { let tp_ty = instance.args.type_at(0); let variant = self.read_scalar(&args[0])?.to_u32()?; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 468a13ad4fd61..cbaf7cba40ba7 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -301,8 +301,6 @@ declare_features! ( /// Allows features specific to auto traits. /// Renamed from `optin_builtin_traits`. (unstable, auto_traits, "1.50.0", Some(13231)), - /// Allows builtin # foo() syntax - (internal, builtin_syntax, "1.71.0", Some(110680)), /// Allows `#[doc(notable_trait)]`. /// Renamed from `doc_spotlight`. (unstable, doc_notable_trait, "1.52.0", Some(45040)), @@ -310,6 +308,8 @@ declare_features! ( (unstable, dropck_eyepatch, "1.10.0", Some(34761)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), + /// Allows internal syntax. + (internal, internal_syntax, "CURRENT_RUSTC_VERSION", Some(110680)), /// Allows using `#[link_name="llvm.*"]`. (internal, link_llvm_intrinsics, "1.0.0", Some(29602)), /// Allows using the `#[linkage = ".."]` attribute. diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 85b666372074a..8b55734d90c8f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -6,7 +6,7 @@ use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol, kw, sym}; use crate::check::check_function_signature; use crate::diagnostics::{UnrecognizedIntrinsicFunction, WrongNumberOfGenericArgumentsToIntrinsic}; @@ -66,6 +66,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi // safe extern fns are otherwise unprecedented. // tidy-alphabetical-start + | kw::OffsetOf | sym::abort_immediate | sym::add_with_overflow | sym::aggregate_raw_ptr @@ -141,7 +142,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::needs_drop | sym::offload | sym::offload_get_num_devices - | sym::offset_of | sym::overflow_checks | sym::powf | sym::powi @@ -271,7 +271,7 @@ pub(crate) fn check_intrinsic_type( (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize) } sym::type_id_size_of => (0, 0, vec![type_id_ty()], Ty::new_option(tcx, tcx.types.usize)), - sym::offset_of => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize), + kw::OffsetOf => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize), sym::field_offset => (1, 0, vec![], tcx.types.usize), sym::rustc_peek => (1, 0, vec![param(0)], param(0)), sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()), diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index f3cba3a27d69f..7ccd7eb435d03 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::adjustment::{ OverloadedDeref, PointerCoercion, }; use rustc_middle::ty::{self, Ty}; -use rustc_span::{Span, span_bug, sym}; +use rustc_span::{Span, kw, span_bug, sym}; use tracing::debug; use crate::method::{MethodCallee, TreatNotYetDefinedOpaques}; @@ -203,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("try_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op); let (Some(imm_tr), imm_op) = (match op { - PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), sym::deref), + PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), kw::Deref), PlaceOp::Index => (self.tcx.lang_items().index_trait(), sym::index), }) else { // Bail if `Deref` or `Index` isn't defined. diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index d116806fc0b73..a8ae60b4daba7 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt}; use rustc_span::def_id::DefId; -use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, bug, sym}; +use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, bug, kw, sym}; use tracing::{debug, instrument}; use crate::builder::Builder; @@ -343,7 +343,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, ) { let (trait_item, method) = match mutability { - Mutability::Not => (LangItem::Deref, sym::deref), + Mutability::Not => (LangItem::Deref, kw::Deref), Mutability::Mut => (LangItem::DerefMut, sym::deref_mut), }; let borrow_kind = super::util::ref_pat_borrow_kind(mutability); diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index ab220cc56a9e0..72947b1c576c8 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -4079,21 +4079,6 @@ impl IntoDiagArg for Case { } } -#[derive(Diagnostic)] -#[diag("unknown `builtin #` construct `{$name}`")] -pub(crate) struct UnknownBuiltinConstruct { - #[primary_span] - pub span: Span, - pub name: Ident, -} - -#[derive(Diagnostic)] -#[diag("expected identifier after `builtin #`")] -pub(crate) struct ExpectedBuiltinIdent { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("static items may not have generic parameters")] pub(crate) struct StaticWithGenerics { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index fd59519f1e5a6..fd5886e0cec90 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1315,8 +1315,6 @@ impl<'a> Parser<'a> { }) } else if this.check(exp!(OpenBracket)) { this.parse_expr_array_or_repeat(exp!(CloseBracket)) - } else if this.is_builtin() { - this.parse_expr_builtin() } else if this.check_path() { this.parse_expr_path_start() } else if this.token.is_keyword(kw::Move) @@ -1385,6 +1383,14 @@ impl<'a> Parser<'a> { return Ok(expr); } Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore)) + } else if this.eat_forced_keyword_noexpect(kw::OffsetOf) { + this.parse_expr_offset_of(lo) + } else if this.eat_forced_keyword_noexpect(kw::TypeAscribe) { + this.parse_expr_type_ascribe(lo) + } else if this.eat_forced_keyword_noexpect(kw::WrapBinder) { + this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap) + } else if this.eat_forced_keyword_noexpect(kw::UnwrapBinder) { + this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap) } else if this.token_uninterpolated_span().at_least_rust_2018() { // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. let at_async = this.check_keyword(exp!(Async)); @@ -1826,58 +1832,9 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr) } - /// Parse `builtin # ident(args,*)`. - fn parse_expr_builtin(&mut self) -> PResult<'a, Box> { - self.parse_builtin(|this, lo, ident| { - Ok(match ident.name { - sym::offset_of => Some(this.parse_expr_offset_of(lo)?), - sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?), - sym::wrap_binder => { - Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?) - } - sym::unwrap_binder => { - Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?) - } - _ => None, - }) - }) - } - - pub(crate) fn parse_builtin( - &mut self, - parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option>, - ) -> PResult<'a, T> { - let lo = self.token.span; - - self.bump(); // `builtin` - self.bump(); // `#` - - let Some((ident, IdentKind::Normal)) = self.token.ident() else { - let err = self - .dcx() - .create_err(crate::diagnostics::ExpectedBuiltinIdent { span: self.token.span }); - return Err(err); - }; - self.psess.gated_spans.gate(sym::builtin_syntax, ident.span); - self.bump(); - + pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box> { self.expect(exp!(OpenParen))?; - let ret = if let Some(res) = parse(self, lo, ident)? { - Ok(res) - } else { - let err = self.dcx().create_err(crate::diagnostics::UnknownBuiltinConstruct { - span: lo.to(ident.span), - name: ident, - }); - return Err(err); - }; - self.expect(exp!(CloseParen))?; - - ret - } - /// Built-in macro for `offset_of!` expressions. - pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box> { let container = self.parse_ty()?; self.expect(exp!(Comma))?; @@ -1900,16 +1857,26 @@ impl<'a> Parser<'a> { } } + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields))) } - /// Built-in macro for type ascription expressions. pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, Box> { + self.expect(exp!(OpenParen))?; let expr = self.parse_expr()?; self.expect(exp!(Comma))?; let ty = self.parse_ty()?; + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); Ok(self.mk_expr(span, ExprKind::Type(expr, ty))) } @@ -1918,9 +1885,15 @@ impl<'a> Parser<'a> { lo: Span, kind: UnsafeBinderCastKind, ) -> PResult<'a, Box> { + self.expect(exp!(OpenParen))?; + let expr = self.parse_expr()?; let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None }; + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. let span = lo.to(self.token.span); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty))) } @@ -3465,10 +3438,6 @@ impl<'a> Parser<'a> { Ok(expr) } - pub(crate) fn is_builtin(&self) -> bool { - self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound) - } - /// Parses a `try {...}` or `try bikeshed Ty {...}` expression (`try` token already eaten). fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, Box> { let annotation = diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index fb8d9ce303865..ba142036946a2 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -354,9 +354,6 @@ impl<'a> Parser<'a> { // UNION ITEM self.bump(); // `union` self.parse_item_union()? - } else if self.is_builtin() { - // BUILTIN# ITEM - return self.parse_item_builtin(); } else if self.eat_keyword_case(exp!(Macro), case) { // MACROS 2.0 ITEM self.parse_item_decl_macro(lo)? @@ -599,11 +596,6 @@ impl<'a> Parser<'a> { if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } - fn parse_item_builtin(&mut self) -> PResult<'a, Option> { - // To be expanded - Ok(None) - } - /// Parses an item macro, e.g., `item!();`. fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> { let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index fb26ef5e8ace6..a89fd9b6298f3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -630,6 +630,15 @@ impl<'a> Parser<'a> { if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) } } + #[must_use] + pub(crate) fn eat_forced_keyword_noexpect(&mut self, kw: Symbol) -> bool { + if self.token.is_forced_keyword(kw) { + self.bump(); + return true; + } + false + } + /// Consume a sequence produced by a metavar expansion, if present. pub fn eat_metavar_seq( &mut self, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 9fd38aa0f3b8f..422e3cbfd082e 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -801,8 +801,17 @@ impl<'a> Parser<'a> { } else { PatKind::Expr(const_expr) } - } else if self.is_builtin() { - self.parse_pat_builtin()? + } else if self.eat_forced_keyword_noexpect(kw::Deref) { + self.expect(exp!(OpenParen))?; + let pat = ast::PatKind::Deref(Box::new(self.parse_pat_allow_top_guard( + None, + RecoverComma::Yes, + RecoverColon::Yes, + CommaRecoveryMode::LikelyTuple, + )?)); + self.expect(exp!(CloseParen))?; + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + pat } // Don't eagerly error on semantically invalid tokens when matching // declarative macros, as the input to those doesn't have to be @@ -1608,23 +1617,6 @@ impl<'a> Parser<'a> { .contains(&self.token.kind) } - fn parse_pat_builtin(&mut self) -> PResult<'a, PatKind> { - self.parse_builtin(|self_, _lo, ident| { - Ok(match ident.name { - // builtin#deref(PAT) - sym::deref => { - Some(ast::PatKind::Deref(Box::new(self_.parse_pat_allow_top_guard( - None, - RecoverComma::Yes, - RecoverColon::Yes, - CommaRecoveryMode::LikelyTuple, - )?))) - } - _ => None, - }) - }) - } - // FIXME: remove this entirely eventually /// Parses the removed `box pat` syntax to provide a more helpful error message. fn parse_pat_box(&mut self) -> PResult<'a, PatKind> { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 49bcdbbe8fa57..df2df24854ee1 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -126,11 +126,7 @@ impl<'a> Parser<'a> { diagnostics::InvalidVariableDeclarationSub::UseLetNotVar, force_collect, )? - } else if self.check_path() - && !self.token.is_qpath_start() - && !self.is_path_start_item() - && !self.is_builtin() - { + } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { // We have avoided contextual keywords like `union`, items with `crate` visibility, // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something // that starts like a path (1 token), but it fact not a path. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index e2187612f5d20..b66d7310dbea5 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -326,8 +326,6 @@ impl<'a> Parser<'a> { self.parse_borrowed_pointee()? } else if self.eat_keyword_noexpect(kw::Typeof) { self.parse_typeof_ty(lo)? - } else if self.is_builtin() { - self.parse_builtin_ty()? } else if self.eat_keyword(exp!(Underscore)) { // A type to be inferred `_` TyKind::Infer @@ -423,6 +421,8 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |tok| tok.kind == token::Lt) { self.parse_unsafe_binder_ty()? + } else if self.eat_forced_keyword_noexpect(kw::FieldOf) { + self.parse_ty_field_of(lo)? } else { let msg = format!("expected type, found {}", super::token_descr(&self.token)); let mut err = self.dcx().struct_span_err(lo, msg); @@ -826,16 +826,9 @@ impl<'a> Parser<'a> { Ok(TyKind::Err(guar)) } - fn parse_builtin_ty(&mut self) -> PResult<'a, TyKind> { - self.parse_builtin(|this, lo, ident| { - Ok(match ident.name { - sym::field_of => Some(this.parse_ty_field_of(lo)?), - _ => None, - }) - }) - } + pub(crate) fn parse_ty_field_of(&mut self, lo: Span) -> PResult<'a, TyKind> { + self.expect(exp!(OpenParen))?; - pub(crate) fn parse_ty_field_of(&mut self, _lo: Span) -> PResult<'a, TyKind> { let container = self.parse_ty()?; self.expect(exp!(Comma))?; @@ -844,30 +837,36 @@ impl<'a> Parser<'a> { if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) { if trailing_comma { - e.note("unexpected third argument to field_of"); + e.note("unexpected third argument to `field_of`"); } else { - e.note("field_of expects dot-separated field and variant names"); + e.note("`field_of` expects dot-separated field and variant names"); } e.emit(); } - // Eat tokens until the macro call ends. + // Eat tokens until the construct ends. if self.may_recover() { while !self.token.kind.is_close_delim_or_eof() { self.bump(); } } + // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but + // it actually "improves" diagnostics slightly by not pointing into the wrapper macros. + let span = self.token.span; + self.expect(exp!(CloseParen))?; + + self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span)); + match *fields { - [] => Err(self.dcx().struct_span_err( - self.token.span, - "`field_of!` expects dot-separated field and variant names", - )), + [] => Err(self + .dcx() + .struct_span_err(span, "`field_of` expects dot-separated field and variant names")), [field] => Ok(TyKind::FieldOf(container, None, field)), [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)), _ => Err(self.dcx().struct_span_err( fields.iter().map(|f| f.span).collect::>(), - "`field_of!` only supports a single field or a variant with a field", + "`field_of` only supports a single field or a variant with a field", )), } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index de141dcc8b823..d7bdc396269c4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -125,17 +125,22 @@ symbols! { // Matching predicates: `is_weak` // tidy-alphabetical-start Auto: "auto", - Builtin: "builtin", Catch: "catch", ContractEnsures: "contract_ensures", ContractRequires: "contract_requires", Default: "default", + Deref: "deref", + FieldOf: "field_of", MacroRules: "macro_rules", + OffsetOf: "offset_of", Pin: "pin", Raw: "raw", Reuse: "reuse", Safe: "safe", + TypeAscribe: "type_ascribe", Union: "union", + UnwrapBinder: "unwrap_binder", + WrapBinder: "wrap_binder", Yeet: "yeet", // tidy-alphabetical-end } @@ -580,7 +585,6 @@ symbols! { bridge, bswap, built, - builtin_syntax, bundle, c_dash_variadic, c_str_literals, @@ -829,7 +833,6 @@ symbols! { deprecated, deprecated_safe, deprecated_suggestion, - deref, deref_method, deref_mut, deref_patterns, @@ -991,7 +994,6 @@ symbols! { field, field_base, field_init_shorthand, - field_of, field_offset, field_projections, field_representing_type, @@ -1174,6 +1176,7 @@ symbols! { integral, internal_eq_trait_method_impls, internal_features, + internal_syntax, interrupt, into_async_iter_into_iter, into_future, @@ -1508,7 +1511,6 @@ symbols! { offload_kernel, offload_region, offset, - offset_of, offset_of_enum, offset_of_nested, offset_of_slice, @@ -2205,7 +2207,6 @@ symbols! { ty, type_alias_enum_variants, type_alias_impl_trait, - type_ascribe, type_ascription, type_changing_struct_update, type_id, @@ -2334,7 +2335,6 @@ symbols! { unwind_attributes, unwind_safe_trait, unwrap, - unwrap_binder, unwrap_or, update, use_cloned, @@ -2420,7 +2420,6 @@ symbols! { windows, windows_subsystem, with_negative_coherence, - wrap_binder, wrapping_add, wrapping_div, wrapping_mul, diff --git a/library/core/src/field.rs b/library/core/src/field.rs index 5a8ae7759bc1e..b17a78846ce2a 100644 --- a/library/core/src/field.rs +++ b/library/core/src/field.rs @@ -124,7 +124,7 @@ impl Ord /// The container type may be a tuple, `struct`, `union` or `enum`. In the case of an enum, the /// variant must also be specified. Only a single field is supported. #[unstable(feature = "field_projections", issue = "145383")] -#[allow_internal_unstable(field_representing_type_raw, builtin_syntax)] +#[allow_internal_unstable(field_representing_type_raw, internal_syntax)] #[diagnostic::on_unmatched_args( note = "this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)`" )] @@ -134,7 +134,7 @@ impl Ord // it to `FieldRepresentingType<...>`. Thus stabilizing this requires careful thought about the // completeness of the trait impls for `FieldRepresentingType`. pub macro field_of($Container:ty, $($fields:expr)+ $(,)?) { - builtin # field_of($Container, $($fields)+) + k#field_of($Container, $($fields)+) } /// Type representing a field of a `struct`, `union`, `enum` variant or tuple. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 36a19f89e58cd..67c216053f7b1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -129,6 +129,7 @@ #![feature(f128)] #![feature(field_projections)] #![feature(final_associated_functions)] +#![feature(forced_keywords)] #![feature(freeze_impls)] #![feature(fundamental)] #![feature(impl_restriction)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3b378078d3284..789119fb20052 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1907,7 +1907,7 @@ pub(crate) mod builtin { } /// Unstable placeholder for type ascription. - #[allow_internal_unstable(builtin_syntax)] + #[allow_internal_unstable(internal_syntax)] #[unstable( feature = "type_ascription", issue = "101728", @@ -1915,11 +1915,11 @@ pub(crate) mod builtin { )] #[diagnostic::opaque] pub macro type_ascribe($expr:expr, $ty:ty) { - builtin # type_ascribe($expr, $ty) + k#type_ascribe($expr, $ty) } /// Unstable placeholder for deref patterns. - #[allow_internal_unstable(builtin_syntax)] + #[allow_internal_unstable(internal_syntax)] #[unstable( feature = "deref_patterns", issue = "87121", @@ -1927,7 +1927,7 @@ pub(crate) mod builtin { )] #[diagnostic::opaque] pub macro deref($pat:pat) { - builtin # deref($pat) + k#deref($pat) } /// Derive macro generating an impl of the trait `From`. diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index b38557779092c..39b07963fb9a9 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1664,10 +1664,10 @@ impl SizedTypeProperties for T {} note = "this macro expects a container type and a (nested) field path, like `offset_of!(Type, field)`" )] #[doc(alias = "memoffset")] -#[allow_internal_unstable(builtin_syntax, core_intrinsics)] +#[allow_internal_unstable(core_intrinsics, internal_syntax)] #[diagnostic::opaque] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { - const { builtin # offset_of($Container, $($fields)+) } + const { k#offset_of($Container, $($fields)+) } } /// Create a fresh instance of the inhabited ZST type `T`. diff --git a/library/core/src/unsafe_binder.rs b/library/core/src/unsafe_binder.rs index 3d2a04e95f078..bb7144fc5dddd 100644 --- a/library/core/src/unsafe_binder.rs +++ b/library/core/src/unsafe_binder.rs @@ -1,27 +1,17 @@ //! Operators used to turn types into unsafe binders and back. /// Unwrap an unsafe binder into its underlying type. -#[allow_internal_unstable(builtin_syntax)] +#[allow_internal_unstable(internal_syntax)] #[unstable(feature = "unsafe_binders", issue = "130516")] #[diagnostic::opaque] -pub macro unwrap_binder { - ($expr:expr) => { - builtin # unwrap_binder ( $expr ) - }, - ($expr:expr ; $ty:ty) => { - builtin # unwrap_binder ( $expr, $ty ) - }, +pub macro unwrap_binder($expr:expr $( ; $ty:ty )?) { + k#unwrap_binder($expr $( , $ty )?) } /// Wrap a type into an unsafe binder. -#[allow_internal_unstable(builtin_syntax)] +#[allow_internal_unstable(internal_syntax)] #[unstable(feature = "unsafe_binders", issue = "130516")] #[diagnostic::opaque] -pub macro wrap_binder { - ($expr:expr) => { - builtin # wrap_binder ( $expr ) - }, - ($expr:expr ; $ty:ty) => { - builtin # wrap_binder ( $expr, $ty ) - }, +pub macro wrap_binder($expr:expr $( ; $ty:ty )?) { + k#wrap_binder($expr $( , $ty )?) } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 56d651aff2731..7cbdaaac864f8 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1853,7 +1853,7 @@ impl PrimitiveType { Char => sym::char, Array => sym::array, Pat => sym::pat, - FieldOf => sym::field_of, + FieldOf => kw::FieldOf, Slice => sym::slice, Tuple => sym::tuple, Unit => sym::unit, diff --git a/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs b/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs index c233fe3f28ed5..2536ad574239b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs +++ b/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs @@ -112,7 +112,7 @@ const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [ ShouldImplTraitCase::new("std::clone::Clone", sym::clone, 1, SelfKind::Ref, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::cmp::Ord", sym::cmp, 2, SelfKind::Ref, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::default::Default", kw::Default, 0, SelfKind::No, OutType::Any, true, Edition2015), - ShouldImplTraitCase::new("std::ops::Deref", sym::deref, 1, SelfKind::Ref, OutType::Ref, true, Edition2015), + ShouldImplTraitCase::new("std::ops::Deref", kw::Deref, 1, SelfKind::Ref, OutType::Ref, true, Edition2015), ShouldImplTraitCase::new("std::ops::DerefMut", sym::deref_mut, 1, SelfKind::RefMut, OutType::Ref, true, Edition2015), ShouldImplTraitCase::new("std::ops::Div", sym::div, 2, SelfKind::Value, OutType::Any, true, Edition2015), ShouldImplTraitCase::new("std::ops::Drop", sym::drop, 1, SelfKind::RefMut, OutType::Unit, true, Edition2015), diff --git a/src/tools/rustfmt/.github/workflows/check_diff.yml b/src/tools/rustfmt/.github/workflows/check_diff.yml index b3543a49c3e9b..7f7bc62846a3c 100644 --- a/src/tools/rustfmt/.github/workflows/check_diff.yml +++ b/src/tools/rustfmt/.github/workflows/check_diff.yml @@ -51,6 +51,8 @@ jobs: steps: - name: checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Build check_diff binary working-directory: ./check_diff @@ -60,19 +62,25 @@ jobs: working-directory: ./check_diff env: CHECK_DIFF_LOG: info + GITHUB_EVENT_INPUTS_COMMIT_HASH: ${{ github.event.inputs.commit_hash }} + GITHUB_EVENT_INPUTS_RUSTFMT_CONFIGS: ${{ github.event.inputs.rustfmt_configs }} + GITHUB_EVENT_INPUTS_CLONE_URL: ${{ github.event.inputs.clone_url }} + GITHUB_EVENT_INPUTS_BRANCH_NAME: ${{ github.event.inputs.branch_name }} + GITHUB_EVENT_INPUTS_LANGUAGE_EDITION: ${{ github.event.inputs.language_edition }} + GITHUB_EVENT_INPUTS_STYLE_EDITION: ${{ github.event.inputs.style_edition }} shell: bash run: | OPTIONS="" - if [[ -n "${{ github.event.inputs.commit_hash }}" ]]; then - OPTIONS+="--commit-hash ${{ github.event.inputs.commit_hash }} " + if [[ -n "${GITHUB_EVENT_INPUTS_COMMIT_HASH}" ]]; then + OPTIONS+="--commit-hash ${GITHUB_EVENT_INPUTS_COMMIT_HASH} " fi - if [[ -n "${{ github.event.inputs.rustfmt_configs }}" ]]; then - OPTIONS+="--rustfmt-config ${{ github.event.inputs.rustfmt_configs }} " + if [[ -n "${GITHUB_EVENT_INPUTS_RUSTFMT_CONFIGS}" ]]; then + OPTIONS+="--rustfmt-config ${GITHUB_EVENT_INPUTS_RUSTFMT_CONFIGS} " fi - target/release/check_diff ${{ github.event.inputs.clone_url }} ${{ github.event.inputs.branch_name }} \ - --edition ${{ github.event.inputs.language_edition }} \ - --style-edition ${{ github.event.inputs.style_edition }} \ + target/release/check_diff ${GITHUB_EVENT_INPUTS_CLONE_URL} ${GITHUB_EVENT_INPUTS_BRANCH_NAME} \ + --edition ${GITHUB_EVENT_INPUTS_LANGUAGE_EDITION} \ + --style-edition ${GITHUB_EVENT_INPUTS_STYLE_EDITION} \ $OPTIONS diff --git a/src/tools/rustfmt/.github/workflows/clippy.yml b/src/tools/rustfmt/.github/workflows/clippy.yml index a5aa91346dd84..fc3eb8916a6bd 100644 --- a/src/tools/rustfmt/.github/workflows/clippy.yml +++ b/src/tools/rustfmt/.github/workflows/clippy.yml @@ -13,6 +13,8 @@ jobs: steps: - name: checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: install rustup run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh @@ -35,10 +37,14 @@ jobs: steps: - name: checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: install rustup run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh sh rustup-init.sh -y --default-toolchain none - name: clippy - run: cargo clippy --locked --manifest-path ${{ matrix.package }}/Cargo.toml + run: cargo clippy --locked --manifest-path "${MATRIX_PACKAGE}/Cargo.toml" + env: + MATRIX_PACKAGE: ${{ matrix.package }} diff --git a/src/tools/rustfmt/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml index 224605740e55e..e8da0d8d3aed1 100644 --- a/src/tools/rustfmt/.github/workflows/integration.yml +++ b/src/tools/rustfmt/.github/workflows/integration.yml @@ -60,6 +60,8 @@ jobs: steps: - name: checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false # Run build - name: install rustup @@ -70,5 +72,6 @@ jobs: - name: run integration tests env: TARGET: x86_64-unknown-linux-gnu - run: cargo run --locked --manifest-path ci/Cargo.toml integration ${{ matrix.integration }} + MATRIX_INTEGRATION: ${{ matrix.integration }} + run: cargo run --locked --manifest-path ci/Cargo.toml integration ${MATRIX_INTEGRATION} continue-on-error: ${{ matrix.allow-failure == true }} diff --git a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml index b3978005fdf62..e2b5e5a68ed71 100644 --- a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml +++ b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml @@ -13,6 +13,8 @@ jobs: steps: - name: checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: install rustup run: | diff --git a/src/tools/rustfmt/.github/workflows/test.yml b/src/tools/rustfmt/.github/workflows/test.yml index 6d0f25834e596..44d36898f216f 100644 --- a/src/tools/rustfmt/.github/workflows/test.yml +++ b/src/tools/rustfmt/.github/workflows/test.yml @@ -43,6 +43,8 @@ jobs: run: git config --global core.autocrlf false - name: checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Install Rustup using win.rustup.rs if: ${{ matrix.os == 'windows-latest' }} @@ -52,7 +54,9 @@ jobs: Invoke-WebRequest https://win.rustup.rs/ -OutFile rustup-init.exe .\rustup-init.exe -y --default-host=x86_64-pc-windows-msvc --default-toolchain=none del rustup-init.exe - rustup target add ${{ matrix.target }} + rustup target add ${env:MATRIX_TARGET} + env: + MATRIX_TARGET: ${{ matrix.target }} shell: powershell - name: Add mingw32 to path for i686-gnu @@ -71,7 +75,9 @@ jobs: run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh sh rustup-init.sh -y --default-toolchain none - rustup target add ${{ matrix.target }} + rustup target add ${MATRIX_TARGET} + env: + MATRIX_TARGET: ${{ matrix.target }} # Run build - name: Build and Test @@ -97,6 +103,8 @@ jobs: - name: Conclusion run: | # Print the dependent jobs to see them in the CI log - jq -C <<< '${{ toJson(needs) }}' + jq -C <<< "${JSON_NEEDS}" # Check if all jobs that we depend on (in the needs array) were successful (or have been skipped). - jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}' + jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< "${JSON_NEEDS}" + env: + JSON_NEEDS: ${{ toJson(needs) }} diff --git a/src/tools/rustfmt/.github/workflows/upload-assets.yml b/src/tools/rustfmt/.github/workflows/upload-assets.yml deleted file mode 100644 index 991cc965e3d51..0000000000000 --- a/src/tools/rustfmt/.github/workflows/upload-assets.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: upload - -on: - push: - release: - types: [created] - workflow_dispatch: - -jobs: - build-release: - name: build-release - strategy: - matrix: - build: [linux-x86_64, macos-x86_64, windows-x86_64-gnu, windows-x86_64-msvc] - include: - - build: linux-x86_64 - os: ubuntu-latest - rust: nightly - target: x86_64-unknown-linux-gnu - - build: macos-x86_64 - os: macos-latest - rust: nightly - target: x86_64-apple-darwin - - build: windows-x86_64-gnu - os: windows-latest - rust: nightly-x86_64-gnu - target: x86_64-pc-windows-gnu - - build: windows-x86_64-msvc - os: windows-latest - rust: nightly-x86_64-msvc - target: x86_64-pc-windows-msvc - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - # Run build - - name: install rustup - run: | - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh - sh rustup-init.sh -y --default-toolchain none - rustup target add ${{ matrix.target }} - - - name: Add mingw64 to path for x86_64-gnu - run: echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH - if: matrix.rust == 'nightly-x86_64-gnu' - shell: bash - - - name: Build release binaries - run: cargo build --release --locked - - - name: Build archive - shell: bash - run: | - staging="rustfmt_${{ matrix.build }}_${{ github.event.release.tag_name }}" - mkdir -p "$staging" - - cp {README.md,Configurations.md,CHANGELOG.md,LICENSE-MIT,LICENSE-APACHE} "$staging/" - - if [ "${{ matrix.os }}" = "windows-latest" ]; then - cp target/release/{rustfmt.exe,cargo-fmt.exe,rustfmt-format-diff.exe,git-rustfmt.exe} "$staging/" - 7z a "$staging.zip" "$staging" - echo "ASSET=$staging.zip" >> $GITHUB_ENV - else - cp target/release/{rustfmt,cargo-fmt,rustfmt-format-diff,git-rustfmt} "$staging/" - tar czf "$staging.tar.gz" "$staging" - echo "ASSET=$staging.tar.gz" >> $GITHUB_ENV - fi - - - name: Upload Release Asset - if: github.event_name == 'release' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: gh release upload "${{ github.event.release.tag_name }}" "${{ env.ASSET }}" diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md index 454ffc1a91cca..b28723aa08e5f 100644 --- a/src/tools/rustfmt/CHANGELOG.md +++ b/src/tools/rustfmt/CHANGELOG.md @@ -2,9 +2,34 @@ ## [Unreleased] -### Changed -- The unstable `required_version` configuration option now defaults to a caret (`^`) semver requirement instead of an exact match when no comparator is given, matching how Cargo treats dependency version requirements. Use the explicit `=` operator (e.g. `required_version = "=1.2.3"`) to opt back into exact matching [#6729](https://github.com/rust-lang/rustfmt/issues/6729) + +## [1.12.0] 2026-12-24 +### Changed +- The unstable `required_version` configuration option now defaults to a caret (`^`) semver requirement instead of an exact match when no comparator is given, matching how Cargo treats dependency version requirements. Use the explicit `=` operator (e.g. `required_version = "=1.2.3"`) to opt back into exact matching [#6729](https://github.com/rust-lang/rustfmt/issues/6729) [#7048](https://github.com/rust-lang/rustfmt/pull/7048) +> [!IMPORTANT] +> Potential breaking changes: +> - When `--config-path` is a directory, rustfmt now also searches its parent directories for config files [#4660](https://github.com/rust-lang/rustfmt/issues/4660) [#7115](https://github.com/rust-lang/rustfmt/pull/7115) +> - Chains with comments now format under `use_try_shorthand=true` [#6121](https://github.com/rust-lang/rustfmt/issues/6121) [#7095](https://github.com/rust-lang/rustfmt/pull/7095) +> - Error on `--print-config minimal` with no output path [#7208](https://github.com/rust-lang/rustfmt/pull/7208) +> - Previously, this printed a warning and exited with `0`. + +### Fixed +- Fix ragged statement comment wrapping under unstable option `wrap_comments=true` and `comment_width` [#7167](https://github.com/rust-lang/rustfmt/issues/7167) [#7170](https://github.com/rust-lang/rustfmt/pull/7170) +- Enforce comment width in item lists [#7174](https://github.com/rust-lang/rustfmt/pull/7174) +- Fix lookup of global config files [#7178](https://github.com/rust-lang/rustfmt/issues/7178) [#7179](https://github.com/rust-lang/rustfmt/pull/7179) +- Don't remove empty generic args when formatting in a macro context [#7136](https://github.com/rust-lang/rustfmt/issues/7136) [#7181](https://github.com/rust-lang/rustfmt/pull/7181) +- Various `cfg_select!` fixes. Note that `cfg_select!` formatting is still nightly-gated. + - Fix `cfg_select!` parser recovery handling and error count leak [#7171](https://github.com/rust-lang/rustfmt/pull/7171) + - Don't remove necessary blocks when formatting `cfg_select!` arms [#7045](https://github.com/rust-lang/rustfmt/issues/7045) [#7183](https://github.com/rust-lang/rustfmt/pull/7183) + - Prevent more comment loss in `cfg_select!` [#7209](https://github.com/rust-lang/rustfmt/issues/7209) [rust-lang/rust#164815](https://github.com/rust-lang/rust/pull/164815) + - Don't lose comments and attributes between `cfg_select!` predicates, outer/inner blocks, arm body and trailing commas [#7209](https://github.com/rust-lang/rustfmt/issues/7209) [#7211](https://github.com/rust-lang/rustfmt/pull/7211) + - Have `cfg_select!` double-brace concise formatting respect `control_brace_style` unstable option [#7214](https://github.com/rust-lang/rustfmt/pull/7214) +- Prevent rustfmt from removing expression attributes when removing nested parentheses [#7190](https://github.com/rust-lang/rustfmt/issues/7190) [#7192](https://github.com/rust-lang/rustfmt/pull/7192) +- Fix `cfg_if!` error count leaks [#7195](https://github.com/rust-lang/rustfmt/pull/7195) +- Format comments after `where` clauses using `clause_shape` budget (affecting unstable options `wrap_comments=true` and `comment_width`) [#7148](https://github.com/rust-lang/rustfmt/issues/7148) [#7156](https://github.com/rust-lang/rustfmt/pull/7156) +- Fix ICE on failure to format generics in enum [#5738](https://github.com/rust-lang/rustfmt/issues/5738) [#6137](https://github.com/rust-lang/rustfmt/issues/6137) [#6318](https://github.com/rust-lang/rustfmt/issues/6318) [#6646](https://github.com/rust-lang/rustfmt/issues/6646) [#6396](https://github.com/rust-lang/rustfmt/pull/6396) +- Avoid leaking wrapper space from doc comment code block formatting (affecting unstable options `format_code_in_doc_comments=true` and `fn_single_line=true`) [#6832](https://github.com/rust-lang/rustfmt/issues/6832) [#6851](https://github.com/rust-lang/rustfmt/pull/6851) ## [1.11.0] 2026-11-12 @@ -28,7 +53,6 @@ - Correct visibility and defaultness order on associated impl type alias [#7064](https://github.com/rust-lang/rustfmt/pull/7064). - Correctly calculate the `shape` for inline const blocks when using `style_edition=2027` [#7065](https://github.com/rust-lang/rustfmt/pull/7065). - Prevent invalid code generation in macros that use raw identifiers [#7110](https://github.com/rust-lang/rustfmt/pull/7110). -- Prevent rustfmt from reporting on `max_width` configuration issues when formatting macros [#6651](https://github.com/rust-lang/rustfmt/pull/6651). ### Changed - No longer apply `use_field_init_shorthand` when formatting macros [#6981](https://github.com/rust-lang/rustfmt/pull/6981). diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock index b83c8ec9612c5..38d5f7724e84d 100644 --- a/src/tools/rustfmt/Cargo.lock +++ b/src/tools/rustfmt/Cargo.lock @@ -582,7 +582,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.11.0" +version = "1.12.0" dependencies = [ "annotate-snippets", "anyhow", diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml index 9e689fc0041f1..78ee1fb2742a0 100644 --- a/src/tools/rustfmt/Cargo.toml +++ b/src/tools/rustfmt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustfmt-nightly" -version = "1.11.0" +version = "1.12.0" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" license = "Apache-2.0 OR MIT" diff --git a/src/tools/rustfmt/rust-toolchain.toml b/src/tools/rustfmt/rust-toolchain.toml index d621e4fb08484..0a85b69efd3e9 100644 --- a/src/tools/rustfmt/rust-toolchain.toml +++ b/src/tools/rustfmt/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-10-22" +channel = "nightly-2026-11-02" components = ["llvm-tools", "rustc-dev"] diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index 7b003672795bd..0653ad3d93758 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -93,12 +93,6 @@ pub enum OperationError { /// An unknown help topic was requested. #[error("Unknown help topic: `{0}`.")] UnknownHelpTopic(String), - /// An unknown print-config option was requested. - #[error("Unknown print-config option: `{0}`.")] - UnknownPrintConfigTopic(String), - /// Attempt to generate a minimal config from standard input. - #[error("The `--print-config=minimal` option doesn't work with standard input.")] - MinimalPathWithStdin, /// An io error during reading or writing. #[error("{0}")] IoError(IoError), @@ -106,6 +100,21 @@ pub enum OperationError { /// supported with standard input. #[error("Emit mode {0} not supported with standard output.")] StdinBadEmit(EmitMode), + #[error(transparent)] + PrintConfig(PrintConfigError), +} + +// Errors related to the '--print-config' option. +#[derive(Error, Debug)] +pub enum PrintConfigError { + /// An unknown print-config option was requested. + #[error("Unknown print-config option: `{0}`.")] + UnknownOption(String), + #[error("The `--print-config=minimal` option requires an output path to write to")] + MinimalPathNoPath, + /// Attempt to generate a minimal config from standard input. + #[error("The `--print-config=minimal` option doesn't work with standard input.")] + MinimalPathWithStdin, } impl From for OperationError { @@ -490,23 +499,24 @@ fn determine_operation(matches: &Matches) -> Result { } let mut free_matches = matches.free.iter(); - let mut minimal_config_path = None; - if let Some(kind) = matches.opt_str("print-config") { - let path = free_matches.next().cloned(); - match kind.as_str() { - "default" => return Ok(Operation::ConfigOutputDefault { path }), - "current" => return Ok(Operation::ConfigOutputCurrent { path }), - "minimal" => { - minimal_config_path = path; - if minimal_config_path.is_none() { - eprintln!("WARNING: PATH required for `--print-config minimal`."); + let minimal_config_path = match matches.opt_str("print-config") { + None => None, + Some(kind) => { + let path = free_matches.next().cloned(); + match kind.as_str() { + "default" => return Ok(Operation::ConfigOutputDefault { path }), + "current" => return Ok(Operation::ConfigOutputCurrent { path }), + "minimal" => Some(path.ok_or(OperationError::PrintConfig( + PrintConfigError::MinimalPathNoPath, + ))?), + _ => { + return Err(OperationError::PrintConfig( + PrintConfigError::UnknownOption(kind), + )); } } - _ => { - return Err(OperationError::UnknownPrintConfigTopic(kind)); - } } - } + }; if matches.opt_present("version") { return Ok(Operation::Version); @@ -524,7 +534,9 @@ fn determine_operation(matches: &Matches) -> Result { // if no file argument is supplied, read from stdin if files.is_empty() { if minimal_config_path.is_some() { - return Err(OperationError::MinimalPathWithStdin); + return Err(OperationError::PrintConfig( + PrintConfigError::MinimalPathWithStdin, + )); } let mut buffer = String::new(); io::stdin().read_to_string(&mut buffer)?; diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs index ee1ccdb437801..69749feb0f357 100644 --- a/src/tools/rustfmt/src/config/config_type.rs +++ b/src/tools/rustfmt/src/config/config_type.rs @@ -435,65 +435,6 @@ macro_rules! create_config { )+ } - /// Reduces the maximum width of the configuration. - /// - /// This method is intended to be used when creating a forked - /// configuration for a particular formatting context in which the - /// total available width needs to be reduced. This reduces the - /// size of max_width, and all other properties affected by small - /// heuristics, without treating those adjustments as overrides. - /// - /// As an example use case, this method is used when formatting - /// arms within a declarative macro. - #[allow(unreachable_pub)] - pub fn reduce_max_width(&mut self, delta: usize) { - self.adjust_max_width(-(delta.min(isize::MAX as usize) as isize)); - } - - /// Increases the maximum width of the configuration. - /// - /// This method is intended to be used when creating a forked - /// configuration for a particular formatting context in which the - /// total available width needs to be increased. This increases the - /// size of max_width, and all other properties affected by small - /// heuristics, without treating those adjustments as overrides. - /// - /// As an example use case, this method is used when formatting - /// arms within a declarative macro. - #[allow(unreachable_pub)] - pub fn increase_max_width(&mut self, delta: usize) { - self.adjust_max_width(delta.min(isize::MAX as usize) as isize); - } - - /// Adjusts the maximum width of the configuration. - /// - /// This method is intended to be used when creating a forked - /// configuration for a particular formatting context in which the - /// total available width needs to be reduced. This adjusts the - /// size of max_width, and all other properties affected by small - /// heuristics, without treating those adjustments as overrides. - /// - /// As an example use case, this method is used when formatting - /// arms within a declarative macro. - fn adjust_max_width(&mut self, delta: isize) { - // NB: we need to either saturate or report an error (or some kind of testable - // warning). I picked to saturate here. - let adjust = |value: usize| value.saturating_add_signed(delta); - - self.array_width.2 = adjust(self.array_width.2); - self.attr_fn_like_width.2 = adjust(self.attr_fn_like_width.2); - self.chain_width.2 = adjust(self.chain_width.2); - self.fn_call_width.2 = adjust(self.fn_call_width.2); - self.single_line_if_else_max_width.2 = adjust(self.single_line_if_else_max_width.2); - self.single_line_let_else_max_width.2 = - adjust(self.single_line_let_else_max_width.2); - self.struct_lit_width.2 = adjust(self.struct_lit_width.2); - self.struct_variant_width.2 = adjust(self.struct_variant_width.2); - - self.max_width.2 = adjust(self.max_width.2); - self.set_heuristics(); - } - fn set_width_heuristics(&mut self, heuristics: WidthHeuristics) { let max_width = self.max_width.2; let get_width_value = | diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index 7ecf2ec3b58cf..0180bb89841c0 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -689,23 +689,6 @@ mod test { assert_eq!(config.verbose(), Verbosity::Normal); } - #[test] - fn test_adjust_max_width() { - // Regression tests for #7147, where we didn't handle overflows / integral cast outside of - // range properly. - - // Reduce with huge amount saturates to zero instead of wraparound. - let mut config = Config::default(); - config.reduce_max_width(usize::MAX); - assert_eq!(config.max_width(), 0); - - // Increase with huge amount saturates instead of wraparound. - let mut config = Config::default(); - config.set().max_width(usize::MAX - 1); - config.increase_max_width(2); - assert_eq!(config.max_width(), usize::MAX); - } - #[test] fn test_config_used_to_toml() { let config = Config::default(); diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 0b82acba264da..a9eccf1c7785a 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -1371,13 +1371,31 @@ pub(crate) fn rewrite_literal( token::LitKind::Str => rewrite_string_lit(context, span, shape), token::LitKind::Integer => rewrite_int_lit(context, token_lit, span, shape), token::LitKind::Float => rewrite_float_lit(context, token_lit, span, shape), - _ => wrap_str( - context.snippet(span).to_owned(), - context.config.max_width(), - context.config.tab_spaces(), - shape, - ) - .max_width_error(shape.width, span), + token::LitKind::Bool + | token::LitKind::Byte + | token::LitKind::ByteStr + | token::LitKind::ByteStrRaw(_) + | token::LitKind::Char + | token::LitKind::CStr + | token::LitKind::CStrRaw(_) + | token::LitKind::StrRaw(_) + | token::LitKind::Err(_) => { + // token::LitKind::Bool is true or false + // token::LitKind::Byte is b'' + // token::LitKind::ByteStr is b"" + // token::LitKind::ByteStrRaw(_) is br"" or br#""# + // token::LitKind::Char is '' + // token::LitKind::CStr is c"" + // token::LitKind::CStrRaw(_) is cr"" or cr#""# + // token::LitKind::StrRaw(_) is r"" or r#""# + wrap_str( + context.snippet(span).to_owned(), + context.config.max_width(), + context.config.tab_spaces(), + shape, + ) + .max_width_error(shape.width, span) + } } } diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 4e82f89e437b1..d5c27400106c6 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -21,16 +21,19 @@ use rustc_span::{BytePos, DUMMY_SP, Ident, Pos, Span, Symbol}; use tracing::debug; use crate::comment::{ - CharClasses, FindUncommented, FullCodeCharKind, LineClasses, contains_comment, + CharClasses, FindUncommented, FullCodeCharKind, LineClasses, + combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, }; -use crate::config::StyleEdition; use crate::config::lists::*; +use crate::config::{ControlBraceStyle, StyleEdition}; use crate::expr::{RhsAssignKind, rewrite_array, rewrite_assign_rhs}; use crate::header::{HeaderPart, format_header}; use crate::is_nightly_channel; use crate::lists::{ListFormatting, itemize_list, write_list}; use crate::overflow; -use crate::parse::macros::cfg_select::{CfgSelectFormatPredicate, parse_cfg_select_arms}; +use crate::parse::macros::cfg_select::{ + CfgSelectArm, CfgSelectFormatPredicate, parse_cfg_select_arms, +}; use crate::parse::macros::lazy_static::parse_lazy_static; use crate::parse::macros::{ParsedMacroArgs, parse_expr, parse_macro_args}; use crate::rewrite::{ @@ -40,8 +43,9 @@ use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ - NodeIdExt, extra_offset, filtered_str_fits, indent_next_line, is_empty_line, mk_sp, - remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, + NodeIdExt, extra_offset, filtered_str_fits, indent_next_line, is_empty_line, + last_line_contains_single_line_comment, mk_sp, remove_trailing_white_spaces, rewrite_ident, + trim_left_preserve_layout, }; use crate::visitor::FmtVisitor; @@ -1361,13 +1365,15 @@ impl MacroBranch { } else { shape.indent.block_indent(&config) }; - config.reduce_max_width(body_indent.width()); + let new_width = config.max_width() - body_indent.width(); + config.set().max_width(new_width); // First try to format as items, then as statements. let new_body_snippet = match crate::format_snippet(&body_str, &config, true) { Some(new_body) => new_body, None => { - config.increase_max_width(config.tab_spaces()); + let new_width = new_width + config.tab_spaces(); + config.set().max_width(new_width); match crate::format_code_block(&body_str, &config, true) { Some(new_body) => new_body, None => { @@ -1622,47 +1628,7 @@ fn format_cfg_select( "}", |arm| arm.span().lo(), |arm| arm.span().hi(), - |arm| { - let predicate_str = match &arm.predicate { - CfgSelectFormatPredicate::Wildcard(_t) => Cow::Borrowed("_"), - CfgSelectFormatPredicate::Cfg(meta_item_inner) => { - Cow::Owned(meta_item_inner.rewrite_result(context, nested_shape)?) - } - }; - - match arm.double_block_inner(context) { - // FIXME(ytmimi) The formatting for the `$predicate => {{}}` case isn't very robust. - // There's the potential that we'll lose comments in between the predicate, the `=>` - // and the body. We also don't handle comments like `{/*comment*/{}/*comment*/}`. - // The `rewrite_match_body` branch also handles `control_brace_style` better. - // That said, it helps fix . - Some(expr) => { - let trailing_comma = if arm.trailing_comma.is_some() { - "," - } else { - "" - }; - let offset = extra_offset(&predicate_str, nested_shape) + " => {".len(); - let nested_shape = nested_shape - .offset_left(offset, arm.span())? - .sub_width("}".len() + trailing_comma.len(), arm.span())?; - let body = expr - .rewrite_result(context, nested_shape) - .map(|rw| format!("{{{rw}}}"))?; - - Ok(format!("{predicate_str} => {body}{trailing_comma}")) - } - None => crate::matches::rewrite_match_body( - context, - &arm.expr, - &predicate_str, - nested_shape, - false, - arm.arrow.span, - last_arm.is_some_and(|la| la == arm), - ), - } - }, + |arm| rewrite_cfg_select_arm(context, nested_shape, last_arm, arm), // Start Span after the opening delimiter. For example, // ``` // cfg_select! { @@ -1694,3 +1660,126 @@ fn format_cfg_select( Ok(rewrite) } + +fn rewrite_cfg_select_arm( + context: &RewriteContext<'_>, + nested_shape: Shape, + last_arm: Option<&CfgSelectArm>, + arm: &CfgSelectArm, +) -> Result { + let try_rewrite = || { + let predicate_str = match &arm.predicate { + CfgSelectFormatPredicate::Wildcard(_t) => Cow::Borrowed("_"), + CfgSelectFormatPredicate::Cfg(meta_item_inner) => { + Cow::Owned(meta_item_inner.rewrite_result(context, nested_shape)?) + } + }; + + // We need to account for comments between predicate and `=>`. + let before_arrow_sp = arm.predicate.span().between(arm.arrow.span); + let before_arrow = context.snippet(before_arrow_sp); + let predicate_str = if contains_comment(before_arrow) { + // We cannot rewrite if the last line is a line comment, it will comment out + // `=>`. + if last_line_contains_single_line_comment(before_arrow.trim_end()) { + return Ok(context.snippet(arm.span()).to_owned()); + } + + Cow::Owned(combine_strs_with_missing_comments( + context, + &predicate_str, + "", + before_arrow_sp, + nested_shape, + true, + )?) + } else { + predicate_str + }; + + match arm.maybe_double_block_concise_formatting(context) { + // FIXME(ytmimi): the `rewrite_match_body` branch also handles + // `control_brace_style` better. That said, it helps fix + // . + Some(inner_expr) => { + // ``` + // => /* comment */ {{ ... }} + // ^------------- between span + // ``` + let after_arrow_comment = context + .snippet(arm.arrow.span.between(arm.expr.span())) + .trim(); + let after_arrow_comment = if after_arrow_comment.is_empty() { + None + } else { + Some(rewrite_comment( + after_arrow_comment, + false, + nested_shape, + context.config, + )?) + }; + + let trailing_comma = if arm.trailing_comma.is_some() { + "," + } else { + "" + }; + + // Force next-line layout if there's a comment after `=>`, like `match` arms. + let next_line_open_brace = matches!( + context.config.control_brace_style(), + ControlBraceStyle::AlwaysNextLine, + ) || after_arrow_comment.is_some(); + + let prefix_width = if next_line_open_brace { + 0 + } else { + extra_offset(&predicate_str, nested_shape) + " => ".len() + }; + + let body_shape = nested_shape + .offset_left(prefix_width + "{".len(), arm.span())? + .sub_width("}".len() + trailing_comma.len(), arm.span())?; + let body = inner_expr.rewrite_result(context, body_shape)?; + + let body = format!("{{{body}}}{trailing_comma}"); + match after_arrow_comment { + Some(comment) => { + let indent = nested_shape.indent.to_string_with_newline(context.config); + Ok(format!("{predicate_str} =>{indent}{comment}{indent}{body}")) + } + None if next_line_open_brace => { + let indent = nested_shape.indent.to_string_with_newline(context.config); + Ok(format!("{predicate_str} =>{indent}{body}")) + } + None => Ok(format!("{predicate_str} => {body}")), + } + } + None => { + // Note that we can't _just_ pass the `=>`'s span, we need to pass + // + // ``` + // => /* comment */ #[attr] { ... } + // ^--------------- this whole span until outer expr + // ``` + // + // Using `Spanned::span` here for `arm.expr` to account for outer + // attributes. + crate::matches::rewrite_match_body( + context, + &arm.expr, + &predicate_str, + nested_shape, + false, + arm.arrow.span.until(arm.expr.span()), + last_arm.is_some_and(|la| la == arm), + ) + } + } + }; + + let rw = try_rewrite()?; + // NB: there could be a comment between body and trailing comma. + Ok(recover_comment_removed(rw, arm.span(), context)) +} diff --git a/src/tools/rustfmt/src/parse/macros/cfg_if.rs b/src/tools/rustfmt/src/parse/macros/cfg_if.rs index 495f12c8f5d5d..08accda2fbd09 100644 --- a/src/tools/rustfmt/src/parse/macros/cfg_if.rs +++ b/src/tools/rustfmt/src/parse/macros/cfg_if.rs @@ -13,9 +13,13 @@ pub(crate) fn parse_cfg_if<'a>( psess: &'a ParseSess, mac: &'a ast::MacCall, ) -> Result, &'static str> { - match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(psess, mac))) { - Ok(Ok(items)) => Ok(items), - Ok(err @ Err(_)) => err, + let result = catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(psess, mac))); + let dcx = psess.inner().dcx(); + let recovered = dcx.has_errors().is_some(); + dcx.reset_err_count(); + match result { + Ok(Ok(_)) if recovered => Err("cfg_if! parsed with recovery"), + Ok(res) => res, Err(..) => Err("failed to parse cfg_if!"), } } diff --git a/src/tools/rustfmt/src/parse/macros/cfg_select.rs b/src/tools/rustfmt/src/parse/macros/cfg_select.rs index 5c5963320d6f7..6db647eaabb88 100644 --- a/src/tools/rustfmt/src/parse/macros/cfg_select.rs +++ b/src/tools/rustfmt/src/parse/macros/cfg_select.rs @@ -163,38 +163,57 @@ impl std::fmt::Debug for CfgSelectArm { } impl CfgSelectArm { - /// Is the cfg_select! arm written with two consecutive blocks. - /// For example `$predicate => {{}}`. If so, extract the inner block. - /// rustfmt will preserve the double block syntax. - pub(crate) fn double_block_inner(&self, context: &RewriteContext<'_>) -> Option<&ast::Expr> { - // In order to see if we can reach in and grab the inner block we'll - // check the following properties of the outer block: + /// Is the `cfg_select!` arm written with two consecutive blocks in a way that we can apply a + /// concise formatting happy path? For example: + /// + /// ```text + /// $predicate => {{}} + /// ``` + /// + /// If so, extract the inner block. rustfmt will preserve the double block syntax. + pub(crate) fn maybe_double_block_concise_formatting( + &self, + context: &RewriteContext<'_>, + ) -> Option<&ast::Expr> { + // To be able to safely use the concise double block `{{ ... }}` concise formatting, the + // outer block must satisfy all of the following properties: + // // 1. It has a single statement that's also a block // 2. It doesn't have a label // 3. It isn't an unsafe block // 4. It doesn't have any attributes - match &self.expr.kind { - ast::ExprKind::Block(b, label) - if b.stmts.len() == 1 + // 5. There are no comments between the outer blocks and the inner blocks, i.e. + // ``` + // { /* A */ { ... } /* B */ } + // ``` + let outer_expr = &self.expr; + match &outer_expr.kind { + ast::ExprKind::Block(outer_block, label) + if let [stmt] = outer_block.stmts.as_slice() && label.is_none() - && !is_unsafe_block(b) + && !is_unsafe_block(&outer_block) && self.expr.attrs.is_empty() => { - match &b.stmts[0].kind { - // This is where we check that the inner block's statement is also a block - ast::StmtKind::Expr(e) if matches!(e.kind, ast::ExprKind::Block(..)) => { - let pre_span = b.span.shrink_to_lo().between(e.span()); - let pre_snippet = context.snippet(pre_span).trim(); - - let post_span = e.span().shrink_to_hi().between(b.span.shrink_to_hi()); - let post_snippet = context.snippet(post_span).trim(); - - if !contains_comment(pre_snippet) && !contains_comment(post_snippet) { - // To prevent comment loss between the blocks we only want to return - // the inner block if there aren't any pre / post comments. - Some(e) - } else { + match &stmt.kind { + // The inner expr has to be a block. + ast::StmtKind::Expr(e) + if let ast::ExprKind::Block(ref inner_block, _inner_label) = e.kind => + { + // Check for comments in between outer/inner blocks. If there are in-between + // comments, we should not apply the concise formatting. Let's call them + // ``` + // { { ... } } + // ^--- ^--- + // pre_sp post_sp + // ``` + let pre_sp = outer_block.span.until(inner_block.span); + let post_sp = outer_block.span.with_lo(inner_block.span.hi()); + if contains_comment(context.snippet(pre_sp)) + || contains_comment(context.snippet(post_sp)) + { None + } else { + Some(e) } } _ => None, diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs index 96b96700a9288..5d5be709e5fb5 100644 --- a/src/tools/rustfmt/src/test/mod.rs +++ b/src/tools/rustfmt/src/test/mod.rs @@ -44,7 +44,7 @@ const FILE_SKIP_LIST: &[&str] = &[ "issue-3253/bar.rs", "issue-3253/paths", // This directory is directly tested by format_files_find_new_files_via_cfg_select - "cfg_select", + "cfg_select_multifile", // These files and directory are a part of modules defined inside `cfg_attr(..)`. "cfg_mod/dir", "cfg_mod/bar.rs", @@ -575,8 +575,8 @@ fn format_files_find_new_files_via_cfg_select() { // transparent mod discovery, and to ensure that it does not suffer // from a similar issue as cfg_if! support did with issue-4656. let files = vec![ - Path::new("tests/source/cfg_select/lib2.rs"), - Path::new("tests/source/cfg_select/lib.rs"), + Path::new("tests/source/cfg_select_multifile/lib2.rs"), + Path::new("tests/source/cfg_select_multifile/lib.rs"), ]; let config = Config::default(); diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 28c2740444822..6451595449046 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1015,14 +1015,6 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Ok("...".to_owned()), - ast::TyKind::FieldOf(ref ty, ref variant, ref field) => { - let ty = ty.rewrite_result(context, shape)?; - if let Some(variant) = variant { - Ok(format!("builtin # field_of({ty}, {variant}.{field})")) - } else { - Ok(format!("builtin # field_of({ty}, {field})")) - } - } ast::TyKind::UnsafeBinder(ref binder) => { let mut result = String::new(); if binder.generic_params.is_empty() { @@ -1049,7 +1041,10 @@ impl Rewrite for ast::Ty { result.push_str(&rewrite); Ok(result) } - ast::TyKind::Pat(..) | ast::TyKind::View(..) | ast::TyKind::GcaMacro(..) => { + ast::TyKind::FieldOf(..) + | ast::TyKind::GcaMacro(..) + | ast::TyKind::Pat(..) + | ast::TyKind::View(..) => { // These don't normally occur in the AST because macros aren't expanded. However, // rustfmt tries to parse macro arguments when formatting macros, so it's not // totally impossible for rustfmt to come across these nodes when formatting a file. diff --git a/src/tools/rustfmt/tests/config/issue_4660/Cargo.toml b/src/tools/rustfmt/tests/config/issue_4660/Cargo.toml index c716e9d057548..c9ddf1793b88f 100644 --- a/src/tools/rustfmt/tests/config/issue_4660/Cargo.toml +++ b/src/tools/rustfmt/tests/config/issue_4660/Cargo.toml @@ -1,2 +1,6 @@ -[workspace] -members = ["inner_lib"] +[package] +name = "inner_lib" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/src/tools/rustfmt/tests/config/issue_4660/configs/rustfmt.hard_tabs.toml b/src/tools/rustfmt/tests/config/issue_4660/configs/rustfmt.hard_tabs.toml new file mode 100644 index 0000000000000..218e203215e94 --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/configs/rustfmt.hard_tabs.toml @@ -0,0 +1 @@ +hard_tabs = true diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/.rustfmt.unstable.toml b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/.rustfmt.unstable.toml deleted file mode 100644 index c7ad93bafe36c..0000000000000 --- a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/.rustfmt.unstable.toml +++ /dev/null @@ -1 +0,0 @@ -disable_all_formatting = true diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/Cargo.toml b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/Cargo.toml deleted file mode 100644 index bb6a80cd0ce9b..0000000000000 --- a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "inner_bin" -version = "0.1.0" -edition = "2021" - -[dependencies] diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/src/main.rs b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/src/main.rs deleted file mode 100644 index 21c34773b8af5..0000000000000 --- a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/src/main.rs +++ /dev/null @@ -1 +0,0 @@ -fn main(){println!("Hello, world!")} diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/Cargo.toml b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/Cargo.toml deleted file mode 100644 index c9ddf1793b88f..0000000000000 --- a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "inner_lib" -version = "0.1.0" -edition = "2021" - -[dependencies] diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/rustfmt.toml b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/rustfmt.toml deleted file mode 100644 index c7ad93bafe36c..0000000000000 --- a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -disable_all_formatting = true diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/src/lib.rs b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/src/lib.rs deleted file mode 100644 index 42375c99d2c97..0000000000000 --- a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn add(left:u64,right:u64)->u64{left+right} diff --git a/src/tools/rustfmt/tests/config/issue_4660/rustfmt.toml b/src/tools/rustfmt/tests/config/issue_4660/rustfmt.toml new file mode 100644 index 0000000000000..8a1751f67698f --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/rustfmt.toml @@ -0,0 +1 @@ +use_field_init_shorthand = true diff --git a/src/tools/rustfmt/tests/config/issue_4660/src/lib.rs b/src/tools/rustfmt/tests/config/issue_4660/src/lib.rs new file mode 100644 index 0000000000000..012fb0f850f8c --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/src/lib.rs @@ -0,0 +1,2 @@ +mod longhand_field_init; +mod with_spaces; diff --git a/src/tools/rustfmt/tests/config/issue_4660/src/longhand_field_init.rs b/src/tools/rustfmt/tests/config/issue_4660/src/longhand_field_init.rs new file mode 100644 index 0000000000000..87ee30033c955 --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/src/longhand_field_init.rs @@ -0,0 +1,10 @@ +struct Foo { + x: u32, + y: u32, +} +fn foo() -> Foo { + let x = 1; + let y = 2; + + Foo { x: x, y: y } +} diff --git a/src/tools/rustfmt/tests/config/issue_4660/src/with_spaces.rs b/src/tools/rustfmt/tests/config/issue_4660/src/with_spaces.rs new file mode 100644 index 0000000000000..211d2de3c959e --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/src/with_spaces.rs @@ -0,0 +1,3 @@ +fn f() { + // comment +} diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs index 5fbf64d8862c1..c2e0c544c2b9c 100644 --- a/src/tools/rustfmt/tests/rustfmt/main.rs +++ b/src/tools/rustfmt/tests/rustfmt/main.rs @@ -1,13 +1,12 @@ //! Integration tests for rustfmt. -use indoc::panicdoc; use std::env; -use std::fs::{File, remove_file}; +use std::fs::File; use std::io::Write; use std::path::Path; use std::process::{Command, Stdio}; -use rustfmt_config_proc_macro::{nightly_only_test, rustfmt_only_ci_test, stable_only_test}; +use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test, rustfmt_only_ci_test}; /// Run the rustfmt executable with environment vars set and return its output. /// If `input` is given, it is piped to the executable's stdin. @@ -16,7 +15,7 @@ fn rustfmt_with_extra( working_dir: Option<&str>, envs: &[(&str, &str)], input: Option<&str>, -) -> (String, String) { +) -> (String, String, i32) { let rustfmt_exe = env!("CARGO_BIN_EXE_rustfmt"); let bin_dir = Path::new(rustfmt_exe).parent().unwrap(); @@ -48,96 +47,142 @@ fn rustfmt_with_extra( Ok(output) => ( String::from_utf8(output.stdout).expect("utf-8"), String::from_utf8(output.stderr).expect("utf-8"), + output.status.code().expect("should exit with a status"), ), Err(e) => panic!("failed to run `{cmd:?} {args:?}`: {e}"), } } -fn rustfmt(args: &[&str]) -> (String, String) { +fn rustfmt(args: &[&str]) -> (String, String, i32) { rustfmt_with_extra(args, None, &[], None) } -macro_rules! assert_that { - ($args:expr, $($check:ident $check_args:tt)&&+) => { - let (stdout, stderr) = rustfmt($args); - if $(!stdout.$check$check_args && !stderr.$check$check_args)||* { - let args = $args; - let expected = stringify!($( $check$check_args )&&*); - panicdoc! {" - Output not expected for rustfmt {args:?} - expected: {expected} - actual stdout: - {stdout} - actual stderr: - {stderr}", - }; - } - }; +#[test] +fn print_config_errors_on_unknown_option() { + let args = &["--print-config", "unknown"]; + + let (stdout, stderr, exit_code) = rustfmt(args); + + assert_eq!(&stdout, ""); + assert!( + stderr.contains("Unknown print-config option"), + "expected helpful error message, got: {stderr}" + ); + assert_eq!(exit_code, 1); } -#[rustfmt_only_ci_test] #[test] -fn print_config() { - assert_that!( - &["--print-config", "unknown"], - starts_with("Unknown print-config option") +fn print_config_default() { + let args = &["--print-config", "default"]; + let (stdout, stderr, exit_code) = rustfmt(args); + + assert!( + stdout.contains("max_width = 100"), + "expected stdout to contain a default config, got: {stdout}", ); - assert_that!(&["--print-config", "default"], contains("max_width = 100")); - assert_that!(&["--print-config", "minimal"], contains("PATH required")); - assert_that!( - &["--print-config", "minimal", "minimal-config"], - contains("doesn't work with standard input.") + assert_eq!(&stderr, ""); + assert_eq!(exit_code, 0) +} + +#[test] +fn print_config_errors_minimal_with_no_path() { + let args = &["--print-config", "minimal"]; + + let (stdout, stderr, exit_code) = rustfmt(args); + + assert_eq!(stdout, ""); + assert_eq!( + stderr, "The `--print-config=minimal` option requires an output path to write to\n", + "expected helpful error message, got: {stderr}" ); + assert_eq!(exit_code, 1) +} - let (stdout, stderr) = rustfmt(&[ +#[test] +fn print_config_errors_minimal_without_input_file() { + let args = &["--print-config", "minimal", "minimal.toml"]; + + let (stdout, stderr, exit_code) = rustfmt(args); + + assert_eq!(&stdout, ""); + assert_eq!( + stderr, "The `--print-config=minimal` option doesn't work with standard input.\n", + "expected helpful error message, got: {stderr}" + ); + assert_eq!(exit_code, 1); +} + +#[rustfmt_only_ci_test] +#[test] +fn print_config_writes_to_file() { + let out_file = tempfile::tempdir().unwrap().keep().join("minimal.toml"); + + let args = &[ + "--config-path", + Path::new("tests/config/disable_all_formatting.toml") + .to_str() + .unwrap(), "--print-config", "minimal", - "minimal-config", + out_file.to_str().unwrap(), "src/shape.rs", - ]); + ]; + + let (stdout, stderr, exit_code) = rustfmt(args); + + assert_eq!(stderr, ""); + assert!(out_file.exists(), "stdout:\n{stdout}\nstderr:\n{stderr}"); + assert_eq!(exit_code, 0); +} + +#[test] +fn print_config_merges_override_from_args() { + let args = &[ + "--print-config", + "current", + ".", + "--config=color=Never,edition=2018", + ]; + + let (stdout, stderr, exit_code) = rustfmt(args); + + assert_eq!(stderr, ""); assert!( - Path::new("minimal-config").exists(), - "stdout:\n{stdout}\nstderr:\n{stderr}" + stdout.contains(r#"color = "Never""#) && stdout.contains(r#"edition = "2018""#), + "expected overrides in stdout, got: {stdout}", ); - remove_file("minimal-config").unwrap(); + assert_eq!(exit_code, 0); } -#[rustfmt_only_ci_test] #[test] -fn inline_config() { - // single invocation - assert_that!( - &[ - "--print-config", - "current", - ".", - "--config=color=Never,edition=2018" - ], - contains("color = \"Never\"") && contains("edition = \"2018\"") - ); +fn print_config_merges_multiple_overrides_from_args() { + let args = &[ + "--print-config", + "current", + ".", + "--config", + "color=never,edition=2018", + "--config", + "color=always,format_strings=true", + ]; + + let (stdout, stderr, exit_code) = rustfmt(args); - // multiple overriding invocations - assert_that!( - &[ - "--print-config", - "current", - ".", - "--config", - "color=never,edition=2018", - "--config", - "color=always,format_strings=true" - ], - contains("color = \"Always\"") - && contains("edition = \"2018\"") - && contains("format_strings = true") + assert_eq!(stderr, ""); + assert!( + stdout.contains(r#"color = "Always""#) + && stdout.contains(r#"edition = "2018""#) + && stdout.contains("format_strings = true"), + "expected overrides in stdout, got: {stdout}", ); + assert_eq!(exit_code, 0); } #[stable_only_test] #[test] fn rustfmt_usage_text() { let args = ["--help"]; - let (stdout, _) = rustfmt(&args); + let (stdout, _, exit_code) = rustfmt(&args); insta::assert_snapshot!(stdout, @" Format Rust code @@ -179,13 +224,14 @@ fn rustfmt_usage_text() { -h, --help [=TOPIC] Show this message or help about a specific topic: `config` "); + assert_eq!(exit_code, 0); } #[nightly_only_test] #[test] fn rustfmt_nightly_usage_text() { let args = ["--help"]; - let (stdout, _) = rustfmt(&args); + let (stdout, _, exit_code) = rustfmt(&args); insta::assert_snapshot!(stdout, @" Format Rust code @@ -239,6 +285,7 @@ fn rustfmt_nightly_usage_text() { -h, --help [=TOPIC] Show this message or help about a specific topic: `config` or `file-lines` "); + assert_eq!(exit_code, 0); } #[test] @@ -253,36 +300,44 @@ fn mod_resolution_error_multiple_candidate_files() { ); let args = ["tests/mod-resolver/issue-5167/src/lib.rs"]; - let (_stdout, stderr) = rustfmt(&args); - assert!(stderr.contains(&error_message)) + let (_stdout, stderr, exit_code) = rustfmt(&args); + + assert!(stderr.contains(&error_message)); + assert_eq!(exit_code, 1); } #[test] fn mod_resolution_error_sibling_module_not_found() { let args = ["tests/mod-resolver/module-not-found/sibling_module/lib.rs"]; - let (_stdout, stderr) = rustfmt(&args); + let (_stdout, stderr, exit_code) = rustfmt(&args); + // Module resolution fails because we're unable to find `a.rs` in the same directory as lib.rs - assert!(stderr.contains("a.rs does not exist")) + assert!(stderr.contains("a.rs does not exist")); + assert_eq!(exit_code, 1); } #[test] fn mod_resolution_error_relative_module_not_found() { let args = ["tests/mod-resolver/module-not-found/relative_module/lib.rs"]; - let (_stdout, stderr) = rustfmt(&args); + let (_stdout, stderr, exit_code) = rustfmt(&args); + // The file `./a.rs` and directory `./a` both exist. // Module resolution fails because we're unable to find `./a/b.rs` #[cfg(not(windows))] assert!(stderr.contains("a/b.rs does not exist")); #[cfg(windows)] assert!(stderr.contains("a\\b.rs does not exist")); + assert_eq!(exit_code, 1); } #[test] fn mod_resolution_error_path_attribute_does_not_exist() { let args = ["tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs"]; - let (_stdout, stderr) = rustfmt(&args); + let (_stdout, stderr, exit_code) = rustfmt(&args); + // The path attribute points to a file that does not exist assert!(stderr.contains("does_not_exist.rs does not exist")); + assert_eq!(exit_code, 1); } #[test] @@ -294,29 +349,33 @@ fn rustfmt_emits_error_on_line_overflow_true() { "tests/cargo-fmt/source/issue_3164/src/main.rs", ]; - let (_stdout, stderr) = rustfmt(&args); + let (_stdout, stderr, exit_code) = rustfmt(&args); assert!(stderr.contains( "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)" - )) + )); + assert_eq!(exit_code, 1); } #[test] #[allow(non_snake_case)] fn dont_emit_ICE() { - let files = [ - "tests/target/issue_5728.rs", - "tests/target/issue_5729.rs", - "tests/target/issue-5885.rs", - "tests/target/issue_6082.rs", - "tests/target/issue_6069.rs", - "tests/target/issue-6105.rs", + let file_args_pairs = [ + ("tests/target/issue_5728.rs", vec![]), + ("tests/target/issue_5729.rs", vec![]), + ("tests/target/issue-5885.rs", vec![]), + ("tests/target/issue_6082.rs", vec![]), + ("tests/target/issue_6069.rs", vec![]), + ("tests/target/issue-6105.rs", vec!["--edition=2021"]), ]; let panic_re = regex::Regex::new("thread.*panicked").unwrap(); - for file in files { - let args = [file]; - let (_stdout, stderr) = rustfmt(&args); + for (file, mut args) in file_args_pairs { + args.push(file); + + let (_stdout, stderr, exit_code) = rustfmt(&args); + assert!(!panic_re.is_match(&stderr)); + assert_eq!(exit_code, 0); } } @@ -332,8 +391,10 @@ fn rustfmt_emits_error_when_control_brace_style_is_always_next_line() { "tests/target/issue_5912.rs", ]; - let (_stdout, stderr) = rustfmt(&args); - assert!(!stderr.contains("error[internal]: left behind trailing whitespace")) + let (_stdout, stderr, exit_code) = rustfmt(&args); + + assert!(!stderr.contains("error[internal]: left behind trailing whitespace")); + assert_eq!(exit_code, 0); } #[nightly_only_test] @@ -343,9 +404,11 @@ fn rustfmt_generates_no_error_if_failed_format_code_in_doc_comments() { let file = "tests/target/issue-6109.rs"; let args = ["--config", "format_code_in_doc_comments=true", file]; - let (stdout, stderr) = rustfmt(&args); + let (stdout, stderr, exit_code) = rustfmt(&args); + assert!(stderr.is_empty()); assert!(stdout.is_empty()); + assert_eq!(exit_code, 0); } #[test] @@ -353,43 +416,123 @@ fn rustfmt_error_improvement_regarding_invalid_toml() { // See also https://github.com/rust-lang/rustfmt/issues/6302 let invalid_toml_config = "tests/config/issue-6302.toml"; let args = ["--config-path", invalid_toml_config]; - let (_stdout, stderr) = rustfmt(&args); + let (_stdout, stderr, exit_code) = rustfmt(&args); let toml_path = Path::new(invalid_toml_config).canonicalize().unwrap(); let expected_error_message = format!("The file `{}` failed to parse", toml_path.display()); assert!(stderr.contains(&expected_error_message)); + assert_eq!(exit_code, 1); } #[test] fn config_path_walks_parent_directories_with_dir_name() { - let src_dir = "tests/config/issue_4660/inner_lib/src"; - let src_file = src_dir.to_owned() + "/lib.rs"; - let args = ["--config-path", src_dir, "--check", &src_file]; - let (stdout, stderr) = rustfmt(&args); + let src_dir = Path::new("tests/config/issue_4660/src"); + let src_file = src_dir.join("longhand_field_init.rs"); + let args = [ + "--config-path", + &src_dir.to_str().unwrap(), + "--check", + "--files-with-diff", + &src_file.to_str().unwrap(), + ]; + + let (stdout, stderr, exit_code) = rustfmt(&args); assert_eq!(stderr, ""); - // Due to `disable_all_formatting = true` in `tests/config/issue_4660/inner_lib/rustfmt.toml`, - // the source file should not be modified. - assert_eq!(stdout, ""); + assert_eq!( + stdout, + format!("{}\n", src_file.canonicalize().unwrap().display()), + // this config sets `use_field_init_shorthand = true` + "we should walk up to tests/config/issue_4660/rustfmt.toml" + ); + assert_eq!(exit_code, 1); } +// on unix [`std::env::home_dir`] reads the `HOME` env var. +#[cfg(unix)] #[test] -fn config_path_does_not_walk_parent_directories_with_toml_name() { - let src_dir = "tests/config/issue_4660/inner_bin/src"; - let toml_file = src_dir.to_owned() + "/.rustfmt.unstable.toml"; - let src_file = src_dir.to_owned() + "/main.rs"; - let args = ["--config-path", &toml_file, "--check", &src_file]; - let (stdout, stderr) = rustfmt(&args); +fn config_path_searches_home_dir_when_dir_path_no_resolve() { + // move the src file to a tempdir, since we'll search up from there looking for the config file + // so we need to avoid using a path within this repo + let new_src_dir = tempfile::tempdir().unwrap().keep(); + let src_file = Path::new("tests/config/issue_4660/src/with_spaces.rs"); + let new_src_path = new_src_dir.join("with_spaces.rs"); + let config_file = Path::new("tests/config/issue_4660/configs/rustfmt.hard_tabs.toml"); + let homedir_path = tempfile::tempdir().unwrap().keep(); + + std::fs::copy(&config_file, homedir_path.join("rustfmt.toml")).unwrap(); + std::fs::copy(&src_file, &new_src_path).unwrap(); + + let args = [ + "--check", + "--files-with-diff", + &new_src_path.to_str().unwrap(), + ]; + let env = &[("HOME", homedir_path.to_str().unwrap())]; + + let (stdout, stderr, exit_code) = rustfmt_with_extra(&args, None, env, None); + + assert_eq!(stderr, ""); + assert_eq!( + stdout, + format!("{}\n", new_src_path.canonicalize().unwrap().display()), + "should search in HOME" + ); + assert_eq!(exit_code, 1); +} + +// The behaviour [`dirs::config_dir`] is os-dependent, so pick one and test to that. +#[cfg(target_os = "linux")] +#[test] +fn config_path_searches_config_dir_when_dir_path_no_resolve() { + // move the src file to a tempdir, since we'll search up from there looking for the config file + let new_src_dir = tempfile::tempdir().unwrap().keep(); + let src_file = Path::new("tests/config/issue_4660/src/with_spaces.rs"); + let new_src_path = new_src_dir.join("with_spaces.rs"); + let config_file = Path::new("tests/config/issue_4660/configs/rustfmt.hard_tabs.toml"); + let xdg_config_dir_path = tempfile::tempdir().unwrap().keep(); + let config_path = xdg_config_dir_path.join("rustfmt/rustfmt.toml"); + + std::fs::create_dir(&config_path.parent().unwrap()).unwrap(); + std::fs::copy(&config_file, config_path).unwrap(); + std::fs::copy(&src_file, &new_src_path).unwrap(); + + let args = [ + "--check", + "--files-with-diff", + &new_src_path.to_str().unwrap(), + ]; + let env = &[("XDG_CONFIG_HOME", xdg_config_dir_path.to_str().unwrap())]; + + let (stdout, stderr, exit_code) = rustfmt_with_extra(&args, None, env, None); + + assert_eq!(stderr, ""); + assert_eq!( + stdout, + format!("{}\n", new_src_path.canonicalize().unwrap().display()), + "should search in XDG_CONFIG_HOME" + ); + assert_eq!(exit_code, 1); +} + +#[test] +fn config_path_errors_when_invalid_file_given() { + let src_file = "not_a_file.rs"; + let config_file = "also_not_a_file.toml"; + let args = ["--config-path", &config_file, "--check", &src_file]; + + let (stdout, stderr, exit_code) = rustfmt(&args); assert_eq!( stderr, format!( "Error: unable to find a config file for the given path: `{}`\n", - Path::new(&toml_file).display(), + Path::new(&config_file).display(), ) ); assert_eq!(stdout, ""); + assert_eq!(exit_code, 1); } #[test] @@ -416,11 +559,12 @@ fn rustfmt_allow_not_a_dir_errors() { let args = [empty_rs.to_str().unwrap()]; let envs = &[("HOME", fake_home_str)]; - let (stdout, stderr) = rustfmt_with_extra(&args, Some(fake_home_str), envs, None); + let (stdout, stderr, exit_code) = rustfmt_with_extra(&args, Some(fake_home_str), envs, None); // Should pass without any errors assert_eq!(stdout, ""); assert_eq!(stderr, ""); + assert_eq!(exit_code, 0); } // FIXME(cfg_select): ungate when `cfg_select!` formatting can be enabled on stable. @@ -430,8 +574,11 @@ fn cfg_select_parser_recovery_ice_7087() { // See also https://github.com/rust-lang/rustfmt/issues/7087 let source = "cfg_select! { true => { fn foo {} } }\n"; let panic_re = regex::Regex::new("thread.*panicked").unwrap(); - let (stdout, stderr) = rustfmt_with_extra(&[], None, &[], Some(source)); + + let (stdout, stderr, exit_code) = rustfmt_with_extra(&[], None, &[], Some(source)); + assert!(!panic_re.is_match(&stderr)); // Invalid arm should cause `cfg_select!` to be re-emitted unmodified. assert_eq!(source, stdout); + assert_eq!(exit_code, 0); } diff --git a/src/tools/rustfmt/tests/source/cfg-if-error-count-leak.rs b/src/tools/rustfmt/tests/source/cfg-if-error-count-leak.rs new file mode 100644 index 0000000000000..d5e289ec95b12 --- /dev/null +++ b/src/tools/rustfmt/tests/source/cfg-if-error-count-leak.rs @@ -0,0 +1,12 @@ +//@ rustfmt-show_parse_errors: false + +cfg_if::cfg_if! { + if #[cfg(unix)] { + fn foo {} + } +} + +fn main() { + foo!(1 + 2); + foo!(1 + 2); +} diff --git a/src/tools/rustfmt/tests/source/cfg_select.rs b/src/tools/rustfmt/tests/source/cfg_select/cfg_select.rs similarity index 98% rename from src/tools/rustfmt/tests/source/cfg_select.rs rename to src/tools/rustfmt/tests/source/cfg_select/cfg_select.rs index ca6abc8aa4af2..d6dc391dd564f 100644 --- a/src/tools/rustfmt/tests/source/cfg_select.rs +++ b/src/tools/rustfmt/tests/source/cfg_select/cfg_select.rs @@ -327,7 +327,7 @@ cfg_select! { any(true, /* comment */ true, true, // true, true, ) - // comment before arrow + /* comment before arrow */ => {} not(false // comment @@ -339,12 +339,12 @@ cfg_select! { ) => "any" } -// comments before and after the `=>` get dropped right now +// comments before and after the `=>` are kept cfg_select! { any(true, true, true, true, ) - // commetn before arrow + /* comment before arrow */ => {} not(false @@ -357,6 +357,15 @@ cfg_select! { "any" } +// FIXME: not formatted, a line comment before `=>` would comment out the `=>` +cfg_select! { + any(true, + true, true, + true, ) + // line comment before arrow + => {} +} + // A bunch of mixed predicates cfg_select! { @@ -752,7 +761,7 @@ cfg_select! { any(true, /* comment */ true, true, // true, true, ) - // comment before arrow + /* comment before arrow */ => {} not(false // comment @@ -764,12 +773,12 @@ cfg_select! { ) => "any" } -// comments before and after the `=>` get dropped right now +// comments before and after the `=>` are kept cfg_select! { any(true, true, true, true, ) - // commetn before arrow + /* comment before arrow */ => {} not(false diff --git a/src/tools/rustfmt/tests/source/cfg_select_edge_cases.rs b/src/tools/rustfmt/tests/source/cfg_select/cfg_select_edge_cases.rs similarity index 82% rename from src/tools/rustfmt/tests/source/cfg_select_edge_cases.rs rename to src/tools/rustfmt/tests/source/cfg_select/cfg_select_edge_cases.rs index 3c591d3afd5a3..8bf6a3240a945 100644 --- a/src/tools/rustfmt/tests/source/cfg_select_edge_cases.rs +++ b/src/tools/rustfmt/tests/source/cfg_select/cfg_select_edge_cases.rs @@ -79,6 +79,77 @@ fn cfg_select_comments_that_might_get_lost() { // No trailing comma in source three_blocks_exclamation_point => {{/* a */{ b; c } /* d */}} } + + cfg_select! { + _ => { { x } /* after */ } + } + + cfg_select! { + _ => { { x } // after newline + } + } + + cfg_select! { + _ => /* between */ {{ x }} + } + + cfg_select! { + _ => // between trailing + {{ x }} + } + + // Trailing comma + cfg_select! { + _ => /* between */ {{ x }}, + } + cfg_select! { + _ => /* between */ {{ a; b }}, + } + + cfg_select! { + _ => /* between */ {{ a; b }} + } + + cfg_select! { + _ => /* multi + line */ {{ x }} + } + + // Comments before `=>` + cfg_select! { + _ /* before arrow */ => {{ x }} + _ /* before arrow */ => x, + _ /* before arrow */ => /* after arrow */ {{ x }} + all(target_os = "linux", target_arch = "x86_64", target_env = "gnu") /* long comment before arrow */ => {{ x }} + _ /* before arrow */ => {} + } + + cfg_select! { + // Not formatted: a line comment before `=>`. + c // before arrow + => x, + } + + cfg_select! { + _ => x /* before comma */, + } + + cfg_select! { + _ => {{ x }} /* before comma */, + } + + cfg_select! { + a => b, + } + + cfg_select! { + _ => xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /* too long */, + } + + cfg_select! { + _ => x // trailing newline + , + } } fn other_cfg_select_cases() { @@ -203,6 +274,23 @@ fn other_cfg_select_cases() { #[inline] || { }} }; + + cfg_select! { + _ => /* before attr */ #[attr] { z } + } + + cfg_select! { + _ => #[attr] /* after attr */ { z } + } + + cfg_select! { + _ => // line comment before attr + #[attr] { z } + } + + cfg_select! { + _ => /* before attr */ #[attr] /* after attr */ { z } + } } fn long_predicate() { diff --git a/src/tools/rustfmt/tests/source/cfg_select_stable.rs b/src/tools/rustfmt/tests/source/cfg_select/cfg_select_stable.rs similarity index 100% rename from src/tools/rustfmt/tests/source/cfg_select_stable.rs rename to src/tools/rustfmt/tests/source/cfg_select/cfg_select_stable.rs diff --git a/src/tools/rustfmt/tests/source/cfg-select-valid-then-invalid-item-error-count-leak.rs b/src/tools/rustfmt/tests/source/cfg_select/cfg_select_valid_then_invalid_item_error_count_leak.rs similarity index 100% rename from src/tools/rustfmt/tests/source/cfg-select-valid-then-invalid-item-error-count-leak.rs rename to src/tools/rustfmt/tests/source/cfg_select/cfg_select_valid_then_invalid_item_error_count_leak.rs diff --git a/src/tools/rustfmt/tests/source/cfg_select/control_brace_style_always_next_line.rs b/src/tools/rustfmt/tests/source/cfg_select/control_brace_style_always_next_line.rs new file mode 100644 index 0000000000000..a12391c20298d --- /dev/null +++ b/src/tools/rustfmt/tests/source/cfg_select/control_brace_style_always_next_line.rs @@ -0,0 +1,100 @@ +//@ rustfmt-unstable: true +//@ rustfmt-edition: 2024 +//@ rustfmt-control_brace_style: AlwaysNextLine + +cfg_select! { + _ => { x } +} + +cfg_select! { + _ => { + x + } +} + +cfg_select! { + _ => {{ x }} +} + +cfg_select! { + _ => {{ + x + }} +} + +cfg_select! { + _ => unsafe { x } +} + +cfg_select! { + _ => { + unsafe { x } + } +} + +cfg_select! { + _ => // line comment + {{ x }} +} + +cfg_select! { + _ => // line comment + { a; b } +} + +cfg_select! { + _ => /* after */ {{ x }} +} + +cfg_select! { + _ => /* after */ {a; b} +} + +cfg_select! { + _ => /* after + multiline */ {{ x }} +} + +cfg_select! { + _ => /* after + multiline */ { a; b } +} + +cfg_select! { + _ => /* after */ {{ + x + }} +} + +cfg_select! { + _ => /* after */ { + a; b + } +} + +cfg_select! { + _ /* this comment is _very_ long but brace should fit ---------------------------------- */ => { a; b } +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 101 columns incl. arrow ------------------- */ => { a; b } +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 100 columns itself -------------------------- */ => { a; b } +} + +cfg_select! { + _ /* this comment is _very_ long but shouldn't change next next line --------------------- */ => + {{ ThisLineIsShort }} +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 101 columns incl. arrow ------------------- */ => + {{ ThisLineIsShort }} +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 100 columns itself -------------------------- */ => + {{ ThisLineIsShort }} +} diff --git a/src/tools/rustfmt/tests/source/cfg_select/control_brace_style_always_same_line.rs b/src/tools/rustfmt/tests/source/cfg_select/control_brace_style_always_same_line.rs new file mode 100644 index 0000000000000..cda500f61afe6 --- /dev/null +++ b/src/tools/rustfmt/tests/source/cfg_select/control_brace_style_always_same_line.rs @@ -0,0 +1,100 @@ +//@ rustfmt-unstable: true +//@ rustfmt-control_brace_style: AlwaysSameLine +// ^ NB: default value + +cfg_select! { + _ => { x } +} + +cfg_select! { + _ => { + x + } +} + +cfg_select! { + _ => {{ x }} +} + +cfg_select! { + _ => {{ + x + }} +} + +cfg_select! { + _ => unsafe { x } +} + +cfg_select! { + _ => { + unsafe { x } + } +} + +cfg_select! { + _ => // line comment + {{ x }} +} + +cfg_select! { + _ => // line comment + { a; b } +} + +cfg_select! { + _ => /* after */ {{ x }} +} + +cfg_select! { + _ => /* after */ {a; b} +} + +cfg_select! { + _ => /* after + multiline */ {{ x }} +} + +cfg_select! { + _ => /* after + multiline */ { a; b } +} + +cfg_select! { + _ => /* after */ {{ + x + }} +} + +cfg_select! { + _ => /* after */ { + a; b + } +} + +cfg_select! { + _ /* this comment is _very_ long but brace should fit ---------------------------------- */ => { a; b } +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 101 columns incl. arrow ------------------- */ => { a; b } +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 100 columns itself -------------------------- */ => { a; b } +} + +cfg_select! { + _ /* this comment is _very_ long but shouldn't change next next line --------------------- */ => + {{ ThisLineIsShort }} +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 101 columns incl. arrow ------------------- */ => + {{ ThisLineIsShort }} +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 100 columns itself -------------------------- */ => + {{ ThisLineIsShort }} +} diff --git a/src/tools/rustfmt/tests/source/issue_7045.rs b/src/tools/rustfmt/tests/source/cfg_select/issue_7045.rs similarity index 100% rename from src/tools/rustfmt/tests/source/issue_7045.rs rename to src/tools/rustfmt/tests/source/cfg_select/issue_7045.rs diff --git a/src/tools/rustfmt/tests/source/issue_7088_stable.rs b/src/tools/rustfmt/tests/source/cfg_select/issue_7088_stable.rs similarity index 100% rename from src/tools/rustfmt/tests/source/issue_7088_stable.rs rename to src/tools/rustfmt/tests/source/cfg_select/issue_7088_stable.rs diff --git a/src/tools/rustfmt/tests/source/issue_7088_unstable.rs b/src/tools/rustfmt/tests/source/cfg_select/issue_7088_unstable.rs similarity index 100% rename from src/tools/rustfmt/tests/source/issue_7088_unstable.rs rename to src/tools/rustfmt/tests/source/cfg_select/issue_7088_unstable.rs diff --git a/src/tools/rustfmt/tests/source/cfg_select/issue_7209.rs b/src/tools/rustfmt/tests/source/cfg_select/issue_7209.rs new file mode 100644 index 0000000000000..4c06baa145027 --- /dev/null +++ b/src/tools/rustfmt/tests/source/cfg_select/issue_7209.rs @@ -0,0 +1,11 @@ +//@ rustfmt-unstable: true +//@ rustfmt-edition: 2024 + +fn gettid() -> u64 { + cfg_select! { + any(target_os = "solaris", target_os = "illumos") => { + // On Solaris and Illumos, the `pthread_t` is the OS TID. + unsafe { libc::pthread_self() as u64 } + } + } +} diff --git a/src/tools/rustfmt/tests/source/cfg_select/format_me_please_1.rs b/src/tools/rustfmt/tests/source/cfg_select_multifile/format_me_please_1.rs similarity index 100% rename from src/tools/rustfmt/tests/source/cfg_select/format_me_please_1.rs rename to src/tools/rustfmt/tests/source/cfg_select_multifile/format_me_please_1.rs diff --git a/src/tools/rustfmt/tests/source/cfg_select/format_me_please_2.rs b/src/tools/rustfmt/tests/source/cfg_select_multifile/format_me_please_2.rs similarity index 100% rename from src/tools/rustfmt/tests/source/cfg_select/format_me_please_2.rs rename to src/tools/rustfmt/tests/source/cfg_select_multifile/format_me_please_2.rs diff --git a/src/tools/rustfmt/tests/source/cfg_select/format_me_please_3.rs b/src/tools/rustfmt/tests/source/cfg_select_multifile/format_me_please_3.rs similarity index 100% rename from src/tools/rustfmt/tests/source/cfg_select/format_me_please_3.rs rename to src/tools/rustfmt/tests/source/cfg_select_multifile/format_me_please_3.rs diff --git a/src/tools/rustfmt/tests/source/cfg_select/format_me_please_4.rs b/src/tools/rustfmt/tests/source/cfg_select_multifile/format_me_please_4.rs similarity index 100% rename from src/tools/rustfmt/tests/source/cfg_select/format_me_please_4.rs rename to src/tools/rustfmt/tests/source/cfg_select_multifile/format_me_please_4.rs diff --git a/src/tools/rustfmt/tests/source/cfg_select/lib.rs b/src/tools/rustfmt/tests/source/cfg_select_multifile/lib.rs similarity index 100% rename from src/tools/rustfmt/tests/source/cfg_select/lib.rs rename to src/tools/rustfmt/tests/source/cfg_select_multifile/lib.rs diff --git a/src/tools/rustfmt/tests/source/cfg_select/lib2.rs b/src/tools/rustfmt/tests/source/cfg_select_multifile/lib2.rs similarity index 100% rename from src/tools/rustfmt/tests/source/cfg_select/lib2.rs rename to src/tools/rustfmt/tests/source/cfg_select_multifile/lib2.rs diff --git a/src/tools/rustfmt/tests/target/cfg-if-error-count-leak.rs b/src/tools/rustfmt/tests/target/cfg-if-error-count-leak.rs new file mode 100644 index 0000000000000..48ef7ddc3ba7a --- /dev/null +++ b/src/tools/rustfmt/tests/target/cfg-if-error-count-leak.rs @@ -0,0 +1,12 @@ +//@ rustfmt-show_parse_errors: false + +cfg_if::cfg_if! { + if #[cfg(unix)] { + fn foo {} + } +} + +fn main() { + foo!(1 + 2); + foo!(1 + 2); +} diff --git a/src/tools/rustfmt/tests/target/cfg_select.rs b/src/tools/rustfmt/tests/target/cfg_select/cfg_select.rs similarity index 96% rename from src/tools/rustfmt/tests/target/cfg_select.rs rename to src/tools/rustfmt/tests/target/cfg_select/cfg_select.rs index 1c2a1ed91a7e0..9d9bbfe0b4c9a 100644 --- a/src/tools/rustfmt/tests/target/cfg_select.rs +++ b/src/tools/rustfmt/tests/target/cfg_select/cfg_select.rs @@ -277,7 +277,8 @@ cfg_select! { true, /* comment */ true, true, // true, true, - ) => {} + ) + /* comment before arrow */ => {} not( false // comment @@ -288,13 +289,29 @@ cfg_select! { ) => "any", } -// comments before and after the `=>` get dropped right now +// comments before and after the `=>` are kept cfg_select! { - any(true, true, true, true,) => {} + any(true, true, true, true,) + /* comment before arrow */ => {} - not(false) => {} + not(false) => + /* comment before opening brace */ + {} - any(false) => "any", + any(false) => + // comment before brace + { + "any" + } +} + +// FIXME: not formatted, a line comment before `=>` would comment out the `=>` +cfg_select! { + any(true, + true, true, + true, ) + // line comment before arrow + => {} } // A bunch of mixed predicates @@ -689,7 +706,8 @@ mod nested { true, /* comment */ true, true, // true, true, - ) => {} + ) + /* comment before arrow */ => {} not( false // comment @@ -700,13 +718,20 @@ mod nested { ) => "any", } - // comments before and after the `=>` get dropped right now + // comments before and after the `=>` are kept cfg_select! { - any(true, true, true, true,) => {} + any(true, true, true, true,) + /* comment before arrow */ => {} - not(false) => {} + not(false) => + /* comment before opening brace */ + {} - any(false) => "any", + any(false) => + // comment before brace + { + "any" + } } // A bunch of mixed predicates diff --git a/src/tools/rustfmt/tests/target/cfg_select_edge_cases.rs b/src/tools/rustfmt/tests/target/cfg_select/cfg_select_edge_cases.rs similarity index 80% rename from src/tools/rustfmt/tests/target/cfg_select_edge_cases.rs rename to src/tools/rustfmt/tests/target/cfg_select/cfg_select_edge_cases.rs index dec05d032e316..ea6eaf9205693 100644 --- a/src/tools/rustfmt/tests/target/cfg_select_edge_cases.rs +++ b/src/tools/rustfmt/tests/target/cfg_select/cfg_select_edge_cases.rs @@ -86,10 +86,12 @@ fn cfg_select_comments_that_might_get_lost() { } } cfg_select! { - _ => {{ x }} + _ => + /* after => */ + {{ x }} } cfg_select! { - _ => {{ x }} + _ /* before arrow */ => {{ x }} } cfg_select! { @@ -109,6 +111,100 @@ fn cfg_select_comments_that_might_get_lost() { } /* d */ }} } + + cfg_select! { + _ => { + { x } /* after */ + } + } + + cfg_select! { + _ => { + { x } // after newline + } + } + + cfg_select! { + _ => + /* between */ + {{ x }} + } + + cfg_select! { + _ => + // between trailing + {{ x }} + } + + // Trailing comma + cfg_select! { + _ => + /* between */ + {{ x }}, + } + cfg_select! { + _ => + /* between */ + {{ + a; + b + }}, + } + + cfg_select! { + _ => + /* between */ + {{ + a; + b + }} + } + + cfg_select! { + _ => + /* multi + line */ + {{ x }} + } + + // Comments before `=>` + cfg_select! { + _ /* before arrow */ => {{ x }} + _ /* before arrow */ => x, + _ /* before arrow */ => + /* after arrow */ + {{ x }} + all(target_os = "linux", target_arch = "x86_64", target_env = "gnu") + /* long comment before arrow */ => {{ x }} + _ /* before arrow */ => {} + } + + cfg_select! { + // Not formatted: a line comment before `=>`. + c // before arrow + => x, + } + + cfg_select! { + _ => x /* before comma */, + } + + cfg_select! { + _ => {{ x }} /* before comma */, + } + + cfg_select! { + a => b, + } + + cfg_select! { + _ => xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /* too long */, + } + + cfg_select! { + _ => x // trailing newline + , + } } fn other_cfg_select_cases() { @@ -288,6 +384,41 @@ fn other_cfg_select_cases() { || {} } }; + + cfg_select! { + _ => + /* before attr */ + #[attr] + { + z + } + } + + cfg_select! { + _ => + #[attr] /* after attr */ + { + z + } + } + + cfg_select! { + _ => + // line comment before attr + #[attr] + { + z + } + } + + cfg_select! { + _ => + /* before attr */ + #[attr] /* after attr */ + { + z + } + } } fn long_predicate() { diff --git a/src/tools/rustfmt/tests/target/cfg_select_stable.rs b/src/tools/rustfmt/tests/target/cfg_select/cfg_select_stable.rs similarity index 100% rename from src/tools/rustfmt/tests/target/cfg_select_stable.rs rename to src/tools/rustfmt/tests/target/cfg_select/cfg_select_stable.rs diff --git a/src/tools/rustfmt/tests/target/cfg-select-valid-then-invalid-item-error-count-leak.rs b/src/tools/rustfmt/tests/target/cfg_select/cfg_select_valid_then_invalid_item_error_count_leak.rs similarity index 100% rename from src/tools/rustfmt/tests/target/cfg-select-valid-then-invalid-item-error-count-leak.rs rename to src/tools/rustfmt/tests/target/cfg_select/cfg_select_valid_then_invalid_item_error_count_leak.rs diff --git a/src/tools/rustfmt/tests/target/cfg_select/control_brace_style_always_next_line.rs b/src/tools/rustfmt/tests/target/cfg_select/control_brace_style_always_next_line.rs new file mode 100644 index 0000000000000..d0a8880d97bd7 --- /dev/null +++ b/src/tools/rustfmt/tests/target/cfg_select/control_brace_style_always_next_line.rs @@ -0,0 +1,132 @@ +//@ rustfmt-unstable: true +//@ rustfmt-edition: 2024 +//@ rustfmt-control_brace_style: AlwaysNextLine + +cfg_select! { + _ => x, +} + +cfg_select! { + _ => x, +} + +cfg_select! { + _ => + {{ x }} +} + +cfg_select! { + _ => + {{ x }} +} + +cfg_select! { + _ => + unsafe { x }, +} + +cfg_select! { + _ => + {unsafe { x }} +} + +cfg_select! { + _ => + // line comment + {{ x }} +} + +cfg_select! { + _ => + // line comment + { + a; + b + } +} + +cfg_select! { + _ => + /* after */ + {{ x }} +} + +cfg_select! { + _ => + /* after */ + { + a; + b + } +} + +cfg_select! { + _ => + /* after + multiline */ + {{ x }} +} + +cfg_select! { + _ => + /* after + multiline */ + { + a; + b + } +} + +cfg_select! { + _ => + /* after */ + {{ x }} +} + +cfg_select! { + _ => + /* after */ + { + a; + b + } +} + +cfg_select! { + _ /* this comment is _very_ long but brace should fit ---------------------------------- */ => + { + a; + b + } +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 101 columns incl. arrow ------------------- */ => + { + a; + b + } +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 100 columns itself -------------------------- */ => + { + a; + b + } +} + +cfg_select! { + _ /* this comment is _very_ long but shouldn't change next next line --------------------- */ => + {{ ThisLineIsShort }} +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 101 columns incl. arrow ------------------- */ => + {{ ThisLineIsShort }} +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 100 columns itself -------------------------- */ => + {{ ThisLineIsShort }} +} diff --git a/src/tools/rustfmt/tests/target/cfg_select/control_brace_style_always_same_line.rs b/src/tools/rustfmt/tests/target/cfg_select/control_brace_style_always_same_line.rs new file mode 100644 index 0000000000000..827b579509d84 --- /dev/null +++ b/src/tools/rustfmt/tests/target/cfg_select/control_brace_style_always_same_line.rs @@ -0,0 +1,127 @@ +//@ rustfmt-unstable: true +//@ rustfmt-control_brace_style: AlwaysSameLine +// ^ NB: default value + +cfg_select! { + _ => x, +} + +cfg_select! { + _ => x, +} + +cfg_select! { + _ => {{ x }} +} + +cfg_select! { + _ => {{ x }} +} + +cfg_select! { + _ => unsafe { x }, +} + +cfg_select! { + _ => {unsafe { x }} +} + +cfg_select! { + _ => + // line comment + {{ x }} +} + +cfg_select! { + _ => + // line comment + { + a; + b + } +} + +cfg_select! { + _ => + /* after */ + {{ x }} +} + +cfg_select! { + _ => + /* after */ + { + a; + b + } +} + +cfg_select! { + _ => + /* after + multiline */ + {{ x }} +} + +cfg_select! { + _ => + /* after + multiline */ + { + a; + b + } +} + +cfg_select! { + _ => + /* after */ + {{ x }} +} + +cfg_select! { + _ => + /* after */ + { + a; + b + } +} + +cfg_select! { + _ /* this comment is _very_ long but brace should fit ---------------------------------- */ => { + a; + b + } +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 101 columns incl. arrow ------------------- */ => + { + a; + b + } +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 100 columns itself -------------------------- */ => + { + a; + b + } +} + +cfg_select! { + _ /* this comment is _very_ long but shouldn't change next next line --------------------- */ => + {{ ThisLineIsShort }} +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 101 columns incl. arrow ------------------- */ => + {{ ThisLineIsShort }} +} + +cfg_select! { + _ /* this comment is _very_ long and adds up to 100 columns itself -------------------------- */ => + {{ ThisLineIsShort }} +} diff --git a/src/tools/rustfmt/tests/target/issue_7045.rs b/src/tools/rustfmt/tests/target/cfg_select/issue_7045.rs similarity index 100% rename from src/tools/rustfmt/tests/target/issue_7045.rs rename to src/tools/rustfmt/tests/target/cfg_select/issue_7045.rs diff --git a/src/tools/rustfmt/tests/target/issue_7088_stable.rs b/src/tools/rustfmt/tests/target/cfg_select/issue_7088_stable.rs similarity index 100% rename from src/tools/rustfmt/tests/target/issue_7088_stable.rs rename to src/tools/rustfmt/tests/target/cfg_select/issue_7088_stable.rs diff --git a/src/tools/rustfmt/tests/target/issue_7088_unstable.rs b/src/tools/rustfmt/tests/target/cfg_select/issue_7088_unstable.rs similarity index 100% rename from src/tools/rustfmt/tests/target/issue_7088_unstable.rs rename to src/tools/rustfmt/tests/target/cfg_select/issue_7088_unstable.rs diff --git a/src/tools/rustfmt/tests/target/issue_7198.rs b/src/tools/rustfmt/tests/target/cfg_select/issue_7198.rs similarity index 100% rename from src/tools/rustfmt/tests/target/issue_7198.rs rename to src/tools/rustfmt/tests/target/cfg_select/issue_7198.rs diff --git a/src/tools/rustfmt/tests/target/cfg_select/issue_7209.rs b/src/tools/rustfmt/tests/target/cfg_select/issue_7209.rs new file mode 100644 index 0000000000000..4c06baa145027 --- /dev/null +++ b/src/tools/rustfmt/tests/target/cfg_select/issue_7209.rs @@ -0,0 +1,11 @@ +//@ rustfmt-unstable: true +//@ rustfmt-edition: 2024 + +fn gettid() -> u64 { + cfg_select! { + any(target_os = "solaris", target_os = "illumos") => { + // On Solaris and Illumos, the `pthread_t` is the OS TID. + unsafe { libc::pthread_self() as u64 } + } + } +} diff --git a/src/tools/rustfmt/tests/target/cfg_select/format_me_please_1.rs b/src/tools/rustfmt/tests/target/cfg_select_multifile/format_me_please_1.rs similarity index 100% rename from src/tools/rustfmt/tests/target/cfg_select/format_me_please_1.rs rename to src/tools/rustfmt/tests/target/cfg_select_multifile/format_me_please_1.rs diff --git a/src/tools/rustfmt/tests/target/cfg_select/format_me_please_2.rs b/src/tools/rustfmt/tests/target/cfg_select_multifile/format_me_please_2.rs similarity index 100% rename from src/tools/rustfmt/tests/target/cfg_select/format_me_please_2.rs rename to src/tools/rustfmt/tests/target/cfg_select_multifile/format_me_please_2.rs diff --git a/src/tools/rustfmt/tests/target/cfg_select/format_me_please_3.rs b/src/tools/rustfmt/tests/target/cfg_select_multifile/format_me_please_3.rs similarity index 100% rename from src/tools/rustfmt/tests/target/cfg_select/format_me_please_3.rs rename to src/tools/rustfmt/tests/target/cfg_select_multifile/format_me_please_3.rs diff --git a/src/tools/rustfmt/tests/target/cfg_select/format_me_please_4.rs b/src/tools/rustfmt/tests/target/cfg_select_multifile/format_me_please_4.rs similarity index 100% rename from src/tools/rustfmt/tests/target/cfg_select/format_me_please_4.rs rename to src/tools/rustfmt/tests/target/cfg_select_multifile/format_me_please_4.rs diff --git a/src/tools/rustfmt/tests/target/cfg_select/lib.rs b/src/tools/rustfmt/tests/target/cfg_select_multifile/lib.rs similarity index 100% rename from src/tools/rustfmt/tests/target/cfg_select/lib.rs rename to src/tools/rustfmt/tests/target/cfg_select_multifile/lib.rs diff --git a/src/tools/rustfmt/tests/target/cfg_select/lib2.rs b/src/tools/rustfmt/tests/target/cfg_select_multifile/lib2.rs similarity index 100% rename from src/tools/rustfmt/tests/target/cfg_select/lib2.rs rename to src/tools/rustfmt/tests/target/cfg_select_multifile/lib2.rs diff --git a/src/tools/rustfmt/tests/target/field-representing-types.rs b/src/tools/rustfmt/tests/target/field-representing-types.rs index a31ccbfb461f2..c5b400c6b3442 100644 --- a/src/tools/rustfmt/tests/target/field-representing-types.rs +++ b/src/tools/rustfmt/tests/target/field-representing-types.rs @@ -1,2 +1,4 @@ -type FRT = builtin # field_of(Type, ident); -type FRT2 = builtin # field_of(Type, ident); +//@ rustfmt-edition: 2021 + +type FRT = k#field_of(Type, ident); +type FRT2 = k#field_of(Type, ident); diff --git a/src/tools/rustfmt/tests/target/issue-6105.rs b/src/tools/rustfmt/tests/target/issue-6105.rs index 1eb0ce89f7812..cb73fc6042e24 100644 --- a/src/tools/rustfmt/tests/target/issue-6105.rs +++ b/src/tools/rustfmt/tests/target/issue-6105.rs @@ -1 +1,3 @@ -const _: () = builtin # offset_of(x, x); +//@ rustfmt-edition: 2021 + +const _: () = k#offset_of(x, x); diff --git a/src/tools/rustfmt/tests/target/issue-6651/custom_width.rs b/src/tools/rustfmt/tests/target/issue-6651/custom_width.rs index dfe747871018f..6bdfb562f5386 100644 --- a/src/tools/rustfmt/tests/target/issue-6651/custom_width.rs +++ b/src/tools/rustfmt/tests/target/issue-6651/custom_width.rs @@ -16,11 +16,6 @@ macro_rules! medium { macro_rules! long { () => { - m!( - aaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbb, - cccccccccccccccc, - ddddddddddddddd - ); + m!(aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccc, ddddddddddddddd); }; } diff --git a/src/tools/rustfmt/tests/target/issue_6069.rs b/src/tools/rustfmt/tests/target/issue_6069.rs index d866ce7c646e3..febd840880a36 100644 --- a/src/tools/rustfmt/tests/target/issue_6069.rs +++ b/src/tools/rustfmt/tests/target/issue_6069.rs @@ -1,3 +1,4 @@ // `Foó` as written here ends with ASCII 6F `'o'` followed by `'\u{0301}'` COMBINING ACUTE ACCENT. -// The compiler normalizes that combination to NFC form, `'\u{00F3}'` LATIN SMALL LETTER O WITH ACUTE. +// The compiler normalizes that combination to NFC form, `'\u{00F3}'` +// LATIN SMALL LETTER O WITH ACUTE. trait Foó: Bar {} diff --git a/src/tools/rustfmt/tests/target/issue_6159.rs b/src/tools/rustfmt/tests/target/issue_6159.rs index 49fd539d3ef5a..35047aadcec6b 100644 --- a/src/tools/rustfmt/tests/target/issue_6159.rs +++ b/src/tools/rustfmt/tests/target/issue_6159.rs @@ -1,3 +1,5 @@ +//@ rustfmt-edition: 2021 + fn main() { - builtin # type_ascribe(10, usize) + k#type_ascribe(10, usize) } diff --git a/src/tools/rustfmt/triagebot.toml b/src/tools/rustfmt/triagebot.toml index de28ad00a4272..7197066a41a98 100644 --- a/src/tools/rustfmt/triagebot.toml +++ b/src/tools/rustfmt/triagebot.toml @@ -13,6 +13,7 @@ allow-unauthenticated = [ "E-*", "F-*", "I-*", + "llm-assisted", "needs-rfc", "needs-triage", "regression-*", diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.rs b/tests/ui/feature-gates/feature-gate-builtin_syntax.rs deleted file mode 100644 index 832bb5a96bc3d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-builtin_syntax.rs +++ /dev/null @@ -1,7 +0,0 @@ -struct Foo { - v: u8, - w: u8, -} -fn main() { - builtin # offset_of(Foo, v); //~ ERROR `builtin #` syntax is unstable -} diff --git a/tests/ui/feature-gates/feature-gate-internal_syntax.rs b/tests/ui/feature-gates/feature-gate-internal_syntax.rs new file mode 100644 index 0000000000000..5b4293d900923 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-internal_syntax.rs @@ -0,0 +1,10 @@ +//@ edition: 2021.. +#![feature(forced_keywords)] + +struct Foo { + v: u8, + w: u8, +} +fn main() { + k#offset_of(Foo, v); //~ ERROR this syntax is internal +} diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr b/tests/ui/feature-gates/feature-gate-internal_syntax.stderr similarity index 56% rename from tests/ui/feature-gates/feature-gate-builtin_syntax.stderr rename to tests/ui/feature-gates/feature-gate-internal_syntax.stderr index 297363b3de711..9db1a51e0d999 100644 --- a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr +++ b/tests/ui/feature-gates/feature-gate-internal_syntax.stderr @@ -1,11 +1,11 @@ -error[E0658]: `builtin #` syntax is unstable - --> $DIR/feature-gate-builtin_syntax.rs:6:15 +error[E0658]: this syntax is internal + --> $DIR/feature-gate-internal_syntax.rs:9:5 | -LL | builtin # offset_of(Foo, v); - | ^^^^^^^^^ +LL | k#offset_of(Foo, v); + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #110680 for more information - = help: add `#![feature(builtin_syntax)]` to the crate attributes to enable + = help: add `#![feature(internal_syntax)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/field_representing_types/invalid.next.stderr b/tests/ui/field_representing_types/invalid.next.stderr index 52872001b4dee..82b2aa81451ab 100644 --- a/tests/ui/field_representing_types/invalid.next.stderr +++ b/tests/ui/field_representing_types/invalid.next.stderr @@ -33,7 +33,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:28:12 | LL | let _: field_of!(Enum, Variant..field); @@ -48,7 +48,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Struct, [42]); | ^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:30:12 | LL | let _: field_of!(Struct, [42]); @@ -57,7 +57,7 @@ LL | let _: field_of!(Struct, [42]); | in this macro invocation | this macro call doesn't expand to a type -error: `field_of!` only supports a single field or a variant with a field +error: `field_of` only supports a single field or a variant with a field --> $DIR/invalid.rs:32:30 | LL | let _: field_of!(Struct, field1.field2.field3); diff --git a/tests/ui/field_representing_types/invalid.old.stderr b/tests/ui/field_representing_types/invalid.old.stderr index 52872001b4dee..82b2aa81451ab 100644 --- a/tests/ui/field_representing_types/invalid.old.stderr +++ b/tests/ui/field_representing_types/invalid.old.stderr @@ -33,7 +33,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:28:12 | LL | let _: field_of!(Enum, Variant..field); @@ -48,7 +48,7 @@ error: offset_of expects dot-separated field and variant names LL | let _: field_of!(Struct, [42]); | ^^^^ -error: `field_of!` expects dot-separated field and variant names +error: `field_of` expects dot-separated field and variant names --> $DIR/invalid.rs:30:12 | LL | let _: field_of!(Struct, [42]); @@ -57,7 +57,7 @@ LL | let _: field_of!(Struct, [42]); | in this macro invocation | this macro call doesn't expand to a type -error: `field_of!` only supports a single field or a variant with a field +error: `field_of` only supports a single field or a variant with a field --> $DIR/invalid.rs:32:30 | LL | let _: field_of!(Struct, field1.field2.field3); diff --git a/tests/ui/field_representing_types/invalid.rs b/tests/ui/field_representing_types/invalid.rs index 0d8c5d563401c..e0ba33dd4eb59 100644 --- a/tests/ui/field_representing_types/invalid.rs +++ b/tests/ui/field_representing_types/invalid.rs @@ -24,10 +24,10 @@ fn main() { let _: field_of!(Struct); //~ ERROR: unexpected end of macro invocation let _: field_of!(Struct,); //~ ERROR: unexpected end of macro invocation let _: field_of!(Struct, field, extra); //~ ERROR: no rules expected `extra` - // FIXME(FRTs): adjust error message to mention `field_of!` & prevent double errors + // FIXME(FRTs): adjust error message to mention `field_of` & prevent double errors let _: field_of!(Enum, Variant..field); //~ ERROR: offset_of expects dot-separated field and variant names - //~^ ERROR: `field_of!` expects dot-separated field and variant names + //~^ ERROR: `field_of` expects dot-separated field and variant names let _: field_of!(Struct, [42]); //~ ERROR: offset_of expects dot-separated field and variant names - //~^ ERROR: `field_of!` expects dot-separated field and variant names - let _: field_of!(Struct, field1.field2.field3); //~ ERROR: `field_of!` only supports a single field or a variant with a field + //~^ ERROR: `field_of` expects dot-separated field and variant names + let _: field_of!(Struct, field1.field2.field3); //~ ERROR: `field_of` only supports a single field or a variant with a field } diff --git a/tests/ui/offset-of/offset-of-builtin.rs b/tests/ui/offset-of/offset-of-builtin.rs deleted file mode 100644 index 6664c10f905ef..0000000000000 --- a/tests/ui/offset-of/offset-of-builtin.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(builtin_syntax)] - -// For the exposed macro we already test these errors in the other files, -// but this test helps to make sure the builtin construct also errors. -// This has the same examples as offset-of-arg-count.rs - -fn main() { - builtin # offset_of(NotEnoughArguments); //~ ERROR expected one of -} -fn t1() { - builtin # offset_of(NotEnoughArgumentsWithAComma, ); //~ ERROR expected expression -} -fn t2() { - builtin # offset_of(S, f, too many arguments); //~ ERROR expected `)`, found `too` -} -fn t3() { - builtin # offset_of(S, f); // compiles fine -} -fn t4() { - builtin # offset_of(S, f.); //~ ERROR unexpected token -} -fn t5() { - builtin # offset_of(S, f.,); //~ ERROR unexpected token -} -fn t6() { - builtin # offset_of(S, f..); //~ ERROR offset_of expects dot-separated field and variant names -} -fn t7() { - builtin # offset_of(S, f..,); //~ ERROR offset_of expects dot-separated field and variant names -} - -struct S { f: u8, } diff --git a/tests/ui/offset-of/offset-of-builtin.stderr b/tests/ui/offset-of/offset-of-builtin.stderr deleted file mode 100644 index 5917ee2936361..0000000000000 --- a/tests/ui/offset-of/offset-of-builtin.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, or `<`, found `)` - --> $DIR/offset-of-builtin.rs:8:43 - | -LL | builtin # offset_of(NotEnoughArguments); - | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `<` - -error: expected expression, found `)` - --> $DIR/offset-of-builtin.rs:11:55 - | -LL | builtin # offset_of(NotEnoughArgumentsWithAComma, ); - | ^ expected expression - -error: expected `)`, found `too` - --> $DIR/offset-of-builtin.rs:14:31 - | -LL | builtin # offset_of(S, f, too many arguments); - | ^^^ expected `)` - | - = note: unexpected third argument to offset_of - -error: unexpected token: `)` - --> $DIR/offset-of-builtin.rs:20:30 - | -LL | builtin # offset_of(S, f.); - | ^ - -error: unexpected token: `,` - --> $DIR/offset-of-builtin.rs:23:30 - | -LL | builtin # offset_of(S, f.,); - | ^ - -error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-builtin.rs:26:28 - | -LL | builtin # offset_of(S, f..); - | ^^^ - -error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-builtin.rs:29:28 - | -LL | builtin # offset_of(S, f..,); - | ^^^ - -error: aborting due to 7 previous errors - diff --git a/tests/ui/offset-of/offset-of-tuple-field.rs b/tests/ui/offset-of/offset-of-tuple-field.rs index 02d41f91a2563..755d61d18b739 100644 --- a/tests/ui/offset-of/offset-of-tuple-field.rs +++ b/tests/ui/offset-of/offset-of-tuple-field.rs @@ -1,5 +1,3 @@ -#![feature(builtin_syntax)] - use std::mem::offset_of; fn main() { @@ -9,12 +7,6 @@ fn main() { offset_of!((u8, u8), 1_u8); //~ ERROR no field `1_` //~| ERROR suffixes on a tuple index - builtin # offset_of((u8, u8), 1e2); //~ ERROR no field `1e2` - builtin # offset_of((u8, u8), _0); //~ ERROR no field `_0` - builtin # offset_of((u8, u8), 01); //~ ERROR no field `01` - builtin # offset_of((u8, u8), 1_u8); //~ ERROR no field `1_` - //~| ERROR suffixes on a tuple index - offset_of!(((u8, u16), (u32, u16, u8)), 0.2); //~ ERROR no field `2` offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); //~ ERROR no field `1e2` offset_of!(((u8, u16), (u32, u16, u8)), 1.2); diff --git a/tests/ui/offset-of/offset-of-tuple-field.stderr b/tests/ui/offset-of/offset-of-tuple-field.stderr index 01622c5fa2da6..052e4b0596fd6 100644 --- a/tests/ui/offset-of/offset-of-tuple-field.stderr +++ b/tests/ui/offset-of/offset-of-tuple-field.stderr @@ -1,17 +1,11 @@ error: suffixes on a tuple index are invalid - --> $DIR/offset-of-tuple-field.rs:15:35 - | -LL | builtin # offset_of((u8, u8), 1_u8); - | ^^^^ invalid suffix `u8` - -error: suffixes on a tuple index are invalid - --> $DIR/offset-of-tuple-field.rs:9:26 + --> $DIR/offset-of-tuple-field.rs:7:26 | LL | offset_of!((u8, u8), 1_u8); | ^^^^ invalid suffix `u8` error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:6:26 + --> $DIR/offset-of-tuple-field.rs:4:26 | LL | offset_of!((u8, u8), _0); | ^^ @@ -23,7 +17,7 @@ LL + offset_of!((u8, u8), 0); | error[E0609]: no field `01` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:7:26 + --> $DIR/offset-of-tuple-field.rs:5:26 | LL | offset_of!((u8, u8), 01); | ^^ @@ -31,7 +25,7 @@ LL | offset_of!((u8, u8), 01); = note: available fields are: `0`, `1` error[E0609]: no field `1e2` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:8:26 + --> $DIR/offset-of-tuple-field.rs:6:26 | LL | offset_of!((u8, u8), 1e2); | ^^^ @@ -39,7 +33,7 @@ LL | offset_of!((u8, u8), 1e2); = note: available fields are: `0`, `1` error[E0609]: no field `1_` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:9:26 + --> $DIR/offset-of-tuple-field.rs:7:26 | LL | offset_of!((u8, u8), 1_u8); | ^^^^ @@ -50,48 +44,8 @@ LL - offset_of!((u8, u8), 1_u8); LL + offset_of!((u8, u8), 1); | -error[E0609]: no field `1e2` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:12:35 - | -LL | builtin # offset_of((u8, u8), 1e2); - | ^^^ - | - = note: available fields are: `0`, `1` - -error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:13:35 - | -LL | builtin # offset_of((u8, u8), _0); - | ^^ - | -help: a field with a similar name exists - | -LL - builtin # offset_of((u8, u8), _0); -LL + builtin # offset_of((u8, u8), 0); - | - -error[E0609]: no field `01` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:14:35 - | -LL | builtin # offset_of((u8, u8), 01); - | ^^ - | - = note: available fields are: `0`, `1` - -error[E0609]: no field `1_` on type `(u8, u8)` - --> $DIR/offset-of-tuple-field.rs:15:35 - | -LL | builtin # offset_of((u8, u8), 1_u8); - | ^^^^ - | -help: a field with a similar name exists - | -LL - builtin # offset_of((u8, u8), 1_u8); -LL + builtin # offset_of((u8, u8), 1); - | - error[E0609]: no field `2` on type `(u8, u16)` - --> $DIR/offset-of-tuple-field.rs:18:47 + --> $DIR/offset-of-tuple-field.rs:10:47 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); | ^ @@ -99,7 +53,7 @@ LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); = note: available fields are: `0`, `1` error[E0609]: no field `1e2` on type `(u8, u16)` - --> $DIR/offset-of-tuple-field.rs:19:47 + --> $DIR/offset-of-tuple-field.rs:11:47 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); | ^^^ @@ -107,11 +61,11 @@ LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); = note: available fields are: `0`, `1` error[E0609]: no field `0` on type `u8` - --> $DIR/offset-of-tuple-field.rs:21:49 + --> $DIR/offset-of-tuple-field.rs:13:49 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); | ^ -error: aborting due to 13 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index ddbaee97b1bb0..be668d9e08946 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -1,4 +1,5 @@ -#![feature(builtin_syntax)] +//@ edition: 2021.. +#![feature(forced_keywords, internal_syntax)] use std::mem::offset_of; @@ -9,9 +10,9 @@ fn main() { offset_of!((u8, u8), 1 .); //~ ERROR unexpected token: `)` // We need to put these into curly braces, otherwise only one of the // errors will be emitted and the others suppressed. - { builtin # offset_of((u8, u8), +1) }; //~ ERROR leading `+` is not supported - { builtin # offset_of((u8, u8), 1.) }; //~ ERROR offset_of expects dot-separated field and variant names - { builtin # offset_of((u8, u8), 1 .) }; //~ ERROR unexpected token: `)` + { k#offset_of((u8, u8), +1) }; //~ ERROR leading `+` is not supported + { k#offset_of((u8, u8), 1.) }; //~ ERROR offset_of expects dot-separated field and variant names + { k#offset_of((u8, u8), 1 .) }; //~ ERROR unexpected token: `)` } type ComplexTup = (((u8, u8), u8), u8); @@ -26,14 +27,15 @@ fn nested() { offset_of!(ComplexTup, 0.0 . 1.); //~ ERROR unexpected token: `)` offset_of!(ComplexTup, 0.0. 1.); //~ ERROR unexpected token: `)` + // FIXME(fmease): Update comment. // Test for builtin too to ensure that the builtin syntax can also handle these cases // We need to put these into curly braces, otherwise only one of the // errors will be emitted and the others suppressed. - { builtin # offset_of(ComplexTup, 0.0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0 .0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0 . 0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0. 0.1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0 .1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0 . 1.) }; //~ ERROR unexpected token: `)` - { builtin # offset_of(ComplexTup, 0.0. 1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0 .0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0 . 0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0. 0.1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0 .1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0 . 1.) }; //~ ERROR unexpected token: `)` + { k#offset_of(ComplexTup, 0.0. 1.) }; //~ ERROR unexpected token: `)` } diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index f90f2db1c6c35..db46373449218 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -1,71 +1,71 @@ error: leading `+` is not supported - --> $DIR/offset-of-tuple.rs:12:37 + --> $DIR/offset-of-tuple.rs:13:29 | -LL | { builtin # offset_of((u8, u8), +1) }; - | ^ unexpected `+` +LL | { k#offset_of((u8, u8), +1) }; + | ^ unexpected `+` | help: try removing the `+` | -LL - { builtin # offset_of((u8, u8), +1) }; -LL + { builtin # offset_of((u8, u8), 1) }; +LL - { k#offset_of((u8, u8), +1) }; +LL + { k#offset_of((u8, u8), 1) }; | error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:13:38 + --> $DIR/offset-of-tuple.rs:14:30 | -LL | { builtin # offset_of((u8, u8), 1.) }; - | ^ +LL | { k#offset_of((u8, u8), 1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:14:40 + --> $DIR/offset-of-tuple.rs:15:32 | -LL | { builtin # offset_of((u8, u8), 1 .) }; - | ^ +LL | { k#offset_of((u8, u8), 1 .) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:32:45 + --> $DIR/offset-of-tuple.rs:34:37 | -LL | { builtin # offset_of(ComplexTup, 0.0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:33:46 + --> $DIR/offset-of-tuple.rs:35:38 | -LL | { builtin # offset_of(ComplexTup, 0 .0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0 .0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:34:47 + --> $DIR/offset-of-tuple.rs:36:39 | -LL | { builtin # offset_of(ComplexTup, 0 . 0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0 . 0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:35:46 + --> $DIR/offset-of-tuple.rs:37:38 | -LL | { builtin # offset_of(ComplexTup, 0. 0.1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0. 0.1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:36:46 + --> $DIR/offset-of-tuple.rs:38:38 | -LL | { builtin # offset_of(ComplexTup, 0.0 .1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0 .1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:37:47 + --> $DIR/offset-of-tuple.rs:39:39 | -LL | { builtin # offset_of(ComplexTup, 0.0 . 1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0 . 1.) }; + | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:38:46 + --> $DIR/offset-of-tuple.rs:40:38 | -LL | { builtin # offset_of(ComplexTup, 0.0. 1.) }; - | ^ +LL | { k#offset_of(ComplexTup, 0.0. 1.) }; + | ^ error: no rules expected `+` - --> $DIR/offset-of-tuple.rs:6:26 + --> $DIR/offset-of-tuple.rs:7:26 | LL | offset_of!((u8, u8), +1); | ^ no rules expected this token in macro call @@ -75,61 +75,61 @@ note: while trying to match meta-variable `$fields:expr` = note: this macro expects a container type and a (nested) field path, like `offset_of!(Type, field)` error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:7:26 + --> $DIR/offset-of-tuple.rs:8:26 | LL | offset_of!((u8, u8), -1); | ^^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:8:27 + --> $DIR/offset-of-tuple.rs:9:27 | LL | offset_of!((u8, u8), 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:9:29 + --> $DIR/offset-of-tuple.rs:10:29 | LL | offset_of!((u8, u8), 1 .); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:21:34 + --> $DIR/offset-of-tuple.rs:22:34 | LL | offset_of!(ComplexTup, 0.0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:22:35 + --> $DIR/offset-of-tuple.rs:23:35 | LL | offset_of!(ComplexTup, 0 .0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:23:36 + --> $DIR/offset-of-tuple.rs:24:36 | LL | offset_of!(ComplexTup, 0 . 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:24:35 + --> $DIR/offset-of-tuple.rs:25:35 | LL | offset_of!(ComplexTup, 0. 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:25:35 + --> $DIR/offset-of-tuple.rs:26:35 | LL | offset_of!(ComplexTup, 0.0 .1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:26:36 + --> $DIR/offset-of-tuple.rs:27:36 | LL | offset_of!(ComplexTup, 0.0 . 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:27:35 + --> $DIR/offset-of-tuple.rs:28:35 | LL | offset_of!(ComplexTup, 0.0. 1.); | ^ diff --git a/tests/ui/parser/builtin-syntax.rs b/tests/ui/parser/builtin-syntax.rs deleted file mode 100644 index 897dab8ec50ae..0000000000000 --- a/tests/ui/parser/builtin-syntax.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(builtin_syntax)] - -fn main() { - builtin # foobar(); //~ ERROR unknown `builtin #` construct -} - -fn not_identifier() { - builtin # {}(); //~ ERROR expected identifier after -} diff --git a/tests/ui/parser/builtin-syntax.stderr b/tests/ui/parser/builtin-syntax.stderr deleted file mode 100644 index ee3764a62216a..0000000000000 --- a/tests/ui/parser/builtin-syntax.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unknown `builtin #` construct `foobar` - --> $DIR/builtin-syntax.rs:4:5 - | -LL | builtin # foobar(); - | ^^^^^^^^^^^^^^^^ - -error: expected identifier after `builtin #` - --> $DIR/builtin-syntax.rs:8:15 - | -LL | builtin # {}(); - | ^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/unpretty/exhaustive.expanded.stdout b/tests/ui/unpretty/exhaustive.expanded.stdout index 7eca271aeda13..3551d40dffbfc 100644 --- a/tests/ui/unpretty/exhaustive.expanded.stdout +++ b/tests/ui/unpretty/exhaustive.expanded.stdout @@ -10,12 +10,13 @@ // errors that only occur once we get past the AST. #![feature(auto_traits)] -#![feature(builtin_syntax)] +#![feature(internal_syntax)] #![feature(const_trait_impl)] #![feature(coroutines)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] +#![feature(forced_keywords)] #![feature(gen_blocks)] #![feature(more_qualified_paths)] #![feature(never_patterns)] @@ -131,7 +132,7 @@ mod expressions { fn expr_cast() { let expr; expr as T; expr as T; } /// ExprKind::Type - fn expr_type() { let expr; builtin # type_ascribe(expr, T); } + fn expr_type() { let expr; k#type_ascribe(expr, T); } /// ExprKind::Let fn expr_let() { @@ -315,7 +316,7 @@ mod expressions { - const { builtin # offset_of(T, field) }; + const { k#offset_of(T, field) }; } /// ExprKind::MacCall fn expr_mac_call() { "..."; "..."; "..."; } diff --git a/tests/ui/unpretty/exhaustive.hir.stderr b/tests/ui/unpretty/exhaustive.hir.stderr index 5ca4b080a95e5..276bc5b5d2573 100644 --- a/tests/ui/unpretty/exhaustive.hir.stderr +++ b/tests/ui/unpretty/exhaustive.hir.stderr @@ -1,17 +1,17 @@ error[E0697]: closures cannot be static - --> $DIR/exhaustive.rs:209:9 + --> $DIR/exhaustive.rs:210:9 | LL | static || value; | ^^^^^^^^^ error[E0697]: closures cannot be static - --> $DIR/exhaustive.rs:210:9 + --> $DIR/exhaustive.rs:211:9 | LL | static move || value; | ^^^^^^^^^^^^^^ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/exhaustive.rs:239:13 + --> $DIR/exhaustive.rs:240:13 | LL | fn expr_await() { | --------------- this is not `async` @@ -20,19 +20,19 @@ LL | fut.await; | ^^^^^ only allowed inside `async` functions and blocks error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/exhaustive.rs:290:9 + --> $DIR/exhaustive.rs:291:9 | LL | _; | ^ `_` not allowed here error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:300:9 + --> $DIR/exhaustive.rs:301:9 | LL | x::(); | ^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:301:9 + --> $DIR/exhaustive.rs:302:9 | LL | x::(T, T) -> T; | ^^^^^^^^^^^^^^ only `Fn` traits may use parentheses @@ -44,31 +44,31 @@ LL + x:: -> T; | error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:302:9 + --> $DIR/exhaustive.rs:303:9 | LL | crate::() -> ()::expressions::() -> ()::expr_path; | ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:302:26 + --> $DIR/exhaustive.rs:303:26 | LL | crate::() -> ()::expressions::() -> ()::expr_path; | ^^^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:305:9 + --> $DIR/exhaustive.rs:306:9 | LL | core::()::marker::()::PhantomData; | ^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:305:19 + --> $DIR/exhaustive.rs:306:19 | LL | core::()::marker::()::PhantomData; | ^^^^^^^^^^ only `Fn` traits may use parentheses error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks - --> $DIR/exhaustive.rs:392:9 + --> $DIR/exhaustive.rs:393:9 | LL | yield; | ^^^^^ @@ -79,7 +79,7 @@ LL | #[coroutine] fn expr_yield() { | ++++++++++++ error[E0703]: invalid ABI: found `C++` - --> $DIR/exhaustive.rs:472:23 + --> $DIR/exhaustive.rs:473:23 | LL | unsafe extern "C++" {} | ^^^^^ invalid ABI @@ -87,7 +87,7 @@ LL | unsafe extern "C++" {} = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions error: `..` patterns are not allowed here - --> $DIR/exhaustive.rs:674:13 + --> $DIR/exhaustive.rs:675:13 | LL | let ..; | ^^ @@ -95,13 +95,13 @@ LL | let ..; = note: only allowed in tuple, tuple struct, and slice patterns error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/exhaustive.rs:789:16 + --> $DIR/exhaustive.rs:790:16 | LL | let _: T() -> !; | ^^^^^^^^ only `Fn` traits may use parentheses error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:803:16 + --> $DIR/exhaustive.rs:804:16 | LL | let _: impl Send; | ^^^^^^^^^ @@ -112,7 +112,7 @@ LL | let _: impl Send; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:804:16 + --> $DIR/exhaustive.rs:805:16 | LL | let _: impl Send + 'static; | ^^^^^^^^^^^^^^^^^^^ @@ -123,7 +123,7 @@ LL | let _: impl Send + 'static; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:805:16 + --> $DIR/exhaustive.rs:806:16 | LL | let _: impl 'static + Send; | ^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | let _: impl 'static + Send; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:806:16 + --> $DIR/exhaustive.rs:807:16 | LL | let _: impl ?Sized; | ^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | let _: impl ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:807:16 + --> $DIR/exhaustive.rs:808:16 | LL | let _: impl [const] Clone; | ^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL | let _: impl [const] Clone; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/exhaustive.rs:808:16 + --> $DIR/exhaustive.rs:809:16 | LL | let _: impl for<'a> Send; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index b1c956c2fe9f1..6af4d3b5b81de 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -1,8 +1,9 @@ -#![attr = Feature([auto_traits#0, builtin_syntax#0, const_trait_impl#0, +#![attr = Feature([auto_traits#0, internal_syntax#0, const_trait_impl#0, coroutines#0, decl_macro#0, deref_patterns#0, explicit_tail_calls#0, -gen_blocks#0, more_qualified_paths#0, never_patterns#0, pattern_types#0, -pattern_type_macro#0, prelude_import#0, specialization#0, trace_macros#0, -trait_alias#0, try_blocks#0, try_blocks_heterogeneous#0, yeet_expr#0])] +forced_keywords#0, gen_blocks#0, more_qualified_paths#0, never_patterns#0, +pattern_types#0, pattern_type_macro#0, prelude_import#0, specialization#0, +trace_macros#0, trait_alias#0, try_blocks#0, try_blocks_heterogeneous#0, +yeet_expr#0])] #![attr = LintCheck([LintCheck {lint_name: LintName { tool: None, name: "incomplete_features" }, kind: Allow}, LintCheck {lint_name: LintName { tool: None, name: "unused_attributes" }, diff --git a/tests/ui/unpretty/exhaustive.rs b/tests/ui/unpretty/exhaustive.rs index 03ef63874ac0a..15f684fc3dd72 100644 --- a/tests/ui/unpretty/exhaustive.rs +++ b/tests/ui/unpretty/exhaustive.rs @@ -9,12 +9,13 @@ // errors that only occur once we get past the AST. #![feature(auto_traits)] -#![feature(builtin_syntax)] +#![feature(internal_syntax)] #![feature(const_trait_impl)] #![feature(coroutines)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] +#![feature(forced_keywords)] #![feature(gen_blocks)] #![feature(more_qualified_paths)] #![feature(never_patterns)] @@ -144,7 +145,7 @@ mod expressions { /// ExprKind::Type fn expr_type() { let expr; - builtin # type_ascribe(expr, T); + k#type_ascribe(expr, T); } /// ExprKind::Let