about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_abi/src/lib.rs2
-rw-r--r--compiler/rustc_ast_ir/src/lib.rs4
-rw-r--r--compiler/rustc_codegen_gcc/target_specs/m68k-unknown-linux-gnu.json2
-rw-r--r--compiler/rustc_parse_format/src/lib.rs4
-rw-r--r--compiler/rustc_target/src/spec/json.rs25
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2
-rw-r--r--compiler/rustc_target/src/tests.rs2
-rw-r--r--library/alloc/src/fmt.rs2
-rw-r--r--library/compiler-builtins/etc/thumbv7em-none-eabi-renamed.json2
-rw-r--r--library/core/src/hint.rs37
-rw-r--r--library/core/src/ptr/mod.rs5
-rw-r--r--library/coretests/tests/hint.rs36
-rwxr-xr-xsrc/ci/docker/scripts/rfl-build.sh3
-rw-r--r--src/tools/compiletest/src/common.rs8
-rw-r--r--src/tools/miri/tests/x86_64-unknown-kernel.json2
-rw-r--r--tests/run-make/rust-lld-custom-target/custom-target.json2
-rw-r--r--tests/run-make/rustdoc-target-spec-json-path/target.json2
-rw-r--r--tests/run-make/target-specs/endianness-mismatch.json2
-rw-r--r--tests/run-make/target-specs/mismatching-data-layout.json2
-rw-r--r--tests/run-make/target-specs/my-awesome-platform.json2
-rw-r--r--tests/run-make/target-specs/my-incomplete-platform.json2
-rw-r--r--tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json2
-rw-r--r--tests/run-make/target-specs/require-explicit-cpu.json2
-rw-r--r--tests/ui/check-cfg/my-awesome-platform.json2
-rw-r--r--tests/ui/codegen/mismatched-data-layout.json2
-rw-r--r--tests/ui/fmt/format-string-wrong-order.rs8
-rw-r--r--tests/ui/fmt/format-string-wrong-order.stderr14
27 files changed, 123 insertions, 55 deletions
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 14e256b8045..a1a0de5aaf8 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -315,7 +315,7 @@ pub enum TargetDataLayoutErrors<'a> {
     MissingAlignment { cause: &'a str },
     InvalidAlignment { cause: &'a str, err: AlignFromBytesError },
     InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
-    InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
+    InconsistentTargetPointerWidth { pointer_size: u64, target: u16 },
     InvalidBitsSize { err: String },
     UnknownPointerSpecification { err: String },
 }
diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs
index 8f2a37c1210..44837b1b494 100644
--- a/compiler/rustc_ast_ir/src/lib.rs
+++ b/compiler/rustc_ast_ir/src/lib.rs
@@ -69,7 +69,7 @@ impl IntTy {
         })
     }
 
-    pub fn normalize(&self, target_width: u32) -> Self {
+    pub fn normalize(&self, target_width: u16) -> Self {
         match self {
             IntTy::Isize => match target_width {
                 16 => IntTy::I16,
@@ -148,7 +148,7 @@ impl UintTy {
         })
     }
 
-    pub fn normalize(&self, target_width: u32) -> Self {
+    pub fn normalize(&self, target_width: u16) -> Self {
         match self {
             UintTy::Usize => match target_width {
                 16 => UintTy::U16,
diff --git a/compiler/rustc_codegen_gcc/target_specs/m68k-unknown-linux-gnu.json b/compiler/rustc_codegen_gcc/target_specs/m68k-unknown-linux-gnu.json
index 95ea06106fb..b13b640a7c7 100644
--- a/compiler/rustc_codegen_gcc/target_specs/m68k-unknown-linux-gnu.json
+++ b/compiler/rustc_codegen_gcc/target_specs/m68k-unknown-linux-gnu.json
@@ -22,5 +22,5 @@
     "unix"
   ],
   "target-mcount": "_mcount",
-  "target-pointer-width": "32"
+  "target-pointer-width": 32
 }
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 8e4da7923fc..5cda0b813d2 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -858,7 +858,9 @@ impl<'input> Parser<'input> {
             self.errors.insert(
                 0,
                 ParseError {
-                    description: "expected format parameter to occur after `:`".to_owned(),
+                    description:
+                        "expected alignment specifier after `:` in format string; example: `{:>?}`"
+                            .to_owned(),
                     note: None,
                     label: format!("expected `{}` to occur after `:`", alignment),
                     span: range,
diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs
index f56a65d9c0c..e9ae5734d5b 100644
--- a/compiler/rustc_target/src/spec/json.rs
+++ b/compiler/rustc_target/src/spec/json.rs
@@ -25,10 +25,7 @@ impl Target {
         let mut base = Target {
             llvm_target: json.llvm_target,
             metadata: Default::default(),
-            pointer_width: json
-                .target_pointer_width
-                .parse()
-                .map_err(|err| format!("invalid target-pointer-width: {err}"))?,
+            pointer_width: json.target_pointer_width,
             data_layout: json.data_layout,
             arch: json.arch,
             options: Default::default(),
@@ -245,19 +242,17 @@ impl ToJson for Target {
         target.update_to_cli();
 
         macro_rules! target_val {
-            ($attr:ident) => {{
-                let name = (stringify!($attr)).replace("_", "-");
-                d.insert(name, target.$attr.to_json());
+            ($attr:ident) => {
+                target_val!($attr, (stringify!($attr)).replace("_", "-"))
+            };
+            ($attr:ident, $json_name:expr) => {{
+                let name = $json_name;
+                d.insert(name.into(), target.$attr.to_json());
             }};
         }
 
         macro_rules! target_option_val {
-            ($attr:ident) => {{
-                let name = (stringify!($attr)).replace("_", "-");
-                if default.$attr != target.$attr {
-                    d.insert(name, target.$attr.to_json());
-                }
-            }};
+            ($attr:ident) => {{ target_option_val!($attr, (stringify!($attr)).replace("_", "-")) }};
             ($attr:ident, $json_name:expr) => {{
                 let name = $json_name;
                 if default.$attr != target.$attr {
@@ -290,7 +285,7 @@ impl ToJson for Target {
 
         target_val!(llvm_target);
         target_val!(metadata);
-        d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json());
+        target_val!(pointer_width, "target-pointer-width");
         target_val!(arch);
         target_val!(data_layout);
 
@@ -463,7 +458,7 @@ struct TargetSpecJsonMetadata {
 #[serde(deny_unknown_fields)]
 struct TargetSpecJson {
     llvm_target: StaticCow<str>,
-    target_pointer_width: String,
+    target_pointer_width: u16,
     data_layout: StaticCow<str>,
     arch: StaticCow<str>,
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index e97a9b9c776..4d9f06c568b 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2331,7 +2331,7 @@ pub struct Target {
     /// Used for generating target documentation.
     pub metadata: TargetMetadata,
     /// Number of bits in a pointer. Influences the `target_pointer_width` `cfg` variable.
-    pub pointer_width: u32,
+    pub pointer_width: u16,
     /// Architecture to use for ABI considerations. Valid options include: "x86",
     /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
     pub arch: StaticCow<str>,
diff --git a/compiler/rustc_target/src/tests.rs b/compiler/rustc_target/src/tests.rs
index ee847a84007..a2692ea6be5 100644
--- a/compiler/rustc_target/src/tests.rs
+++ b/compiler/rustc_target/src/tests.rs
@@ -7,7 +7,7 @@ fn report_unused_fields() {
         "arch": "powerpc64",
         "data-layout": "e-m:e-i64:64-n32:64",
         "llvm-target": "powerpc64le-elf",
-        "target-pointer-width": "64",
+        "target-pointer-width": 64,
         "code-mode": "foo"
     }
     "#;
diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs
index d0ba9c39886..82eaf7d8724 100644
--- a/library/alloc/src/fmt.rs
+++ b/library/alloc/src/fmt.rs
@@ -354,7 +354,7 @@
 //! sign := '+' | '-'
 //! width := count
 //! precision := count | '*'
-//! type := '?' | 'x?' | 'X?' | identifier
+//! type := '?' | 'x?' | 'X?' | 'o' | 'x' | 'X' | 'p' | 'b' | 'e' | 'E'
 //! count := parameter | integer
 //! parameter := argument '$'
 //! ```
diff --git a/library/compiler-builtins/etc/thumbv7em-none-eabi-renamed.json b/library/compiler-builtins/etc/thumbv7em-none-eabi-renamed.json
index 81273d44e49..6369bbe2547 100644
--- a/library/compiler-builtins/etc/thumbv7em-none-eabi-renamed.json
+++ b/library/compiler-builtins/etc/thumbv7em-none-eabi-renamed.json
@@ -19,5 +19,5 @@
   },
   "panic-strategy": "abort",
   "relocation-model": "static",
-  "target-pointer-width": "32"
+  "target-pointer-width": 32
 }
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 535c5a8e77b..23cfdf5bfde 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -776,12 +776,45 @@ pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
     // Change this to use ManuallyDrop instead.
     let mut true_val = MaybeUninit::new(true_val);
     let mut false_val = MaybeUninit::new(false_val);
+
+    struct DropOnPanic<T> {
+        // Invariant: valid pointer and points to an initialized value that is not further used,
+        // i.e. it can be dropped by this guard.
+        inner: *mut T,
+    }
+
+    impl<T> Drop for DropOnPanic<T> {
+        fn drop(&mut self) {
+            // SAFETY: Must be guaranteed on construction of local type `DropOnPanic`.
+            unsafe { self.inner.drop_in_place() }
+        }
+    }
+
+    let true_ptr = true_val.as_mut_ptr();
+    let false_ptr = false_val.as_mut_ptr();
+
     // SAFETY: The value that is not selected is dropped, and the selected one
     // is returned. This is necessary because the intrinsic doesn't drop the
     // value that is  not selected.
     unsafe {
-        crate::intrinsics::select_unpredictable(!condition, &mut true_val, &mut false_val)
-            .assume_init_drop();
+        // Extract the selected value first, ensure it is dropped as well if dropping the unselected
+        // value panics. We construct a temporary by-pointer guard around the selected value while
+        // dropping the unselected value. Arguments overlap here, so we can not use mutable
+        // reference for these arguments.
+        let guard = crate::intrinsics::select_unpredictable(condition, true_ptr, false_ptr);
+        let drop = crate::intrinsics::select_unpredictable(condition, false_ptr, true_ptr);
+
+        // SAFETY: both pointers are well-aligned and point to initialized values inside a
+        // `MaybeUninit` each. In both possible values for `condition` the pointer `guard` and
+        // `drop` do not alias (even though the two argument pairs we have selected from did alias
+        // each other).
+        let guard = DropOnPanic { inner: guard };
+        drop.drop_in_place();
+        crate::mem::forget(guard);
+
+        // Note that it is important to use the values here. Reading from the pointer we got makes
+        // LLVM forget the !unpredictable annotation sometimes (in tests, integer sized values in
+        // particular seemed to confuse it, also observed in llvm/llvm-project #82340).
         crate::intrinsics::select_unpredictable(condition, true_val, false_val).assume_init()
     }
 }
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 6fc85a83e17..6b94088cb56 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -2166,10 +2166,9 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
     }
 }
 
-/// Align pointer `p`.
+/// Calculate an element-offset that increases a pointer's alignment.
 ///
-/// Calculate offset (in terms of elements of `size_of::<T>()` stride) that has to be applied
-/// to pointer `p` so that pointer `p` would get aligned to `a`.
+/// Calculate an element-offset (not byte-offset) that when added to a given pointer `p`, increases `p`'s alignment to at least the given alignment `a`.
 ///
 /// # Safety
 /// `a` must be a power of two.
diff --git a/library/coretests/tests/hint.rs b/library/coretests/tests/hint.rs
index 032bbc1dcc8..24de27b24b8 100644
--- a/library/coretests/tests/hint.rs
+++ b/library/coretests/tests/hint.rs
@@ -21,3 +21,39 @@ fn select_unpredictable_drop() {
     assert!(a_dropped.get());
     assert!(b_dropped.get());
 }
+
+#[test]
+#[should_panic = "message canary"]
+fn select_unpredictable_drop_on_panic() {
+    use core::cell::Cell;
+
+    struct X<'a> {
+        cell: &'a Cell<u16>,
+        expect: u16,
+        write: u16,
+    }
+
+    impl Drop for X<'_> {
+        fn drop(&mut self) {
+            let value = self.cell.get();
+            self.cell.set(self.write);
+            assert_eq!(value, self.expect, "message canary");
+        }
+    }
+
+    let cell = Cell::new(0);
+
+    // Trigger a double-panic if the selected cell was not dropped during panic.
+    let _armed = X { cell: &cell, expect: 0xdead, write: 0 };
+    let selected = X { cell: &cell, write: 0xdead, expect: 1 };
+    let unselected = X { cell: &cell, write: 1, expect: 0xff };
+
+    // The correct drop order is:
+    //
+    // 1. `unselected` drops, writes 1, and panics as 0 != 0xff
+    // 2. `selected` drops during unwind, writes 0xdead and does not panic as 1 == 1
+    // 3. `armed` drops during unwind, writes 0 and does not panic as 0xdead == 0xdead
+    //
+    // If `selected` is not dropped, `armed` panics as 1 != 0xdead
+    let _unreachable = core::hint::select_unpredictable(true, selected, unselected);
+}
diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index 8acc5040a2f..70ff5d0d2c7 100755
--- a/src/ci/docker/scripts/rfl-build.sh
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -2,7 +2,8 @@
 
 set -euo pipefail
 
-LINUX_VERSION=v6.16-rc1
+# https://github.com/rust-lang/rust/pull/144443
+LINUX_VERSION=7770d51bce622b13195b2d3c85407282fc9c27e5
 
 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt
 ../x.py build --stage 2 library rustdoc clippy rustfmt
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index b72c0b7ed20..89b1b4f84b6 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -6,7 +6,6 @@ use std::sync::OnceLock;
 use build_helper::git::GitConfig;
 use camino::{Utf8Path, Utf8PathBuf};
 use semver::Version;
-use serde::de::{Deserialize, Deserializer, Error as _};
 
 use crate::executor::ColorConfig;
 use crate::fatal;
@@ -1072,7 +1071,7 @@ pub struct TargetCfg {
     pub(crate) abi: String,
     #[serde(rename = "target-family", default)]
     pub(crate) families: Vec<String>,
-    #[serde(rename = "target-pointer-width", deserialize_with = "serde_parse_u32")]
+    #[serde(rename = "target-pointer-width")]
     pub(crate) pointer_width: u32,
     #[serde(rename = "target-endian", default)]
     endian: Endian,
@@ -1182,11 +1181,6 @@ fn query_rustc_output(config: &Config, args: &[&str], envs: HashMap<String, Stri
     String::from_utf8(output.stdout).unwrap()
 }
 
-fn serde_parse_u32<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u32, D::Error> {
-    let string = String::deserialize(deserializer)?;
-    string.parse().map_err(D::Error::custom)
-}
-
 #[derive(Debug, Clone)]
 pub struct TestPaths {
     pub file: Utf8PathBuf,         // e.g., compile-test/foo/bar/baz.rs
diff --git a/src/tools/miri/tests/x86_64-unknown-kernel.json b/src/tools/miri/tests/x86_64-unknown-kernel.json
index a5eaceb4f68..0f8032c39d5 100644
--- a/src/tools/miri/tests/x86_64-unknown-kernel.json
+++ b/src/tools/miri/tests/x86_64-unknown-kernel.json
@@ -1,7 +1,7 @@
 {
   "llvm-target": "x86_64-unknown-none",
   "target-endian": "little",
-  "target-pointer-width": "64",
+  "target-pointer-width": 64,
   "target-c-int-width": 32,
   "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
   "arch": "x86_64",
diff --git a/tests/run-make/rust-lld-custom-target/custom-target.json b/tests/run-make/rust-lld-custom-target/custom-target.json
index e2c64cbdb43..28c3dc6f387 100644
--- a/tests/run-make/rust-lld-custom-target/custom-target.json
+++ b/tests/run-make/rust-lld-custom-target/custom-target.json
@@ -53,5 +53,5 @@
   "target-family": [
     "unix"
   ],
-  "target-pointer-width": "64"
+  "target-pointer-width": 64
 }
diff --git a/tests/run-make/rustdoc-target-spec-json-path/target.json b/tests/run-make/rustdoc-target-spec-json-path/target.json
index d7e4cac57ae..6d8fe8528c8 100644
--- a/tests/run-make/rustdoc-target-spec-json-path/target.json
+++ b/tests/run-make/rustdoc-target-spec-json-path/target.json
@@ -33,5 +33,5 @@
     "thread"
   ],
   "target-family": "unix",
-  "target-pointer-width": "64"
+  "target-pointer-width": 64
 }
diff --git a/tests/run-make/target-specs/endianness-mismatch.json b/tests/run-make/target-specs/endianness-mismatch.json
index cc03becc59a..d73ea1cbcfe 100644
--- a/tests/run-make/target-specs/endianness-mismatch.json
+++ b/tests/run-make/target-specs/endianness-mismatch.json
@@ -4,7 +4,7 @@
     "linker-flavor": "gcc",
     "llvm-target": "x86_64-unknown-linux-gnu",
     "target-endian": "big",
-    "target-pointer-width": "64",
+    "target-pointer-width": 64,
     "arch": "x86_64",
     "os": "linux"
 }
diff --git a/tests/run-make/target-specs/mismatching-data-layout.json b/tests/run-make/target-specs/mismatching-data-layout.json
index d12caaad14a..e948d4d2f99 100644
--- a/tests/run-make/target-specs/mismatching-data-layout.json
+++ b/tests/run-make/target-specs/mismatching-data-layout.json
@@ -2,5 +2,5 @@
   "arch": "x86_64",
   "data-layout": "e-m:e-i64:16:32:64",
   "llvm-target": "x86_64-unknown-unknown-gnu",
-  "target-pointer-width": "64"
+  "target-pointer-width": 64
 }
diff --git a/tests/run-make/target-specs/my-awesome-platform.json b/tests/run-make/target-specs/my-awesome-platform.json
index d41038b84a8..732a6bacd15 100644
--- a/tests/run-make/target-specs/my-awesome-platform.json
+++ b/tests/run-make/target-specs/my-awesome-platform.json
@@ -3,7 +3,7 @@
     "linker-flavor": "gcc",
     "llvm-target": "i686-unknown-linux-gnu",
     "target-endian": "little",
-    "target-pointer-width": "32",
+    "target-pointer-width": 32,
     "arch": "x86",
     "os": "linux"
 }
diff --git a/tests/run-make/target-specs/my-incomplete-platform.json b/tests/run-make/target-specs/my-incomplete-platform.json
index 8bdc4108f49..68dbfc62d1c 100644
--- a/tests/run-make/target-specs/my-incomplete-platform.json
+++ b/tests/run-make/target-specs/my-incomplete-platform.json
@@ -2,7 +2,7 @@
     "data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
     "linker-flavor": "gcc",
     "target-endian": "little",
-    "target-pointer-width": "32",
+    "target-pointer-width": 32,
     "arch": "x86",
     "os": "foo"
 }
diff --git a/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json b/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json
index 27833f1abdd..008ea548383 100644
--- a/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json
+++ b/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json
@@ -4,7 +4,7 @@
     "linker-flavor": "gcc",
     "llvm-target": "x86_64-unknown-linux-gnu",
     "target-endian": "little",
-    "target-pointer-width": "64",
+    "target-pointer-width": 64,
     "arch": "x86_64",
     "os": "linux"
 }
diff --git a/tests/run-make/target-specs/require-explicit-cpu.json b/tests/run-make/target-specs/require-explicit-cpu.json
index 9744bca168e..4f23b644d8c 100644
--- a/tests/run-make/target-specs/require-explicit-cpu.json
+++ b/tests/run-make/target-specs/require-explicit-cpu.json
@@ -3,7 +3,7 @@
     "linker-flavor": "gcc",
     "llvm-target": "i686-unknown-linux-gnu",
     "target-endian": "little",
-    "target-pointer-width": "32",
+    "target-pointer-width": 32,
     "arch": "x86",
     "os": "linux",
     "need-explicit-cpu": true
diff --git a/tests/ui/check-cfg/my-awesome-platform.json b/tests/ui/check-cfg/my-awesome-platform.json
index 4c16d06c7b7..3a1f6b1a54c 100644
--- a/tests/ui/check-cfg/my-awesome-platform.json
+++ b/tests/ui/check-cfg/my-awesome-platform.json
@@ -3,7 +3,7 @@
     "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
     "arch": "x86_64",
     "target-endian": "little",
-    "target-pointer-width": "64",
+    "target-pointer-width": 64,
     "os": "ericos",
     "linker-flavor": "ld.lld",
     "linker": "rust-lld",
diff --git a/tests/ui/codegen/mismatched-data-layout.json b/tests/ui/codegen/mismatched-data-layout.json
index f8c510c1863..a1b222010ab 100644
--- a/tests/ui/codegen/mismatched-data-layout.json
+++ b/tests/ui/codegen/mismatched-data-layout.json
@@ -3,7 +3,7 @@
     "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
     "arch": "x86_64",
     "target-endian": "little",
-    "target-pointer-width": "64",
+    "target-pointer-width": 64,
     "os": "none",
     "linker-flavor": "ld.lld",
     "linker": "rust-lld",
diff --git a/tests/ui/fmt/format-string-wrong-order.rs b/tests/ui/fmt/format-string-wrong-order.rs
index 891279b97e4..4d4e04ecd04 100644
--- a/tests/ui/fmt/format-string-wrong-order.rs
+++ b/tests/ui/fmt/format-string-wrong-order.rs
@@ -13,9 +13,11 @@ fn main() {
     format!("{?:#?}", bar);
     //~^ ERROR invalid format string: expected format parameter to occur after `:`
     format!("Hello {<5:}!", "x");
-    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    //~^ ERROR invalid format string: expected alignment specifier after `:` in format string; example: `{:>?}`
     format!("Hello {^5:}!", "x");
-    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    //~^ ERROR invalid format string: expected alignment specifier after `:` in format string; example: `{:>?}`
     format!("Hello {>5:}!", "x");
-    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    //~^ ERROR invalid format string: expected alignment specifier after `:` in format string; example: `{:>?}`
+    println!("{0:#X>18}", 12345);
+    //~^ ERROR invalid format string: expected alignment specifier after `:` in format string; example: `{:>?}`
 }
diff --git a/tests/ui/fmt/format-string-wrong-order.stderr b/tests/ui/fmt/format-string-wrong-order.stderr
index 7f017511761..441ae6d2e50 100644
--- a/tests/ui/fmt/format-string-wrong-order.stderr
+++ b/tests/ui/fmt/format-string-wrong-order.stderr
@@ -50,23 +50,29 @@ LL |     format!("{?:#?}", bar);
    |
    = note: `?` comes after `:`, try `:?` instead
 
-error: invalid format string: expected format parameter to occur after `:`
+error: invalid format string: expected alignment specifier after `:` in format string; example: `{:>?}`
   --> $DIR/format-string-wrong-order.rs:15:21
    |
 LL |     format!("Hello {<5:}!", "x");
    |                     ^ expected `<` to occur after `:` in format string
 
-error: invalid format string: expected format parameter to occur after `:`
+error: invalid format string: expected alignment specifier after `:` in format string; example: `{:>?}`
   --> $DIR/format-string-wrong-order.rs:17:21
    |
 LL |     format!("Hello {^5:}!", "x");
    |                     ^ expected `^` to occur after `:` in format string
 
-error: invalid format string: expected format parameter to occur after `:`
+error: invalid format string: expected alignment specifier after `:` in format string; example: `{:>?}`
   --> $DIR/format-string-wrong-order.rs:19:21
    |
 LL |     format!("Hello {>5:}!", "x");
    |                     ^ expected `>` to occur after `:` in format string
 
-error: aborting due to 9 previous errors
+error: invalid format string: expected alignment specifier after `:` in format string; example: `{:>?}`
+  --> $DIR/format-string-wrong-order.rs:21:20
+   |
+LL |     println!("{0:#X>18}", 12345);
+   |                    ^ expected `>` to occur after `:` in format string
+
+error: aborting due to 10 previous errors