diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index cf0ee4fc28fe2..78afc33974826 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -229,15 +229,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) { // Do not suggest going from `Trait()` to `Trait<>` if !data.inputs.is_empty() { - if let Some(split) = snippet.find('(') { - let trait_name = &snippet[0..split]; - let args = &snippet[split + 1..snippet.len() - 1]; - err.span_suggestion( - data.span, - "use angle brackets instead", - format!("{}<{}>", trait_name, args), - Applicability::MaybeIncorrect, - ); + // Suggest replacing `(` and `)` with `<` and `>` + // The snippet may be missing the closing `)`, skip that case + if snippet.ends_with(')') { + if let Some(split) = snippet.find('(') { + let trait_name = &snippet[0..split]; + let args = &snippet[split + 1..snippet.len() - 1]; + err.span_suggestion( + data.span, + "use angle brackets instead", + format!("{}<{}>", trait_name, args), + Applicability::MaybeIncorrect, + ); + } } } }; diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index 9e1497961d9ea..71ff762c714bf 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -23,11 +23,9 @@ impl IdFunctor for Box { let value = raw.read(); // SAFETY: Converts `Box` to `Box>` which is the // inverse of `Box::assume_init()` and should be safe. - let mut raw: Box> = Box::from_raw(raw.cast()); + let raw: Box> = Box::from_raw(raw.cast()); // SAFETY: Write the mapped value back into the `Box`. - raw.write(f(value)?); - // SAFETY: We just initialized `raw`. - raw.assume_init() + Box::write(raw, f(value)?) }) } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 57506bc68345b..02811b2491c15 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -533,7 +533,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } - if sized && fields.iter().any(|f| f.abi.is_uninhabited()) { + if fields.iter().any(|f| f.abi.is_uninhabited()) { abi = Abi::Uninhabited; } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 25eb56456e15f..ba9b2eae2c830 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -788,10 +788,14 @@ impl<'tcx> ty::TyS<'tcx> { [component_ty] => component_ty, _ => self, }; + // This doesn't depend on regions, so try to minimize distinct // query keys used. - let erased = tcx.normalize_erasing_regions(param_env, query_ty); - tcx.needs_drop_raw(param_env.and(erased)) + // If normalization fails, we just use `query_ty`. + let query_ty = + tcx.try_normalize_erasing_regions(param_env, query_ty).unwrap_or(query_ty); + + tcx.needs_drop_raw(param_env.and(query_ty)) } } } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 595b623b02078..fc309aa848ca1 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -147,8 +147,10 @@ where Ok(tys) => tys, }; for required_ty in tys { - let required = - tcx.normalize_erasing_regions(self.param_env, required_ty); + let required = tcx + .try_normalize_erasing_regions(self.param_env, required_ty) + .unwrap_or(required_ty); + queue_type(self, required); } } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index f6332b072cf30..0b72b3f0ee7b0 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -763,6 +763,42 @@ impl Box, A> { let (raw, alloc) = Box::into_raw_with_allocator(self); unsafe { Box::from_raw_in(raw as *mut T, alloc) } } + + /// Writes the value and converts to `Box`. + /// + /// This method converts the box similarly to [`Box::assume_init`] but + /// writes `value` into it before conversion thus guaranteeing safety. + /// In some scenarios use of this method may improve performance because + /// the compiler may be able to optimize copying from stack. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let big_box = Box::<[usize; 1024]>::new_uninit(); + /// + /// let mut array = [0; 1024]; + /// for (i, place) in array.iter_mut().enumerate() { + /// *place = i; + /// } + /// + /// // The optimizer may be able to elide this copy, so previous code writes + /// // to heap directly. + /// let big_box = Box::write(big_box, array); + /// + /// for (i, x) in big_box.iter().enumerate() { + /// assert_eq!(*x, i); + /// } + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn write(mut boxed: Self, value: T) -> Box { + unsafe { + (*boxed).write(value); + boxed.assume_init() + } + } } impl Box<[mem::MaybeUninit], A> { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 4eeb5e4394386..6e9b388a2bd07 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -703,7 +703,8 @@ impl Option { #[inline] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - pub fn expect(self, msg: &str) -> T { + #[rustc_const_unstable(feature = "const_option", issue = "67441")] + pub const fn expect(self, msg: &str) -> T { match self { Some(val) => val, None => expect_failed(msg), @@ -1658,7 +1659,7 @@ impl Option> { #[inline(never)] #[cold] #[track_caller] -fn expect_failed(msg: &str) -> ! { +const fn expect_failed(msg: &str) -> ! { panic!("{}", msg) } diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 7686b61b67a89..e48b589f7d8f5 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -97,6 +97,7 @@ pub fn errno() -> i32 { } #[cfg(target_os = "dragonfly")] +#[allow(dead_code)] pub fn set_errno(e: i32) { extern "C" { #[thread_local] diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 4da59577d78a1..64c8416b61c79 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -76,7 +76,21 @@ use crate::fmt; /// destroyed, but not all platforms have this guard. Those platforms that do /// not guard typically have a synthetic limit after which point no more /// destructors are run. +/// 3. When the process exits on Windows systems, TLS destructors may only be +/// run on the thread that causes the process to exit. This is because the +/// other threads may be forcibly terminated. /// +/// ## Synchronization in thread-local destructors +/// +/// On Windows, synchronization operations (such as [`JoinHandle::join`]) in +/// thread local destructors are prone to deadlocks and so should be avoided. +/// This is because the [loader lock] is held while a destructor is run. The +/// lock is acquired whenever a thread starts or exits or when a DLL is loaded +/// or unloaded. Therefore these events are blocked for as long as a thread +/// local destructor is running. +/// +/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices +/// [`JoinHandle::join`]: crate::thread::JoinHandle::join /// [`with`]: LocalKey::with #[stable(feature = "rust1", since = "1.0.0")] pub struct LocalKey { diff --git a/library/unwind/build.rs b/library/unwind/build.rs index 1d0b4a59a287b..a3f5224151d94 100644 --- a/library/unwind/build.rs +++ b/library/unwind/build.rs @@ -17,6 +17,9 @@ fn main() { } else { println!("cargo:rustc-link-lib=gcc"); } + + // Android's unwinding library depends on dl_iterate_phdr in `libdl`. + println!("cargo:rustc-link-lib=dl"); } else if target.contains("freebsd") { println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("netbsd") { diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 2a783c6da57e4..c07851da18ac1 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -7,6 +7,12 @@ {#- -#} {#- -#} {{page.title}} {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} {#- -#} ( + PhantomData<(A, T)>, +); + +enum Never {} + +impl Foo { + fn new_foo() -> Foo { + Foo(PhantomData) + } +} + +fn main() { + let _ = Foo::<[()], Never>::new_foo(); +} diff --git a/src/test/ui/type/issue-91268.rs b/src/test/ui/type/issue-91268.rs new file mode 100644 index 0000000000000..fd2733c1c545e --- /dev/null +++ b/src/test/ui/type/issue-91268.rs @@ -0,0 +1,9 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: cannot find type `ţ` in this scope +// error-pattern: parenthesized type parameters may only be used with a `Fn` trait +// error-pattern: type arguments are not allowed for this type +// error-pattern: mismatched types +// ignore-tidy-trailing-newlines +// `ţ` must be the last character in this file, it cannot be followed by a newline +fn main() { + 0: u8(ţ \ No newline at end of file diff --git a/src/test/ui/type/issue-91268.stderr b/src/test/ui/type/issue-91268.stderr new file mode 100644 index 0000000000000..2fe6ba6248c8d --- /dev/null +++ b/src/test/ui/type/issue-91268.stderr @@ -0,0 +1,50 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-91268.rs:9:12 + | +LL | fn main() { + | - unclosed delimiter +LL | 0: u8(ţ + | - ^ + | | + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-91268.rs:9:12 + | +LL | fn main() { + | - unclosed delimiter +LL | 0: u8(ţ + | - ^ + | | + | unclosed delimiter + +error[E0412]: cannot find type `ţ` in this scope + --> $DIR/issue-91268.rs:9:11 + | +LL | 0: u8(ţ + | ^ expecting a type here because of type ascription + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-91268.rs:9:8 + | +LL | 0: u8(ţ + | ^^^^ only `Fn` traits may use parentheses + +error[E0109]: type arguments are not allowed for this type + --> $DIR/issue-91268.rs:9:11 + | +LL | 0: u8(ţ + | ^ type argument not allowed + +error[E0308]: mismatched types + --> $DIR/issue-91268.rs:9:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | 0: u8(ţ + | ^^^^^^^ expected `()`, found `u8` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0109, E0214, E0308, E0412. +For more information about an error, try `rustc --explain E0109`. diff --git a/src/test/ui/union/issue-81199.rs b/src/test/ui/union/issue-81199.rs new file mode 100644 index 0000000000000..628e7c6ed5da8 --- /dev/null +++ b/src/test/ui/union/issue-81199.rs @@ -0,0 +1,21 @@ +#[repr(C)] +union PtrRepr { + const_ptr: *const T, + mut_ptr: *mut T, + components: PtrComponents, + //~^ ERROR the trait bound +} + +#[repr(C)] +struct PtrComponents { + data_address: *const (), + metadata: ::Metadata, +} + + + +pub trait Pointee { + type Metadata; +} + +fn main() {} diff --git a/src/test/ui/union/issue-81199.stderr b/src/test/ui/union/issue-81199.stderr new file mode 100644 index 0000000000000..f26bfe3a0b060 --- /dev/null +++ b/src/test/ui/union/issue-81199.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `T: Pointee` is not satisfied in `PtrComponents` + --> $DIR/issue-81199.rs:5:17 + | +LL | components: PtrComponents, + | ^^^^^^^^^^^^^^^^ within `PtrComponents`, the trait `Pointee` is not implemented for `T` + | +note: required because it appears within the type `PtrComponents` + --> $DIR/issue-81199.rs:10:8 + | +LL | struct PtrComponents { + | ^^^^^^^^^^^^^ + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider further restricting this bound + | +LL | union PtrRepr { + | +++++++++ +help: borrowed types always have a statically known size + | +LL | components: &PtrComponents, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | components: Box>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/rustfmt/.github/workflows/linux.yml b/src/tools/rustfmt/.github/workflows/linux.yml index 6eaae69c70805..db49794164212 100644 --- a/src/tools/rustfmt/.github/workflows/linux.yml +++ b/src/tools/rustfmt/.github/workflows/linux.yml @@ -8,7 +8,9 @@ on: jobs: test: runs-on: ubuntu-latest - name: (${{ matrix.target }}, nightly) + name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) + env: + CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }} strategy: # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization. @@ -20,6 +22,7 @@ jobs: target: [ x86_64-unknown-linux-gnu, ] + cfg_release_channel: [nightly, stable] steps: - name: checkout diff --git a/src/tools/rustfmt/.github/workflows/mac.yml b/src/tools/rustfmt/.github/workflows/mac.yml index 79e4f69163e03..55e1cc9539b85 100644 --- a/src/tools/rustfmt/.github/workflows/mac.yml +++ b/src/tools/rustfmt/.github/workflows/mac.yml @@ -10,13 +10,16 @@ jobs: # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources # macOS Catalina 10.15 runs-on: macos-latest - name: (${{ matrix.target }}, nightly) + name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) + env: + CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }} strategy: fail-fast: false matrix: target: [ x86_64-apple-darwin, ] + cfg_release_channel: [nightly, stable] steps: - name: checkout diff --git a/src/tools/rustfmt/.github/workflows/windows.yml b/src/tools/rustfmt/.github/workflows/windows.yml index c05e8d4896ac7..dcb08b5412ea6 100644 --- a/src/tools/rustfmt/.github/workflows/windows.yml +++ b/src/tools/rustfmt/.github/workflows/windows.yml @@ -8,7 +8,9 @@ on: jobs: test: runs-on: windows-latest - name: (${{ matrix.target }}, nightly) + name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) + env: + CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }} strategy: # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization. @@ -23,6 +25,7 @@ jobs: x86_64-pc-windows-gnu, x86_64-pc-windows-msvc, ] + cfg_release_channel: [nightly, stable] steps: # The Windows runners have autocrlf enabled by default diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md index 13826883d2f4b..a89fbe863e652 100644 --- a/src/tools/rustfmt/Configurations.md +++ b/src/tools/rustfmt/Configurations.md @@ -47,7 +47,7 @@ Where to put a binary operator when a binary expression goes multiline. - **Default value**: `"Front"` - **Possible values**: `"Front"`, `"Back"` -- **Stable**: No (tracking issue: #3368) +- **Stable**: No (tracking issue: [#3368](https://github.com/rust-lang/rustfmt/issues/3368)) #### `"Front"` (default): @@ -88,7 +88,7 @@ them, additional blank lines are inserted. - **Default value**: `0` - **Possible values**: *unsigned integer* -- **Stable**: No (tracking issue: #3382) +- **Stable**: No (tracking issue: [#3382](https://github.com/rust-lang/rustfmt/issues/3382)) ### Example Original Code (rustfmt will not change it with the default value of `0`): @@ -128,7 +128,7 @@ lines are found, they are trimmed down to match this integer. - **Default value**: `1` - **Possible values**: any non-negative integer -- **Stable**: No (tracking issue: #3381) +- **Stable**: No (tracking issue: [#3381](https://github.com/rust-lang/rustfmt/issues/3381)) ### Example Original Code: @@ -186,7 +186,7 @@ Brace style for items - **Default value**: `"SameLineWhere"` - **Possible values**: `"AlwaysNextLine"`, `"PreferSameLine"`, `"SameLineWhere"` -- **Stable**: No (tracking issue: #3376) +- **Stable**: No (tracking issue: [#3376](https://github.com/rust-lang/rustfmt/issues/3376)) ### Functions @@ -313,7 +313,7 @@ Whether to use colored output or not. - **Default value**: `"Auto"` - **Possible values**: "Auto", "Always", "Never" -- **Stable**: No (tracking issue: #3385) +- **Stable**: No (tracking issue: [#3385](https://github.com/rust-lang/rustfmt/issues/3385)) ## `combine_control_expr` @@ -321,7 +321,7 @@ Combine control expressions with function calls. - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3369) +- **Stable**: No (tracking issue: [#3369](https://github.com/rust-lang/rustfmt/issues/3369)) #### `true` (default): @@ -429,7 +429,7 @@ Maximum length of comments. No effect unless`wrap_comments = true`. - **Default value**: `80` - **Possible values**: any positive integer -- **Stable**: No (tracking issue: #3349) +- **Stable**: No (tracking issue: [#3349](https://github.com/rust-lang/rustfmt/issues/3349)) **Note:** A value of `0` results in [`wrap_comments`](#wrap_comments) being applied regardless of a line's width. @@ -452,7 +452,7 @@ Replace strings of _ wildcards by a single .. in tuple patterns - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3384) +- **Stable**: No (tracking issue: [#3384](https://github.com/rust-lang/rustfmt/issues/3384)) #### `false` (default): @@ -477,7 +477,7 @@ Brace style for control flow constructs - **Default value**: `"AlwaysSameLine"` - **Possible values**: `"AlwaysNextLine"`, `"AlwaysSameLine"`, `"ClosingNextLine"` -- **Stable**: No (tracking issue: #3377) +- **Stable**: No (tracking issue: [#3377](https://github.com/rust-lang/rustfmt/issues/3377)) #### `"AlwaysSameLine"` (default): @@ -551,7 +551,7 @@ Put empty-body functions and impls on a single line - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3356) +- **Stable**: No (tracking issue: [#3356](https://github.com/rust-lang/rustfmt/issues/3356)) #### `true` (default): @@ -584,7 +584,7 @@ doesn't get ignored when aligning. - **Default value** : 0 - **Possible values**: any positive integer -- **Stable**: No (tracking issue: #3372) +- **Stable**: No (tracking issue: [#3372](https://github.com/rust-lang/rustfmt/issues/3372)) #### `0` (default): @@ -630,7 +630,7 @@ using a shorter name. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3391) +- **Stable**: No (tracking issue: [#3391](https://github.com/rust-lang/rustfmt/issues/3391)) See also [`max_width`](#max_width). @@ -641,7 +641,7 @@ trailing whitespaces. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3392) +- **Stable**: No (tracking issue: [#3392](https://github.com/rust-lang/rustfmt/issues/3392)) ## `fn_args_layout` @@ -771,7 +771,7 @@ Put single-expression functions on a single line - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3358) +- **Stable**: No (tracking issue: [#3358](https://github.com/rust-lang/rustfmt/issues/3358)) #### `false` (default): @@ -832,7 +832,7 @@ Force multiline closure and match arm bodies to be wrapped in a block - **Default value**: `false` - **Possible values**: `false`, `true` -- **Stable**: No (tracking issue: #3374) +- **Stable**: No (tracking issue: [#3374](https://github.com/rust-lang/rustfmt/issues/3374)) #### `false` (default): @@ -881,7 +881,7 @@ Format code snippet included in doc comments. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3348) +- **Stable**: No (tracking issue: [#3348](https://github.com/rust-lang/rustfmt/issues/3348)) #### `false` (default): @@ -933,7 +933,7 @@ if any of the first five lines contains `@generated` marker. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No +- **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080)) ## `format_macro_matchers` @@ -941,7 +941,7 @@ Format the metavariable matching patterns in macros. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3354) +- **Stable**: No (tracking issue: [#3354](https://github.com/rust-lang/rustfmt/issues/3354)) #### `false` (default): @@ -978,7 +978,7 @@ Format the bodies of macros. - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3355) +- **Stable**: No (tracking issue: [#3355](https://github.com/rust-lang/rustfmt/issues/3355)) #### `true` (default): @@ -1011,7 +1011,7 @@ Format string literals where necessary - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3353) +- **Stable**: No (tracking issue: [#3353](https://github.com/rust-lang/rustfmt/issues/3353)) #### `false` (default): @@ -1064,7 +1064,7 @@ Control the case of the letters in hexadecimal literal values - **Default value**: `Preserve` - **Possible values**: `Upper`, `Lower` -- **Stable**: No +- **Stable**: No (tracking issue: [#5081](https://github.com/rust-lang/rustfmt/issues/5081)) ## `hide_parse_errors` @@ -1072,7 +1072,7 @@ Do not show parse errors if the parser failed to parse files. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3390) +- **Stable**: No (tracking issue: [#3390](https://github.com/rust-lang/rustfmt/issues/3390)) ## `ignore` @@ -1081,7 +1081,7 @@ The pattern format is the same as [.gitignore](https://git-scm.com/docs/gitignor - **Default value**: format every file - **Possible values**: See an example below -- **Stable**: No (tracking issue: #3395) +- **Stable**: No (tracking issue: [#3395](https://github.com/rust-lang/rustfmt/issues/3395)) ### Example @@ -1114,7 +1114,7 @@ Indent style of imports - **Default Value**: `"Block"` - **Possible values**: `"Block"`, `"Visual"` -- **Stable**: No (tracking issue: #3360) +- **Stable**: No (tracking issue: [#3360](https://github.com/rust-lang/rustfmt/issues/3360)) #### `"Block"` (default): @@ -1140,7 +1140,7 @@ Item layout inside a imports block - **Default value**: "Mixed" - **Possible values**: "Horizontal", "HorizontalVertical", "Mixed", "Vertical" -- **Stable**: No (tracking issue: #3361) +- **Stable**: No (tracking issue: [#3361](https://github.com/rust-lang/rustfmt/issues/3361)) #### `"Mixed"` (default): @@ -1203,7 +1203,7 @@ Indent on expressions or items. - **Default value**: `"Block"` - **Possible values**: `"Block"`, `"Visual"` -- **Stable**: No (tracking issue: #3346) +- **Stable**: No (tracking issue: [#3346](https://github.com/rust-lang/rustfmt/issues/3346)) ### Array @@ -1456,7 +1456,7 @@ Write an item and its attribute on the same line if their combined width is belo - **Default value**: 0 - **Possible values**: any positive integer -- **Stable**: No (tracking issue: #3343) +- **Stable**: No (tracking issue: [#3343](https://github.com/rust-lang/rustfmt/issues/3343)) ### Example @@ -1477,7 +1477,7 @@ Check whether beginnings of files match a license template. - **Default value**: `""` - **Possible values**: path to a license template file -- **Stable**: No (tracking issue: #3352) +- **Stable**: No (tracking issue: [#3352](https://github.com/rust-lang/rustfmt/issues/3352)) A license template is a plain text file which is matched literally against the beginning of each source file, except for `{}`-delimited blocks, which are @@ -1499,7 +1499,7 @@ The Style Guide requires that bodies are block wrapped by default if a line brea - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3373) +- **Stable**: No (tracking issue: [#3373](https://github.com/rust-lang/rustfmt/issues/3373)) #### `true` (default): @@ -1701,7 +1701,7 @@ How imports should be grouped into `use` statements. Imports will be merged or s - **Default value**: `Preserve` - **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One` -- **Stable**: No +- **Stable**: No (tracking issue: [#4991](https://github.com/rust-lang/rustfmt/issues/4991)) #### `Preserve` (default): @@ -1826,7 +1826,7 @@ Convert /* */ comments to // comments where possible - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3350) +- **Stable**: No (tracking issue: [#3350](https://github.com/rust-lang/rustfmt/issues/3350)) #### `false` (default): @@ -1854,7 +1854,7 @@ Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3351) +- **Stable**: No (tracking issue: [#3351](https://github.com/rust-lang/rustfmt/issues/3351)) #### `false` (default): @@ -1885,7 +1885,7 @@ instead of being indented on a new line. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3370) +- **Stable**: No (tracking issue: [#3370](https://github.com/rust-lang/rustfmt/issues/3370)) #### `false` (default): @@ -1992,7 +1992,7 @@ Reorder impl items. `type` and `const` are put first, then macros and methods. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3363) +- **Stable**: No (tracking issue: [#3363](https://github.com/rust-lang/rustfmt/issues/3363)) #### `false` (default) @@ -2063,7 +2063,7 @@ Controls the strategy for how imports are grouped together. - **Default value**: `Preserve` - **Possible values**: `Preserve`, `StdExternalCrate`, `One` -- **Stable**: No +- **Stable**: No (tracking issue: [#5083](https://github.com/rust-lang/rustfmt/issues/5083)) #### `Preserve` (default): @@ -2166,7 +2166,7 @@ Report `FIXME` items in comments. - **Default value**: `"Never"` - **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"` -- **Stable**: No (tracking issue: #3394) +- **Stable**: No (tracking issue: [#3394](https://github.com/rust-lang/rustfmt/issues/3394)) Warns about any comments containing `FIXME` in them when set to `"Always"`. If it contains a `#X` (with `X` being a number) in parentheses following the @@ -2181,7 +2181,7 @@ Report `TODO` items in comments. - **Default value**: `"Never"` - **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"` -- **Stable**: No (tracking issue: #3393) +- **Stable**: No (tracking issue: [#3393](https://github.com/rust-lang/rustfmt/issues/3393)) Warns about any comments containing `TODO` in them when set to `"Always"`. If it contains a `#X` (with `X` being a number) in parentheses following the @@ -2196,7 +2196,7 @@ specific version of rustfmt is used in your CI, use this option. - **Default value**: `CARGO_PKG_VERSION` - **Possible values**: any published version (e.g. `"0.3.8"`) -- **Stable**: No (tracking issue: #3386) +- **Stable**: No (tracking issue: [#3386](https://github.com/rust-lang/rustfmt/issues/3386)) ## `skip_children` @@ -2204,7 +2204,7 @@ Don't reformat out of line modules - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3389) +- **Stable**: No (tracking issue: [#3389](https://github.com/rust-lang/rustfmt/issues/3386)) ## `single_line_if_else_max_width` @@ -2224,7 +2224,7 @@ Leave a space after the colon. - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3366) +- **Stable**: No (tracking issue: [#3366](https://github.com/rust-lang/rustfmt/issues/3366)) #### `true` (default): @@ -2256,7 +2256,7 @@ Leave a space before the colon. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3365) +- **Stable**: No (tracking issue: [#3365](https://github.com/rust-lang/rustfmt/issues/3365)) #### `false` (default): @@ -2288,7 +2288,7 @@ Put spaces around the .., ..=, and ... range operators - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3367) +- **Stable**: No (tracking issue: [#3367](https://github.com/rust-lang/rustfmt/issues/3367)) #### `false` (default): @@ -2344,7 +2344,7 @@ The maximum diff of width between struct fields to be aligned with each other. - **Default value** : 0 - **Possible values**: any non-negative integer -- **Stable**: No (tracking issue: #3371) +- **Stable**: No (tracking issue: [#3371](https://github.com/rust-lang/rustfmt/issues/3371)) #### `0` (default): @@ -2372,7 +2372,7 @@ Put small struct literals on a single line - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3357) +- **Stable**: No (tracking issue: [#3357](https://github.com/rust-lang/rustfmt/issues/3357)) #### `true` (default): @@ -2460,7 +2460,7 @@ How to handle trailing commas for lists - **Default value**: `"Vertical"` - **Possible values**: `"Always"`, `"Never"`, `"Vertical"` -- **Stable**: No (tracking issue: #3379) +- **Stable**: No (tracking issue: [#3379](https://github.com/rust-lang/rustfmt/issues/3379)) #### `"Vertical"` (default): @@ -2518,7 +2518,7 @@ Add trailing semicolon after break, continue and return - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3378) +- **Stable**: No (tracking issue: [#3378](https://github.com/rust-lang/rustfmt/issues/3378)) #### `true` (default): ```rust @@ -2540,7 +2540,7 @@ Determines if `+` or `=` are wrapped in spaces in the punctuation of types - **Default value**: `"Wide"` - **Possible values**: `"Compressed"`, `"Wide"` -- **Stable**: No (tracking issue: #3364) +- **Stable**: No (tracking issue: [#3364](https://github.com/rust-lang/rustfmt/issues/3364)) #### `"Wide"` (default): @@ -2564,7 +2564,7 @@ Enable unstable features on the unstable channel. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3387) +- **Stable**: No (tracking issue: [#3387](https://github.com/rust-lang/rustfmt/issues/3387)) ## `use_field_init_shorthand` @@ -2779,7 +2779,7 @@ version number. - **Default value**: `One` - **Possible values**: `One`, `Two` -- **Stable**: No (tracking issue: #3383) +- **Stable**: No (tracking issue: [#3383](https://github.com/rust-lang/rustfmt/issues/3383)) ### Example @@ -2793,7 +2793,7 @@ Forces the `where` clause to be laid out on a single line. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3359) +- **Stable**: No (tracking issue: [#3359](https://github.com/rust-lang/rustfmt/issues/3359)) #### `false` (default): @@ -2825,7 +2825,7 @@ Break comments to fit on the line - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3347) +- **Stable**: No (tracking issue: [#3347](https://github.com/rust-lang/rustfmt/issues/3347)) #### `false` (default): diff --git a/src/tools/rustfmt/README.md b/src/tools/rustfmt/README.md index b3d21e6fb87c7..b3a968f0c043e 100644 --- a/src/tools/rustfmt/README.md +++ b/src/tools/rustfmt/README.md @@ -48,12 +48,11 @@ cargo +nightly fmt ## Limitations Rustfmt tries to work on as much Rust code as possible. Sometimes, the code -doesn't even need to compile! As we approach a 1.0 release we are also looking -to limit areas of instability; in particular, post-1.0, the formatting of most -code should not change as Rustfmt improves. However, there are some things that -Rustfmt can't do or can't do well (and thus where formatting might change -significantly, even post-1.0). We would like to reduce the list of limitations -over time. +doesn't even need to compile! In general, we are looking to limit areas of +instability; in particular, post-1.0, the formatting of most code should not +change as Rustfmt improves. However, there are some things that Rustfmt can't +do or can't do well (and thus where formatting might change significantly, +even post-1.0). We would like to reduce the list of limitations over time. The following list enumerates areas where Rustfmt does not work or where the stability guarantees do not apply (we don't make a distinction between the two diff --git a/src/tools/rustfmt/config_proc_macro/src/lib.rs b/src/tools/rustfmt/config_proc_macro/src/lib.rs index 78e7e098ed9e1..513018213192d 100644 --- a/src/tools/rustfmt/config_proc_macro/src/lib.rs +++ b/src/tools/rustfmt/config_proc_macro/src/lib.rs @@ -8,6 +8,8 @@ mod item_enum; mod item_struct; mod utils; +use std::str::FromStr; + use proc_macro::TokenStream; use syn::parse_macro_input; @@ -23,3 +25,43 @@ pub fn config_type(_args: TokenStream, input: TokenStream) -> TokenStream { TokenStream::from(output) } + +/// Used to conditionally output the TokenStream for tests that need to be run on nightly only. +/// +/// ```rust +/// #[nightly_only_test] +/// #[test] +/// fn test_needs_nightly_rustfmt() { +/// assert!(true); +/// } +/// ``` +#[proc_macro_attribute] +pub fn nightly_only_test(_args: TokenStream, input: TokenStream) -> TokenStream { + // if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is true + if option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") { + input + } else { + // output an empty token stream if CFG_RELEASE_CHANNEL is not set to "nightly" or "dev" + TokenStream::from_str("").unwrap() + } +} + +/// Used to conditionally output the TokenStream for tests that need to be run on stable only. +/// +/// ```rust +/// #[stable_only_test] +/// #[test] +/// fn test_needs_stable_rustfmt() { +/// assert!(true); +/// } +/// ``` +#[proc_macro_attribute] +pub fn stable_only_test(_args: TokenStream, input: TokenStream) -> TokenStream { + // if CFG_RELEASE_CHANNEL is not set we default to nightly, hence why the default is false + if option_env!("CFG_RELEASE_CHANNEL").map_or(false, |c| c == "stable") { + input + } else { + // output an empty token stream if CFG_RELEASE_CHANNEL is not set or is not 'stable' + TokenStream::from_str("").unwrap() + } +} diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs index 7b76c232937dc..0f850b9b2f2fb 100644 --- a/src/tools/rustfmt/src/comment.rs +++ b/src/tools/rustfmt/src/comment.rs @@ -3,6 +3,8 @@ use std::{self, borrow::Cow, iter}; use itertools::{multipeek, MultiPeek}; +use lazy_static::lazy_static; +use regex::Regex; use rustc_span::Span; use crate::config::Config; @@ -15,6 +17,17 @@ use crate::utils::{ }; use crate::{ErrorKind, FormattingError}; +lazy_static! { + /// A regex matching reference doc links. + /// + /// ```markdown + /// /// An [example]. + /// /// + /// /// [example]: this::is::a::link + /// ``` + static ref REFERENCE_LINK_URL: Regex = Regex::new(r"^\[.+\]\s?:").unwrap(); +} + fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { false @@ -506,6 +519,7 @@ struct CommentRewrite<'a> { opener: String, closer: String, line_start: String, + style: CommentStyle<'a>, } impl<'a> CommentRewrite<'a> { @@ -515,10 +529,14 @@ impl<'a> CommentRewrite<'a> { shape: Shape, config: &'a Config, ) -> CommentRewrite<'a> { - let (opener, closer, line_start) = if block_style { - CommentStyle::SingleBullet.to_str_tuplet() + let ((opener, closer, line_start), style) = if block_style { + ( + CommentStyle::SingleBullet.to_str_tuplet(), + CommentStyle::SingleBullet, + ) } else { - comment_style(orig, config.normalize_comments()).to_str_tuplet() + let style = comment_style(orig, config.normalize_comments()); + (style.to_str_tuplet(), style) }; let max_width = shape @@ -551,6 +569,7 @@ impl<'a> CommentRewrite<'a> { opener: opener.to_owned(), closer: closer.to_owned(), line_start: line_start.to_owned(), + style, }; cr.result.push_str(opener); cr @@ -570,6 +589,15 @@ impl<'a> CommentRewrite<'a> { result } + /// Check if any characters were written to the result buffer after the start of the comment. + /// when calling [`CommentRewrite::new()`] the result buffer is initiazlied with the opening + /// characters for the comment. + fn buffer_contains_comment(&self) -> bool { + // if self.result.len() < self.opener.len() then an empty comment is in the buffer + // if self.result.len() > self.opener.len() then a non empty comment is in the buffer + self.result.len() != self.opener.len() + } + fn finish(mut self) -> String { if !self.code_block_buffer.is_empty() { // There is a code block that is not properly enclosed by backticks. @@ -585,7 +613,12 @@ impl<'a> CommentRewrite<'a> { // the last few lines are part of an itemized block self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent); let item_fmt = ib.create_string_format(&self.fmt); - self.result.push_str(&self.comment_line_separator); + + // only push a comment_line_separator for ItemizedBlocks if the comment is not empty + if self.buffer_contains_comment() { + self.result.push_str(&self.comment_line_separator); + } + self.result.push_str(&ib.opener); match rewrite_string( &ib.trimmed_block_as_string(), @@ -619,7 +652,13 @@ impl<'a> CommentRewrite<'a> { line: &'a str, has_leading_whitespace: bool, ) -> bool { - let is_last = i == count_newlines(orig); + let num_newlines = count_newlines(orig); + let is_last = i == num_newlines; + let needs_new_comment_line = if self.style.is_block_comment() { + num_newlines > 0 || self.buffer_contains_comment() + } else { + self.buffer_contains_comment() + }; if let Some(ref mut ib) = self.item_block { if ib.add_line(line) { @@ -628,7 +667,12 @@ impl<'a> CommentRewrite<'a> { self.is_prev_line_multi_line = false; self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent); let item_fmt = ib.create_string_format(&self.fmt); - self.result.push_str(&self.comment_line_separator); + + // only push a comment_line_separator if we need to start a new comment line + if needs_new_comment_line { + self.result.push_str(&self.comment_line_separator); + } + self.result.push_str(&ib.opener); match rewrite_string( &ib.trimmed_block_as_string(), @@ -842,7 +886,11 @@ fn trim_custom_comment_prefix(s: &str) -> String { /// Returns `true` if the given string MAY include URLs or alike. fn has_url(s: &str) -> bool { // This function may return false positive, but should get its job done in most cases. - s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://") + s.contains("https://") + || s.contains("http://") + || s.contains("ftp://") + || s.contains("file://") + || REFERENCE_LINK_URL.is_match(s) } /// Given the span, rewrite the missing comment inside it if available. diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index c5419d860c943..5dbe532ac388f 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -405,6 +405,8 @@ mod test { use super::*; use std::str; + use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test}; + #[allow(dead_code)] mod mock { use super::super::*; @@ -525,21 +527,17 @@ mod test { assert!(config.license_template.is_none()); } + #[nightly_only_test] #[test] fn test_valid_license_template_path() { - if !crate::is_nightly_channel!() { - return; - } let toml = r#"license_template_path = "tests/license-template/lt.txt""#; let config = Config::from_toml(toml, Path::new("")).unwrap(); assert!(config.license_template.is_some()); } + #[nightly_only_test] #[test] fn test_override_existing_license_with_no_license() { - if !crate::is_nightly_channel!() { - return; - } let toml = r#"license_template_path = "tests/license-template/lt.txt""#; let mut config = Config::from_toml(toml, Path::new("")).unwrap(); assert!(config.license_template.is_some()); @@ -634,48 +632,42 @@ make_backup = false assert_eq!(&toml, &default_config); } - // FIXME(#2183): these tests cannot be run in parallel because they use env vars. - // #[test] - // fn test_as_not_nightly_channel() { - // let mut config = Config::default(); - // assert_eq!(config.was_set().unstable_features(), false); - // config.set().unstable_features(true); - // assert_eq!(config.was_set().unstable_features(), false); - // } - - // #[test] - // fn test_as_nightly_channel() { - // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); - // let mut config = Config::default(); - // config.set().unstable_features(true); - // assert_eq!(config.was_set().unstable_features(), false); - // config.set().unstable_features(true); - // assert_eq!(config.unstable_features(), true); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); - // } - - // #[test] - // fn test_unstable_from_toml() { - // let mut config = Config::from_toml("unstable_features = true").unwrap(); - // assert_eq!(config.was_set().unstable_features(), false); - // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); - // config = Config::from_toml("unstable_features = true").unwrap(); - // assert_eq!(config.was_set().unstable_features(), true); - // assert_eq!(config.unstable_features(), true); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); - // } + #[stable_only_test] + #[test] + fn test_as_not_nightly_channel() { + let mut config = Config::default(); + assert_eq!(config.was_set().unstable_features(), false); + config.set().unstable_features(true); + assert_eq!(config.was_set().unstable_features(), false); + } + + #[nightly_only_test] + #[test] + fn test_as_nightly_channel() { + let mut config = Config::default(); + config.set().unstable_features(true); + // When we don't set the config from toml or command line options it + // doesn't get marked as set by the user. + assert_eq!(config.was_set().unstable_features(), false); + config.set().unstable_features(true); + assert_eq!(config.unstable_features(), true); + } + + #[nightly_only_test] + #[test] + fn test_unstable_from_toml() { + let config = Config::from_toml("unstable_features = true", Path::new("")).unwrap(); + assert_eq!(config.was_set().unstable_features(), true); + assert_eq!(config.unstable_features(), true); + } #[cfg(test)] mod deprecated_option_merge_imports { use super::*; + #[nightly_only_test] #[test] fn test_old_option_set() { - if !crate::is_nightly_channel!() { - return; - } let toml = r#" unstable_features = true merge_imports = true @@ -684,11 +676,9 @@ make_backup = false assert_eq!(config.imports_granularity(), ImportGranularity::Crate); } + #[nightly_only_test] #[test] fn test_both_set() { - if !crate::is_nightly_channel!() { - return; - } let toml = r#" unstable_features = true merge_imports = true @@ -698,11 +688,9 @@ make_backup = false assert_eq!(config.imports_granularity(), ImportGranularity::Preserve); } + #[nightly_only_test] #[test] fn test_new_overridden() { - if !crate::is_nightly_channel!() { - return; - } let toml = r#" unstable_features = true merge_imports = true @@ -712,11 +700,9 @@ make_backup = false assert_eq!(config.imports_granularity(), ImportGranularity::Preserve); } + #[nightly_only_test] #[test] fn test_old_overridden() { - if !crate::is_nightly_channel!() { - return; - } let toml = r#" unstable_features = true imports_granularity = "Module" diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 58942e442de05..5fd86c1a4eadd 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -196,9 +196,10 @@ pub(crate) fn format_expr( capture, is_async, movability, fn_decl, body, expr.span, context, shape, ) } - ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => { - rewrite_chain(expr, context, shape) - } + ast::ExprKind::Try(..) + | ast::ExprKind::Field(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { wrap_str( @@ -377,7 +378,6 @@ pub(crate) fn format_expr( )) } } - ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape), ast::ExprKind::Underscore => Some("_".to_owned()), ast::ExprKind::Err => None, }; @@ -829,6 +829,7 @@ impl<'a> ControlFlow<'a> { &format!("{}{}{}", matcher, pat_string, self.connector), expr, cond_shape, + &RhsAssignKind::Expr(&expr.kind, expr.span), RhsTactics::Default, comments_span, true, @@ -1839,6 +1840,34 @@ fn rewrite_unary_op( rewrite_unary_prefix(context, ast::UnOp::to_string(op), expr, shape) } +pub(crate) enum RhsAssignKind<'ast> { + Expr(&'ast ast::ExprKind, Span), + Bounds, + Ty, +} + +impl<'ast> RhsAssignKind<'ast> { + // TODO(calebcartwright) + // Preemptive addition for handling RHS with chains, not yet utilized. + // It may make more sense to construct the chain first and then check + // whether there are actually chain elements. + #[allow(dead_code)] + fn is_chain(&self) -> bool { + match self { + RhsAssignKind::Expr(kind, _) => { + matches!( + kind, + ast::ExprKind::Try(..) + | ast::ExprKind::Field(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Await(_) + ) + } + _ => false, + } + } +} + fn rewrite_assignment( context: &RewriteContext<'_>, lhs: &ast::Expr, @@ -1855,7 +1884,13 @@ fn rewrite_assignment( let lhs_shape = shape.sub_width(operator_str.len() + 1)?; let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str); - rewrite_assign_rhs(context, lhs_str, rhs, shape) + rewrite_assign_rhs( + context, + lhs_str, + rhs, + &RhsAssignKind::Expr(&rhs.kind, rhs.span), + shape, + ) } /// Controls where to put the rhs. @@ -1876,9 +1911,10 @@ pub(crate) fn rewrite_assign_rhs, R: Rewrite>( context: &RewriteContext<'_>, lhs: S, ex: &R, + rhs_kind: &RhsAssignKind<'_>, shape: Shape, ) -> Option { - rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default) + rewrite_assign_rhs_with(context, lhs, ex, shape, rhs_kind, RhsTactics::Default) } pub(crate) fn rewrite_assign_rhs_expr( @@ -1886,6 +1922,7 @@ pub(crate) fn rewrite_assign_rhs_expr( lhs: &str, ex: &R, shape: Shape, + rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, ) -> Option { let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') { @@ -1910,6 +1947,7 @@ pub(crate) fn rewrite_assign_rhs_expr( ex, orig_shape, ex.rewrite(context, orig_shape), + rhs_kind, rhs_tactics, has_rhs_comment, ) @@ -1920,10 +1958,11 @@ pub(crate) fn rewrite_assign_rhs_with, R: Rewrite>( lhs: S, ex: &R, shape: Shape, + rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, ) -> Option { let lhs = lhs.into(); - let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?; + let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?; Some(lhs + &rhs) } @@ -1932,6 +1971,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments, R: Rewrite>( lhs: S, ex: &R, shape: Shape, + rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, between_span: Span, allow_extend: bool, @@ -1943,7 +1983,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments, R: Rewrite>( } else { shape }; - let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?; + let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?; if contains_comment { let rhs = rhs.trim_start(); @@ -1958,6 +1998,7 @@ fn choose_rhs( expr: &R, shape: Shape, orig_rhs: Option, + _rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, has_rhs_comment: bool, ) -> Option { diff --git a/src/tools/rustfmt/src/ignore_path.rs b/src/tools/rustfmt/src/ignore_path.rs index d8974e12b8f5f..7738eee0a7604 100644 --- a/src/tools/rustfmt/src/ignore_path.rs +++ b/src/tools/rustfmt/src/ignore_path.rs @@ -37,21 +37,17 @@ mod test { use crate::config::{Config, FileName}; use crate::ignore_path::IgnorePathSet; + use rustfmt_config_proc_macro::nightly_only_test; + + #[nightly_only_test] #[test] fn test_ignore_path_set() { - match option_env!("CFG_RELEASE_CHANNEL") { - // this test requires nightly - None | Some("nightly") => { - let config = - Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new("")) - .unwrap(); - let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap(); - - assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs")))); - assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs")))); - assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs")))); - } - _ => (), - }; + let config = + Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new("")).unwrap(); + let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap(); + + assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs")))); + assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs")))); + assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs")))); } } diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index acc91f861e474..f36bdba26e98e 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -18,7 +18,7 @@ use crate::config::lists::*; use crate::config::{BraceStyle, Config, IndentStyle, Version}; use crate::expr::{ is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, - rewrite_assign_rhs_with_comments, RhsTactics, + rewrite_assign_rhs_with_comments, RhsAssignKind, RhsTactics, }; use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use crate::macros::{rewrite_macro, MacroPosition}; @@ -28,6 +28,7 @@ use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt::Stmt; +use crate::types::opaque_ty; use crate::utils::*; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; @@ -115,7 +116,13 @@ impl Rewrite for ast::Local { // 1 = trailing semicolon; let nested_shape = shape.sub_width(1)?; - result = rewrite_assign_rhs(context, result, init, nested_shape)?; + result = rewrite_assign_rhs( + context, + result, + init, + &RhsAssignKind::Expr(&init.kind, init.span), + nested_shape, + )?; // todo else } @@ -563,11 +570,13 @@ impl<'a> FmtVisitor<'a> { let variant_body = if let Some(ref expr) = field.disr_expr { let lhs = format!("{:1$} =", variant_body, pad_discrim_ident_to); + let ex = &*expr.value; rewrite_assign_rhs_with( &context, lhs, - &*expr.value, + ex, shape, + &RhsAssignKind::Expr(&ex.kind, ex.span), RhsTactics::AllowOverflow, )? } else { @@ -579,6 +588,22 @@ impl<'a> FmtVisitor<'a> { fn visit_impl_items(&mut self, items: &[ptr::P]) { if self.get_context().config.reorder_impl_items() { + type TyOpt = Option>; + use crate::ast::AssocItemKind::*; + let is_type = |ty: &TyOpt| opaque_ty(ty).is_none(); + let is_opaque = |ty: &TyOpt| opaque_ty(ty).is_some(); + let both_type = |l: &TyOpt, r: &TyOpt| is_type(l) && is_type(r); + let both_opaque = |l: &TyOpt, r: &TyOpt| is_opaque(l) && is_opaque(r); + let need_empty_line = |a: &ast::AssocItemKind, b: &ast::AssocItemKind| match (a, b) { + (TyAlias(lty), TyAlias(rty)) + if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) => + { + false + } + (Const(..), Const(..)) => false, + _ => true, + }; + // Create visitor for each items, then reorder them. let mut buffer = vec![]; for item in items { @@ -587,50 +612,6 @@ impl<'a> FmtVisitor<'a> { self.buffer.clear(); } - fn is_type(ty: &Option>) -> bool { - if let Some(lty) = ty { - if let ast::TyKind::ImplTrait(..) = lty.kind { - return false; - } - } - true - } - - fn is_opaque(ty: &Option>) -> bool { - !is_type(ty) - } - - fn both_type( - a: &Option>, - b: &Option>, - ) -> bool { - is_type(a) && is_type(b) - } - - fn both_opaque( - a: &Option>, - b: &Option>, - ) -> bool { - is_opaque(a) && is_opaque(b) - } - - // In rustc-ap-v638 the `OpaqueTy` AssocItemKind variant was removed but - // we still need to differentiate to maintain sorting order. - - // type -> opaque -> const -> macro -> method - use crate::ast::AssocItemKind::*; - fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool { - match (a, b) { - (TyAlias(lty), TyAlias(rty)) - if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) => - { - false - } - (Const(..), Const(..)) => false, - _ => true, - } - } - buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) { (TyAlias(lty), TyAlias(rty)) if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) => @@ -676,136 +657,133 @@ impl<'a> FmtVisitor<'a> { pub(crate) fn format_impl( context: &RewriteContext<'_>, item: &ast::Item, + iimpl: &ast::Impl, offset: Indent, ) -> Option { - if let ast::ItemKind::Impl(impl_kind) = &item.kind { - let ast::Impl { - ref generics, - ref self_ty, - ref items, - .. - } = **impl_kind; - let mut result = String::with_capacity(128); - let ref_and_type = format_impl_ref_and_type(context, item, offset)?; - let sep = offset.to_string_with_newline(context.config); - result.push_str(&ref_and_type); + let ast::Impl { + generics, + self_ty, + items, + .. + } = iimpl; + let mut result = String::with_capacity(128); + let ref_and_type = format_impl_ref_and_type(context, item, iimpl, offset)?; + let sep = offset.to_string_with_newline(context.config); + result.push_str(&ref_and_type); - let where_budget = if result.contains('\n') { - context.config.max_width() - } else { - context.budget(last_line_width(&result)) - }; + let where_budget = if result.contains('\n') { + context.config.max_width() + } else { + context.budget(last_line_width(&result)) + }; - let mut option = WhereClauseOption::snuggled(&ref_and_type); - let snippet = context.snippet(item.span); - let open_pos = snippet.find_uncommented("{")? + 1; - if !contains_comment(&snippet[open_pos..]) - && items.is_empty() - && generics.where_clause.predicates.len() == 1 - && !result.contains('\n') - { - option.suppress_comma(); - option.snuggle(); - option.allow_single_line(); - } + let mut option = WhereClauseOption::snuggled(&ref_and_type); + let snippet = context.snippet(item.span); + let open_pos = snippet.find_uncommented("{")? + 1; + if !contains_comment(&snippet[open_pos..]) + && items.is_empty() + && generics.where_clause.predicates.len() == 1 + && !result.contains('\n') + { + option.suppress_comma(); + option.snuggle(); + option.allow_single_line(); + } - let missing_span = mk_sp(self_ty.span.hi(), item.span.hi()); - let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{"); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - false, - "{", - where_span_end, - self_ty.span.hi(), - option, - )?; + let missing_span = mk_sp(self_ty.span.hi(), item.span.hi()); + let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{"); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + false, + "{", + where_span_end, + self_ty.span.hi(), + option, + )?; - // If there is no where-clause, we may have missing comments between the trait name and - // the opening brace. - if generics.where_clause.predicates.is_empty() { - if let Some(hi) = where_span_end { - match recover_missing_comment_in_span( - mk_sp(self_ty.span.hi(), hi), - Shape::indented(offset, context.config), - context, - last_line_width(&result), - ) { - Some(ref missing_comment) if !missing_comment.is_empty() => { - result.push_str(missing_comment); - } - _ => (), + // If there is no where-clause, we may have missing comments between the trait name and + // the opening brace. + if generics.where_clause.predicates.is_empty() { + if let Some(hi) = where_span_end { + match recover_missing_comment_in_span( + mk_sp(self_ty.span.hi(), hi), + Shape::indented(offset, context.config), + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); } + _ => (), } } + } - if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? { - result.push_str(&where_clause_str); - if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { - // if the where_clause contains extra comments AND - // there is only one where-clause predicate - // recover the suppressed comma in single line where_clause formatting - if generics.where_clause.predicates.len() == 1 { - result.push(','); - } - result.push_str(&format!("{}{{{}}}", sep, sep)); - } else { - result.push_str(" {}"); + if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? { + result.push_str(&where_clause_str); + if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { + // if the where_clause contains extra comments AND + // there is only one where-clause predicate + // recover the suppressed comma in single line where_clause formatting + if generics.where_clause.predicates.len() == 1 { + result.push(','); } - return Some(result); + result.push_str(&format!("{}{{{}}}", sep, sep)); + } else { + result.push_str(" {}"); } + return Some(result); + } - result.push_str(&where_clause_str); + result.push_str(&where_clause_str); - let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n'); - match context.config.brace_style() { - _ if need_newline => result.push_str(&sep), - BraceStyle::AlwaysNextLine => result.push_str(&sep), - BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() { - result.push_str(&sep); - } else { - result.push(' '); - } + let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n'); + match context.config.brace_style() { + _ if need_newline => result.push_str(&sep), + BraceStyle::AlwaysNextLine => result.push_str(&sep), + BraceStyle::PreferSameLine => result.push(' '), + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() { + result.push_str(&sep); + } else { + result.push(' '); } } + } - result.push('{'); - // this is an impl body snippet(impl SampleImpl { /* here */ }) - let lo = max(self_ty.span.hi(), generics.where_clause.span.hi()); - let snippet = context.snippet(mk_sp(lo, item.span.hi())); - let open_pos = snippet.find_uncommented("{")? + 1; + result.push('{'); + // this is an impl body snippet(impl SampleImpl { /* here */ }) + let lo = max(self_ty.span.hi(), generics.where_clause.span.hi()); + let snippet = context.snippet(mk_sp(lo, item.span.hi())); + let open_pos = snippet.find_uncommented("{")? + 1; - if !items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_context(context); - let item_indent = offset.block_only().block_indent(context.config); - visitor.block_indent = item_indent; - visitor.last_pos = lo + BytePos(open_pos as u32); + if !items.is_empty() || contains_comment(&snippet[open_pos..]) { + let mut visitor = FmtVisitor::from_context(context); + let item_indent = offset.block_only().block_indent(context.config); + visitor.block_indent = item_indent; + visitor.last_pos = lo + BytePos(open_pos as u32); - visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); - visitor.visit_impl_items(items); + visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); + visitor.visit_impl_items(items); - visitor.format_missing(item.span.hi() - BytePos(1)); + visitor.format_missing(item.span.hi() - BytePos(1)); - let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); - let outer_indent_str = offset.block_only().to_string_with_newline(context.config); + let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); + let outer_indent_str = offset.block_only().to_string_with_newline(context.config); - result.push_str(&inner_indent_str); - result.push_str(visitor.buffer.trim()); - result.push_str(&outer_indent_str); - } else if need_newline || !context.config.empty_item_single_line() { - result.push_str(&sep); - } + result.push_str(&inner_indent_str); + result.push_str(visitor.buffer.trim()); + result.push_str(&outer_indent_str); + } else if need_newline || !context.config.empty_item_single_line() { + result.push_str(&sep); + } - result.push('}'); + result.push('}'); - Some(result) - } else { - unreachable!(); - } + Some(result) } fn is_impl_single_line( @@ -830,111 +808,106 @@ fn is_impl_single_line( fn format_impl_ref_and_type( context: &RewriteContext<'_>, item: &ast::Item, + iimpl: &ast::Impl, offset: Indent, ) -> Option { - if let ast::ItemKind::Impl(impl_kind) = &item.kind { - let ast::Impl { - unsafety, - polarity, - defaultness, - constness, - ref generics, - of_trait: ref trait_ref, - ref self_ty, - .. - } = **impl_kind; - let mut result = String::with_capacity(128); + let ast::Impl { + unsafety, + polarity, + defaultness, + constness, + ref generics, + of_trait: ref trait_ref, + ref self_ty, + .. + } = *iimpl; + let mut result = String::with_capacity(128); - result.push_str(&format_visibility(context, &item.vis)); - result.push_str(format_defaultness(defaultness)); - result.push_str(format_unsafety(unsafety)); + result.push_str(&format_visibility(context, &item.vis)); + result.push_str(format_defaultness(defaultness)); + result.push_str(format_unsafety(unsafety)); - let shape = if context.config.version() == Version::Two { - Shape::indented(offset + last_line_width(&result), context.config) - } else { - generics_shape_from_config( - context.config, - Shape::indented(offset + last_line_width(&result), context.config), - 0, - )? - }; - let generics_str = rewrite_generics(context, "impl", generics, shape)?; - result.push_str(&generics_str); - result.push_str(format_constness_right(constness)); + let shape = if context.config.version() == Version::Two { + Shape::indented(offset + last_line_width(&result), context.config) + } else { + generics_shape_from_config( + context.config, + Shape::indented(offset + last_line_width(&result), context.config), + 0, + )? + }; + let generics_str = rewrite_generics(context, "impl", generics, shape)?; + result.push_str(&generics_str); + result.push_str(format_constness_right(constness)); - let polarity_str = match polarity { - ast::ImplPolarity::Negative(_) => "!", - ast::ImplPolarity::Positive => "", - }; + let polarity_str = match polarity { + ast::ImplPolarity::Negative(_) => "!", + ast::ImplPolarity::Positive => "", + }; - let polarity_overhead; - let trait_ref_overhead; - if let Some(ref trait_ref) = *trait_ref { - let result_len = last_line_width(&result); - result.push_str(&rewrite_trait_ref( - context, - trait_ref, - offset, - polarity_str, - result_len, - )?); - polarity_overhead = 0; // already written - trait_ref_overhead = " for".len(); - } else { - polarity_overhead = polarity_str.len(); - trait_ref_overhead = 0; - } + let polarity_overhead; + let trait_ref_overhead; + if let Some(ref trait_ref) = *trait_ref { + let result_len = last_line_width(&result); + result.push_str(&rewrite_trait_ref( + context, + trait_ref, + offset, + polarity_str, + result_len, + )?); + polarity_overhead = 0; // already written + trait_ref_overhead = " for".len(); + } else { + polarity_overhead = polarity_str.len(); + trait_ref_overhead = 0; + } - // Try to put the self type in a single line. - let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { - // If there is no where-clause adapt budget for type formatting to take space and curly - // brace into account. - match context.config.brace_style() { - BraceStyle::AlwaysNextLine => 0, - _ => 2, - } - } else { - 0 - }; - let used_space = last_line_width(&result) - + polarity_overhead - + trait_ref_overhead - + curly_brace_overhead; - // 1 = space before the type. - let budget = context.budget(used_space + 1); - if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { - if !self_ty_str.contains('\n') { - if trait_ref.is_some() { - result.push_str(" for "); - } else { - result.push(' '); - result.push_str(polarity_str); - } - result.push_str(&self_ty_str); - return Some(result); + // Try to put the self type in a single line. + let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { + // If there is no where-clause adapt budget for type formatting to take space and curly + // brace into account. + match context.config.brace_style() { + BraceStyle::AlwaysNextLine => 0, + _ => 2, + } + } else { + 0 + }; + let used_space = + last_line_width(&result) + polarity_overhead + trait_ref_overhead + curly_brace_overhead; + // 1 = space before the type. + let budget = context.budget(used_space + 1); + if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { + if !self_ty_str.contains('\n') { + if trait_ref.is_some() { + result.push_str(" for "); + } else { + result.push(' '); + result.push_str(polarity_str); } + result.push_str(&self_ty_str); + return Some(result); } + } - // Couldn't fit the self type on a single line, put it on a new line. - result.push('\n'); - // Add indentation of one additional tab. - let new_line_offset = offset.block_indent(context.config); - result.push_str(&new_line_offset.to_string(context.config)); - if trait_ref.is_some() { - result.push_str("for "); - } else { - result.push_str(polarity_str); - } - let budget = context.budget(last_line_width(&result) + polarity_overhead); - let type_offset = match context.config.indent_style() { - IndentStyle::Visual => new_line_offset + trait_ref_overhead, - IndentStyle::Block => new_line_offset, - }; - result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); - Some(result) + // Couldn't fit the self type on a single line, put it on a new line. + result.push('\n'); + // Add indentation of one additional tab. + let new_line_offset = offset.block_indent(context.config); + result.push_str(&new_line_offset.to_string(context.config)); + if trait_ref.is_some() { + result.push_str("for "); } else { - unreachable!(); + result.push_str(polarity_str); } + let budget = context.budget(last_line_width(&result) + polarity_overhead); + let type_offset = match context.config.indent_style() { + IndentStyle::Visual => new_line_offset + trait_ref_overhead, + IndentStyle::Block => new_line_offset, + }; + result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); + Some(result) } fn rewrite_trait_ref( @@ -1068,6 +1041,7 @@ pub(crate) fn format_trait( result + ":", bounds, shape, + &RhsAssignKind::Bounds, RhsTactics::ForceNextLineWithoutIndent, )?; } @@ -1248,7 +1222,14 @@ pub(crate) fn format_trait_alias( generic_bounds, generics, }; - rewrite_assign_rhs(context, lhs, &trait_alias_bounds, shape.sub_width(1)?).map(|s| s + ";") + rewrite_assign_rhs( + context, + lhs, + &trait_alias_bounds, + &RhsAssignKind::Bounds, + shape.sub_width(1)?, + ) + .map(|s| s + ";") } fn format_unit_struct( @@ -1541,43 +1522,38 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( ref bounds, ref ty, } = *ty_alias_kind; - let ty_opt = ty.as_ref().map(|t| &**t); + let ty_opt = ty.as_ref(); let (ident, vis) = match visitor_kind { Item(i) => (i.ident, &i.vis), AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis), ForeignItem(i) => (i.ident, &i.vis), }; let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span); - + let op_ty = opaque_ty(ty); // Type Aliases are formatted slightly differently depending on the context // in which they appear, whether they are opaque, and whether they are associated. // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases - match (visitor_kind, ty_opt) { - (Item(_), None) => { - let op_ty = OpaqueType { bounds }; - rewrite_ty(rw_info, Some(bounds), Some(&op_ty), vis) + match (visitor_kind, &op_ty) { + (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(ref op_bounds)) => { + let op = OpaqueType { bounds: op_bounds }; + rewrite_ty(rw_info, Some(bounds), Some(&op), vis) + } + (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => { + rewrite_ty(rw_info, Some(bounds), ty_opt, vis) } - (Item(_), Some(ty)) => rewrite_ty(rw_info, Some(bounds), Some(&*ty), vis), (AssocImplItem(_), _) => { - let result = if let Some(ast::Ty { - kind: ast::TyKind::ImplTrait(_, ref bounds), - .. - }) = ty_opt - { - let op_ty = OpaqueType { bounds }; - rewrite_ty(rw_info, None, Some(&op_ty), &DEFAULT_VISIBILITY) + let result = if let Some(ref op_bounds) = op_ty { + let op = OpaqueType { bounds: op_bounds }; + rewrite_ty(rw_info, Some(bounds), Some(&op), &DEFAULT_VISIBILITY) } else { - rewrite_ty(rw_info, None, ty.as_ref(), vis) + rewrite_ty(rw_info, Some(bounds), ty_opt, vis) }?; match defaultness { ast::Defaultness::Default(..) => Some(format!("default {}", result)), _ => Some(result), } } - (AssocTraitItem(_), _) | (ForeignItem(_), _) => { - rewrite_ty(rw_info, Some(bounds), ty.as_ref(), vis) - } } } @@ -1670,7 +1646,7 @@ fn rewrite_ty( // 1 = `;` let shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, lhs, &*ty, shape).map(|s| s + ";") + rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";") } else { Some(format!("{};", result)) } @@ -1760,7 +1736,7 @@ pub(crate) fn rewrite_struct_field( let is_prefix_empty = prefix.is_empty(); // We must use multiline. We are going to put attributes and a field on different lines. - let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?; + let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, &RhsAssignKind::Ty, shape)?; // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. let field_str = if is_prefix_empty { field_str.trim_start() @@ -1890,6 +1866,7 @@ fn rewrite_static( &lhs, &**expr, Shape::legacy(remaining_width, offset.block_only()), + &RhsAssignKind::Expr(&expr.kind, expr.span), RhsTactics::Default, comments_span, true, @@ -1900,6 +1877,12 @@ fn rewrite_static( Some(format!("{}{};", prefix, ty_str)) } } + +// FIXME(calebcartwright) - This is a hack around a bug in the handling of TyKind::ImplTrait. +// This should be removed once that bug is resolved, with the type alias formatting using the +// defined Ty for the RHS directly. +// https://github.com/rust-lang/rustfmt/issues/4373 +// https://github.com/rust-lang/rustfmt/issues/5027 struct OpaqueType<'a> { bounds: &'a ast::GenericBounds, } @@ -3173,7 +3156,14 @@ impl Rewrite for ast::ForeignItem { rewrite_ident(context, self.ident) ); // 1 = ; - rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") + rewrite_assign_rhs( + context, + prefix, + &**ty, + &RhsAssignKind::Ty, + shape.sub_width(1)?, + ) + .map(|s| s + ";") } ast::ForeignItemKind::TyAlias(ref ty_alias) => { let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span); diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs index d341ec8e6b0e7..3515dd172510c 100644 --- a/src/tools/rustfmt/src/lists.rs +++ b/src/tools/rustfmt/src/lists.rs @@ -444,10 +444,15 @@ where let offset = formatting.shape.indent + overhead; let comment_shape = Shape::legacy(width, offset); - // Use block-style only for the last item or multiline comments. - let block_style = !formatting.ends_with_newline && last - || comment.trim().contains('\n') - || comment.trim().len() > width; + let block_style = if !formatting.ends_with_newline && last { + true + } else if starts_with_newline(comment) { + false + } else if comment.trim().contains('\n') || comment.trim().len() > width { + true + } else { + false + }; rewrite_comment( comment.trim_start(), diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index ef747638e33ec..a52568be9eac4 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -27,7 +27,7 @@ use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, }; use crate::config::lists::*; -use crate::expr::rewrite_array; +use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind}; use crate::lists::{itemize_list, write_list, ListFormatting}; use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext}; @@ -1468,10 +1468,11 @@ fn format_lazy_static( id, ty.rewrite(context, nested_shape)? )); - result.push_str(&crate::expr::rewrite_assign_rhs( + result.push_str(&rewrite_assign_rhs( context, stmt, &*expr, + &RhsAssignKind::Expr(&expr.kind, expr.span), nested_shape.sub_width(1)?, )?); result.push(';'); diff --git a/src/tools/rustfmt/src/syntux/session.rs b/src/tools/rustfmt/src/syntux/session.rs index cdb4893d443b9..dd7c7352686e6 100644 --- a/src/tools/rustfmt/src/syntux/session.rs +++ b/src/tools/rustfmt/src/syntux/session.rs @@ -286,10 +286,11 @@ impl LineRangeUtils for ParseSess { mod tests { use super::*; + use rustfmt_config_proc_macro::nightly_only_test; + mod emitter { use super::*; use crate::config::IgnoreList; - use crate::is_nightly_channel; use crate::utils::mk_sp; use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName, DUMMY_SP}; use std::path::PathBuf; @@ -371,11 +372,9 @@ mod tests { assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } + #[nightly_only_test] #[test] fn handles_recoverable_parse_error_in_ignored_file() { - if !is_nightly_channel!() { - return; - } let num_emitted_errors = Lrc::new(AtomicU32::new(0)); let can_reset_errors = Lrc::new(AtomicBool::new(false)); let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); @@ -398,11 +397,9 @@ mod tests { assert_eq!(can_reset_errors.load(Ordering::Acquire), true); } + #[nightly_only_test] #[test] fn handles_recoverable_parse_error_in_non_ignored_file() { - if !is_nightly_channel!() { - return; - } let num_emitted_errors = Lrc::new(AtomicU32::new(0)); let can_reset_errors = Lrc::new(AtomicBool::new(false)); let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); @@ -424,11 +421,9 @@ mod tests { assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } + #[nightly_only_test] #[test] fn handles_mix_of_recoverable_parse_error() { - if !is_nightly_channel!() { - return; - } let num_emitted_errors = Lrc::new(AtomicU32::new(0)); let can_reset_errors = Lrc::new(AtomicBool::new(false)); let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs index e2620508c340b..cceb28dfea6d7 100644 --- a/src/tools/rustfmt/src/test/mod.rs +++ b/src/tools/rustfmt/src/test/mod.rs @@ -15,6 +15,8 @@ use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChu use crate::source_file; use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session}; +use rustfmt_config_proc_macro::nightly_only_test; + mod configuration_snippet; mod mod_resolver; mod parser; @@ -307,14 +309,11 @@ fn assert_output(source: &Path, expected_filename: &Path) { // Idempotence tests. Files in tests/target are checked to be unaltered by // rustfmt. +#[nightly_only_test] #[test] fn idempotence_tests() { init_log(); run_test_with(&TestSetting::default(), || { - // these tests require nightly - if !is_nightly_channel!() { - return; - } // Get all files in the tests/target directory. let files = get_test_files(Path::new("tests/target"), true); let (_reports, count, fails) = check_files(files, &None); @@ -332,13 +331,11 @@ fn idempotence_tests() { // Run rustfmt on itself. This operation must be idempotent. We also check that // no warnings are emitted. +// Issue-3443: these tests require nightly +#[nightly_only_test] #[test] fn self_tests() { init_log(); - // Issue-3443: these tests require nightly - if !is_nightly_channel!() { - return; - } let mut files = get_test_files(Path::new("tests"), false); let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; for dir in bin_directories { diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 9ea90c5e46dd8..88f5dc4324510 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -2,6 +2,7 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability}; +use rustc_ast::ptr; use rustc_span::{symbol::kw, BytePos, Pos, Span}; use crate::comment::{combine_strs_with_missing_comments, contains_comment}; @@ -9,6 +10,7 @@ use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; use crate::expr::{ format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType, + RhsAssignKind, }; use crate::lists::{ definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, @@ -429,7 +431,7 @@ impl Rewrite for ast::WherePredicate { format!("{}{}", type_str, colon) }; - rewrite_assign_rhs(context, lhs, bounds, shape)? + rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape)? } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, @@ -442,7 +444,7 @@ impl Rewrite for ast::WherePredicate { .. }) => { let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?; - rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, shape)? + rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)? } }; @@ -1031,6 +1033,13 @@ fn join_bounds_inner( } } +pub(crate) fn opaque_ty(ty: &Option>) -> Option<&ast::GenericBounds> { + ty.as_ref().and_then(|t| match &t.kind { + ast::TyKind::ImplTrait(_, bounds) => Some(bounds), + _ => None, + }) +} + pub(crate) fn can_be_overflowed_type( context: &RewriteContext<'_>, ty: &ast::Ty, diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 527042d098a1c..e4a7be742abcb 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -485,9 +485,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if should_visit_node_again { match item.kind { ast::ItemKind::Use(ref tree) => self.format_import(item, tree), - ast::ItemKind::Impl { .. } => { + ast::ItemKind::Impl(ref iimpl) => { let block_indent = self.block_indent; - let rw = self.with_context(|ctx| format_impl(ctx, item, block_indent)); + let rw = self.with_context(|ctx| format_impl(ctx, item, iimpl, block_indent)); self.push_rewrite(item.span, rw); } ast::ItemKind::Trait(..) => { diff --git a/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-not-normalized.rs b/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-not-normalized.rs new file mode 100644 index 0000000000000..b96c02802d69c --- /dev/null +++ b/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-not-normalized.rs @@ -0,0 +1,129 @@ +// rustfmt-wrap_comments: true + +// https://github.com/rust-lang/rustfmt/issues/4909 +pub enum E { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub enum E2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub enum E3 { + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + +} + +pub struct S { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub struct S2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub struct S3 { + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions +} + +fn foo( + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo2(// Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo3( + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + +) -> usize { + 5 +} + +fn main() { + let v = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v2: Vec = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v3 = vec![ + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + ]; + + // https://github.com/rust-lang/rustfmt/issues/4430 + match a { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + } + + match a { + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + } +} diff --git a/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-true.rs b/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-true.rs new file mode 100644 index 0000000000000..360b838520eda --- /dev/null +++ b/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-true.rs @@ -0,0 +1,130 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +// https://github.com/rust-lang/rustfmt/issues/4909 +pub enum E { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub enum E2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub enum E3 { + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + +} + +pub struct S { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub struct S2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub struct S3 { + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions +} + +fn foo( + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo2(// Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo3( + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + +) -> usize { + 5 +} + +fn main() { + let v = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v2: Vec = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v3 = vec![ + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + ]; + + // https://github.com/rust-lang/rustfmt/issues/4430 + match a { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + } + + match a { + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage through the inclusion pipeline, or according to the descriptions + } +} diff --git a/src/tools/rustfmt/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs new file mode 100644 index 0000000000000..09f68cae42406 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs @@ -0,0 +1,33 @@ +// rustfmt-wrap_comments: true + +fn main() { + { + { + { + { + { + { + { + { + { + { + { + // - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc + + // * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc + + /* - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */ + + /* * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */ + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/src/tools/rustfmt/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs new file mode 100644 index 0000000000000..75f748000f9ba --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs @@ -0,0 +1,19 @@ +// rustfmt-wrap_comments: true + +// +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +// +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +/* + * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ +/* + * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ + +/* + * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ +/* + * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ diff --git a/src/tools/rustfmt/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs new file mode 100644 index 0000000000000..00437f00216ba --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs @@ -0,0 +1,13 @@ +// rustfmt-wrap_comments: true + +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ +/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ + +/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ +/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ diff --git a/src/tools/rustfmt/tests/source/issue_4823.rs b/src/tools/rustfmt/tests/source/issue_4823.rs new file mode 100644 index 0000000000000..a008dd3d83817 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4823.rs @@ -0,0 +1,5 @@ +macro_rules! m { +() => { +type Type; +}; +} diff --git a/src/tools/rustfmt/tests/source/issue_5027.rs b/src/tools/rustfmt/tests/source/issue_5027.rs new file mode 100644 index 0000000000000..67beeb23b7114 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_5027.rs @@ -0,0 +1,7 @@ +// rustfmt-version: Two + +pub type Iter<'a, D> = impl DoubleEndedIterator)>+ ExactSizeIterator+ 'a; + +trait FOo {pub type Iter<'a, D> = impl DoubleEndedIterator)>+ ExactSizeIterator+ 'a;} + +impl Bar {pub type Iter<'a, D> = impl DoubleEndedIterator)>+ ExactSizeIterator+ 'a;} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/issue_5086.rs b/src/tools/rustfmt/tests/source/issue_5086.rs new file mode 100644 index 0000000000000..1644c9d2ccbbb --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_5086.rs @@ -0,0 +1,2 @@ +#[cfg(any())] + type Type : Bound ; \ No newline at end of file diff --git a/src/tools/rustfmt/tests/target/comments-in-lists/format-doc-comments.rs b/src/tools/rustfmt/tests/target/comments-in-lists/format-doc-comments.rs new file mode 100644 index 0000000000000..be31bf0a33198 --- /dev/null +++ b/src/tools/rustfmt/tests/target/comments-in-lists/format-doc-comments.rs @@ -0,0 +1,96 @@ +// rustfmt-format_code_in_doc_comments: true + +// https://github.com/rust-lang/rustfmt/issues/4420 +enum Minimal { + Example, + //[thisisremoved thatsleft + // canbeanything +} + +struct Minimal2 { + Example: usize, + //[thisisremoved thatsleft + // canbeanything +} + +pub enum E { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub enum E2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub struct S { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub struct S2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +fn foo( + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo2(// Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn main() { + let v = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v2: Vec = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + match a { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + } +} diff --git a/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-false.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-false.rs new file mode 100644 index 0000000000000..80aea59d1b520 --- /dev/null +++ b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-false.rs @@ -0,0 +1,85 @@ +// rustfmt-normalize_comments: true + +// https://github.com/rust-lang/rustfmt/issues/4909 +pub enum E { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub enum E2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub struct S { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub struct S2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +fn foo( + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo2(// Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn main() { + let v = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v2: Vec = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + // https://github.com/rust-lang/rustfmt/issues/4430 + match a { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + } +} diff --git a/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-not-normalized.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-not-normalized.rs new file mode 100644 index 0000000000000..52315f470e4b9 --- /dev/null +++ b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-not-normalized.rs @@ -0,0 +1,142 @@ +// rustfmt-wrap_comments: true + +// https://github.com/rust-lang/rustfmt/issues/4909 +pub enum E { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub enum E2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub enum E3 { + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions +} + +pub struct S { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub struct S2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub struct S3 { + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions +} + +fn foo( + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo2(// Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo3( + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn main() { + let v = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v2: Vec = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v3 = vec![ + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + ]; + + // https://github.com/rust-lang/rustfmt/issues/4430 + match a { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + } + + match a { + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + } +} diff --git a/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-true.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-true.rs new file mode 100644 index 0000000000000..e0bfcf0b5007d --- /dev/null +++ b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-true.rs @@ -0,0 +1,143 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +// https://github.com/rust-lang/rustfmt/issues/4909 +pub enum E { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub enum E2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub enum E3 { + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + Variant1, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + Variant2, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions +} + +pub struct S { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +} + +pub struct S2 { + // This can be changed once https://github.com/rust-lang/rustfmt/issues/4854 is fixed +// Expand as needed, numbers should be ascending according to the stage +// through the inclusion pipeline, or according to the descriptions +} + +pub struct S3 { + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + some_field: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + last_field: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions +} + +fn foo( + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo2(// Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn foo3( + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + a: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions + b: usize, + // Expand as needed, numbers should be ascending according to the stage through the inclusion + // pipeline, or according to the descriptions +) -> usize { + 5 +} + +fn main() { + let v = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v2: Vec = vec![ + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + ]; + + let v3 = vec![ + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + 1, + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + 2, + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + ]; + + // https://github.com/rust-lang/rustfmt/issues/4430 + match a { + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage + // through the inclusion pipeline, or according to the descriptions + } + + match a { + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + b => c, + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + d => e, + // Expand as needed, numbers should be ascending according to the stage through the + // inclusion pipeline, or according to the descriptions + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs new file mode 100644 index 0000000000000..f4801de018481 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs @@ -0,0 +1,33 @@ +// rustfmt-wrap_comments: false + +fn main() { + { + { + { + { + { + { + { + { + { + { + { + // - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc + + // * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc + + /* - aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */ + + /* * aaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa aaaaaaaaa bbbbbbbbbb bbbbbbbbb bbbbbbbbb ccc cccccccccc ccccccc cccccccc */ + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs new file mode 100644 index 0000000000000..b289c9f859e0e --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs @@ -0,0 +1,49 @@ +// rustfmt-wrap_comments: true + +fn main() { + { + { + { + { + { + { + { + { + { + { + { + // - aaaa aaaaaaaaa aaaaaaaaa + // aaaaaaaaa aaaaaaaaa + // bbbbbbbbbb bbbbbbbbb + // bbbbbbbbb ccc cccccccccc + // ccccccc cccccccc + + // * aaaa aaaaaaaaa aaaaaaaaa + // aaaaaaaaa aaaaaaaaa + // bbbbbbbbbb bbbbbbbbb + // bbbbbbbbb ccc cccccccccc + // ccccccc cccccccc + + /* - aaaa aaaaaaaaa aaaaaaaaa + * aaaaaaaaa aaaaaaaaa + * bbbbbbbbbb bbbbbbbbb + * bbbbbbbbb ccc cccccccccc + * ccccccc cccccccc */ + + /* * aaaa aaaaaaaaa aaaaaaaaa + * aaaaaaaaa aaaaaaaaa + * bbbbbbbbbb bbbbbbbbb + * bbbbbbbbb ccc cccccccccc + * ccccccc cccccccc */ + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs new file mode 100644 index 0000000000000..60beed1b04828 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs @@ -0,0 +1,17 @@ +// rustfmt-wrap_comments: false + +// - some itemized block 1 +// - some itemized block 2 + +// * some itemized block 3 +// * some itemized block 4 + +/* + * - some itemized block 5 + * - some itemized block 6 + */ + +/* + * * some itemized block 7 + * * some itemized block 8 + */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs new file mode 100644 index 0000000000000..84fba4b7c1986 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs @@ -0,0 +1,17 @@ +// rustfmt-wrap_comments: true + +// - some itemized block 1 +// - some itemized block 2 + +// * some itemized block 3 +// * some itemized block 4 + +/* + * - some itemized block 5 + * - some itemized block 6 + */ + +/* + * * some itemized block 7 + * * some itemized block 8 + */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs new file mode 100644 index 0000000000000..d1bf44f6c7413 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs @@ -0,0 +1,37 @@ +// rustfmt-wrap_comments: false + +// Some text +// - some itemized block 1 +// - some itemized block 2 +// Some more text +// - some itemized block 3 +// - some itemized block 4 +// Even more text + +// Some text +// * some itemized block 5 +// * some itemized block 6 +// Some more text +// * some itemized block 7 +// * some itemized block 8 +// Even more text + +/* + * Some text + * - some itemized block 9 + * - some itemized block 10 + * Some more text + * - some itemized block 11 + * - some itemized block 12 + * Even more text + */ + +/* + * Some text + * * some itemized block 13 + * * some itemized block 14 + * Some more text + * * some itemized block 15 + * * some itemized block 16 + * Even more text + */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs new file mode 100644 index 0000000000000..f767491f902d4 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs @@ -0,0 +1,37 @@ +// rustfmt-wrap_comments: true + +// Some text +// - some itemized block 1 +// - some itemized block 2 +// Some more text +// - some itemized block 3 +// - some itemized block 4 +// Even more text + +// Some text +// * some itemized block 5 +// * some itemized block 6 +// Some more text +// * some itemized block 7 +// * some itemized block 8 +// Even more text + +/* + * Some text + * - some itemized block 9 + * - some itemized block 10 + * Some more text + * - some itemized block 11 + * - some itemized block 12 + * Even more text + */ + +/* + * Some text + * * some itemized block 13 + * * some itemized block 14 + * Some more text + * * some itemized block 15 + * * some itemized block 16 + * Even more text + */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs new file mode 100644 index 0000000000000..2cd85c787f974 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs @@ -0,0 +1,9 @@ +// rustfmt-wrap_comments: false + +// - some itemized block 1 + +// * some itemized block 2 + +/* - some itemized block 3 */ + +/* * some itemized block 4 */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs new file mode 100644 index 0000000000000..e9f343d75d5eb --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs @@ -0,0 +1,9 @@ +// rustfmt-wrap_comments: true + +// - some itemized block 1 + +// * some itemized block 2 + +/* - some itemized block 3 */ + +/* * some itemized block 4 */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs new file mode 100644 index 0000000000000..97bb7733d189f --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs @@ -0,0 +1,19 @@ +// rustfmt-wrap_comments: false + +// +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +// +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +/* + * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ +/* + * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ + +/* + * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ +/* + * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ diff --git a/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs new file mode 100644 index 0000000000000..c8af8383e058a --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs @@ -0,0 +1,27 @@ +// rustfmt-wrap_comments: true + +// +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod +// tempor incididunt ut labore et dolore magna aliqua. +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod +// tempor incididunt ut labore et dolore magna aliqua. + +// +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod +// tempor incididunt ut labore et dolore magna aliqua. +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod +// tempor incididunt ut labore et dolore magna aliqua. + +/* + * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + * tempor incididunt ut labore et dolore magna aliqua. */ +/* + * - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + * tempor incididunt ut labore et dolore magna aliqua. */ + +/* + * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + * tempor incididunt ut labore et dolore magna aliqua. */ +/* + * * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + * tempor incididunt ut labore et dolore magna aliqua. */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs new file mode 100644 index 0000000000000..75cc42c0e66bb --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs @@ -0,0 +1,17 @@ +// rustfmt-wrap_comments: false + +// +// - some itemized block 1 +// - some itemized block 2 + +// +// * some itemized block 3 +// * some itemized block 4 + +/* + * - some itemized block 5 + * - some itemized block 6 */ + +/* + * * some itemized block 7 + * * some itemized block 8 */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs new file mode 100644 index 0000000000000..ef2c8f90cd309 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs @@ -0,0 +1,17 @@ +// rustfmt-wrap_comments: true + +// +// - some itemized block 1 +// - some itemized block 2 + +// +// * some itemized block 3 +// * some itemized block 4 + +/* + * - some itemized block 5 + * - some itemized block 6 */ + +/* + * * some itemized block 7 + * * some itemized block 8 */ diff --git a/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs new file mode 100644 index 0000000000000..c826cc5d4da6e --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs @@ -0,0 +1,13 @@ +// rustfmt-wrap_comments: false + +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ +/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ + +/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ +/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.*/ diff --git a/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs new file mode 100644 index 0000000000000..7f764dbd8a22b --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs @@ -0,0 +1,21 @@ +// rustfmt-wrap_comments: true + +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod +// tempor incididunt ut labore et dolore magna aliqua. +// - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod +// tempor incididunt ut labore et dolore magna aliqua. + +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod +// tempor incididunt ut labore et dolore magna aliqua. +// * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod +// tempor incididunt ut labore et dolore magna aliqua. + +/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + * tempor incididunt ut labore et dolore magna aliqua. */ +/* - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + * tempor incididunt ut labore et dolore magna aliqua. */ + +/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + * tempor incididunt ut labore et dolore magna aliqua. */ +/* * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + * tempor incididunt ut labore et dolore magna aliqua. */ diff --git a/src/tools/rustfmt/tests/target/issue-5095.rs b/src/tools/rustfmt/tests/target/issue-5095.rs new file mode 100644 index 0000000000000..6981a65808c90 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5095.rs @@ -0,0 +1,27 @@ +// rustfmt-wrap_comments: true + +pub mod a_long_name { + pub mod b_long_name { + pub mod c_long_name { + pub mod d_long_name { + pub mod e_long_name { + pub struct Bananas; + impl Bananas { + pub fn fantastic() {} + } + + pub mod f_long_name { + pub struct Apples; + } + } + } + } + } +} + +/// Check out [my other struct] ([`Bananas`]) and [the method it has]. +/// +/// [my other struct]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::f_long_name::Apples +/// [`Bananas`]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::Bananas::fantastic() +/// [the method it has]: a_long_name::b_long_name::c_long_name::d_long_name::e_long_name::Bananas::fantastic() +pub struct A; diff --git a/src/tools/rustfmt/tests/target/issue_4823.rs b/src/tools/rustfmt/tests/target/issue_4823.rs new file mode 100644 index 0000000000000..de17467c0efad --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4823.rs @@ -0,0 +1,5 @@ +macro_rules! m { + () => { + type Type; + }; +} diff --git a/src/tools/rustfmt/tests/target/issue_5027.rs b/src/tools/rustfmt/tests/target/issue_5027.rs new file mode 100644 index 0000000000000..26d771720b6c5 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_5027.rs @@ -0,0 +1,17 @@ +// rustfmt-version: Two + +pub type Iter<'a, D> = impl DoubleEndedIterator)> + + ExactSizeIterator + + 'a; + +trait FOo { + pub type Iter<'a, D> = impl DoubleEndedIterator)> + + ExactSizeIterator + + 'a; +} + +impl Bar { + type Iter<'a, D> = impl DoubleEndedIterator)> + + ExactSizeIterator + + 'a; +} diff --git a/src/tools/rustfmt/tests/target/issue_5086.rs b/src/tools/rustfmt/tests/target/issue_5086.rs new file mode 100644 index 0000000000000..7a0be06f7917a --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_5086.rs @@ -0,0 +1,2 @@ +#[cfg(any())] +type Type: Bound;