authorbors <bors@rust-lang.org> 2025-11-17 07:49:48 UTC
committerbors <bors@rust-lang.org> 2025-11-17 07:49:48 UTC
logcc328c12382f05d8ddf6ffc8139deb7985270ad8
tree2ce5805c0a9557d25a55886fdad3c605cf7a330c
parent89fe96197d232f86d733566df31c6dcebd1750da
parent06304ef1007c69d8ed4dd2684c5377ad2fcd5a4f

Auto merge of #149013 - Zalathar:rollup-io1ddhc, r=Zalathar

Rollup of 11 pull requests Successful merges: - rust-lang/rust#148505 (add larger test for `proc_macro` `FromStr` implementations) - rust-lang/rust#148752 (Constify `ManuallyDrop::take`) - rust-lang/rust#148757 (Constify `mem::take`) - rust-lang/rust#148855 (Error if an autodiff user does not set lto=fat) - rust-lang/rust#148912 (add note to `lines` docs about empty str behavior) - rust-lang/rust#148958 (Run codegen tests on a 32-bit target in PR CI) - rust-lang/rust#148994 (Abi compatibility test cleanup) - rust-lang/rust#148999 (Tweak Motor OS linker preset, fix `remote-test-server` for Motor OS) - rust-lang/rust#149004 (compiletest: Avoid race condition in file deletion) - rust-lang/rust#149008 (triagebot: remove jsha from notifications for rustdoc HTML) - rust-lang/rust#149010 (compiletest: Remove the "wasm32-bare" alias for `wasm32-unknown-unknown`) r? `@ghost` `@rustbot` modify labels: rollup

29 files changed, 540 insertions(+), 73 deletions(-)

compiler/rustc_codegen_llvm/messages.ftl+1
......@@ -1,4 +1,5 @@
11codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable
2codegen_llvm_autodiff_without_lto = using the autodiff feature requires setting `lto="fat"` in your Cargo.toml
23
34codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
45
compiler/rustc_codegen_llvm/src/errors.rs+4
......@@ -32,6 +32,10 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
3232 }
3333}
3434
35#[derive(Diagnostic)]
36#[diag(codegen_llvm_autodiff_without_lto)]
37pub(crate) struct AutoDiffWithoutLto;
38
3539#[derive(Diagnostic)]
3640#[diag(codegen_llvm_autodiff_without_enable)]
3741pub(crate) struct AutoDiffWithoutEnable;
compiler/rustc_codegen_llvm/src/intrinsic.rs+4-1
......@@ -25,7 +25,7 @@ use crate::abi::FnAbiLlvmExt;
2525use crate::builder::Builder;
2626use crate::builder::autodiff::{adjust_activity_to_abi, generate_enzyme_call};
2727use crate::context::CodegenCx;
28use crate::errors::AutoDiffWithoutEnable;
28use crate::errors::{AutoDiffWithoutEnable, AutoDiffWithoutLto};
2929use crate::llvm::{self, Metadata, Type, Value};
3030use crate::type_of::LayoutLlvmExt;
3131use crate::va_arg::emit_va_arg;
......@@ -1136,6 +1136,9 @@ fn codegen_autodiff<'ll, 'tcx>(
11361136 if !tcx.sess.opts.unstable_opts.autodiff.contains(&rustc_session::config::AutoDiff::Enable) {
11371137 let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutEnable);
11381138 }
1139 if tcx.sess.lto() != rustc_session::config::Lto::Fat {
1140 let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutLto);
1141 }
11391142
11401143 let fn_args = instance.args;
11411144 let callee_ty = instance.ty(tcx, bx.typing_env());
compiler/rustc_session/src/session.rs-8
......@@ -594,14 +594,6 @@ impl Session {
594594
595595 /// Calculates the flavor of LTO to use for this compilation.
596596 pub fn lto(&self) -> config::Lto {
597 // Autodiff currently requires fat-lto to have access to the llvm-ir of all (indirectly) used functions and types.
598 // fat-lto is the easiest solution to this requirement, but quite expensive.
599 // FIXME(autodiff): Make autodiff also work with embed-bc instead of fat-lto.
600 // Don't apply fat-lto to proc-macro crates as they cannot use fat-lto without -Zdylib-lto
601 if self.opts.autodiff_enabled() && !self.opts.crate_types.contains(&CrateType::ProcMacro) {
602 return config::Lto::Fat;
603 }
604
605597 // If our target has codegen requirements ignore the command line
606598 if self.target.requires_lto {
607599 return config::Lto::Fat;
compiler/rustc_target/src/spec/base/motor.rs+3-11
......@@ -4,16 +4,8 @@ use crate::spec::{
44
55pub(crate) fn opts() -> TargetOptions {
66 let pre_link_args = TargetOptions::link_args(
7 LinkerFlavor::Gnu(Cc::No, Lld::No),
8 &[
9 "-e",
10 "motor_start",
11 "--no-undefined",
12 "--error-unresolved-symbols",
13 "--no-undefined-version",
14 "-u",
15 "__rust_abort",
16 ],
7 LinkerFlavor::Gnu(Cc::Yes, Lld::No),
8 &["-e", "motor_start", "-u", "__rust_abort"],
179 );
1810 TargetOptions {
1911 os: Os::Motor,
......@@ -23,7 +15,7 @@ pub(crate) fn opts() -> TargetOptions {
2315 // We use "OS level" TLS (see thread/local.rs in stdlib).
2416 has_thread_local: false,
2517 frame_pointer: FramePointer::NonLeaf,
26 linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No),
18 linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
2719 main_needs_argc_argv: true,
2820 panic_strategy: PanicStrategy::Abort,
2921 pre_link_args,
compiler/rustc_target/src/spec/targets/x86_64_unknown_motor.rs+1-2
......@@ -1,5 +1,5 @@
11use crate::spec::{
2 Arch, CodeModel, LinkSelfContainedDefault, LldFlavor, RelocModel, RelroLevel, Target, base,
2 Arch, CodeModel, LinkSelfContainedDefault, RelocModel, RelroLevel, Target, base,
33};
44
55pub(crate) fn target() -> Target {
......@@ -15,7 +15,6 @@ pub(crate) fn target() -> Target {
1515 base.relro_level = RelroLevel::Full;
1616 base.static_position_independent_executables = true;
1717 base.relocation_model = RelocModel::Pic;
18 base.lld_flavor_json = LldFlavor::Ld;
1918 base.link_self_contained = LinkSelfContainedDefault::True;
2019 base.dynamic_linking = false;
2120 base.crt_static_default = true;
library/core/src/mem/manually_drop.rs+2-1
......@@ -217,8 +217,9 @@ impl<T> ManuallyDrop<T> {
217217 ///
218218 #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
219219 #[stable(feature = "manually_drop_take", since = "1.42.0")]
220 #[rustc_const_unstable(feature = "const_manually_drop_take", issue = "148773")]
220221 #[inline]
221 pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
222 pub const unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
222223 // SAFETY: we are reading from a reference, which is guaranteed
223224 // to be valid for reads.
224225 unsafe { ptr::read(&slot.value) }
library/core/src/mem/mod.rs+2-1
......@@ -808,7 +808,8 @@ pub const fn swap<T>(x: &mut T, y: &mut T) {
808808/// ```
809809#[inline]
810810#[stable(feature = "mem_take", since = "1.40.0")]
811pub fn take<T: Default>(dest: &mut T) -> T {
811#[rustc_const_unstable(feature = "const_default", issue = "143894")]
812pub const fn take<T: [const] Default>(dest: &mut T) -> T {
812813 replace(dest, T::default())
813814}
814815
library/core/src/str/mod.rs+11
......@@ -1251,6 +1251,8 @@ impl str {
12511251 /// ending will return the same lines as an otherwise identical string
12521252 /// without a final line ending.
12531253 ///
1254 /// An empty string returns an empty iterator.
1255 ///
12541256 /// # Examples
12551257 ///
12561258 /// Basic usage:
......@@ -1281,6 +1283,15 @@ impl str {
12811283 ///
12821284 /// assert_eq!(None, lines.next());
12831285 /// ```
1286 ///
1287 /// An empty string returns an empty iterator:
1288 ///
1289 /// ```
1290 /// let text = "";
1291 /// let mut lines = text.lines();
1292 ///
1293 /// assert_eq!(lines.next(), None);
1294 /// ```
12841295 #[stable(feature = "rust1", since = "1.0.0")]
12851296 #[inline]
12861297 pub fn lines(&self) -> Lines<'_> {
src/ci/docker/host-x86_64/pr-check-2/Dockerfile+8
......@@ -21,6 +21,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
2121 mingw-w64 \
2222 && rm -rf /var/lib/apt/lists/*
2323
24RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz | \
25 tar -xz
26ENV WASI_SDK_PATH=/wasi-sdk-27.0-x86_64-linux
27
2428ENV RUST_CONFIGURE_ARGS="--set rust.validate-mir-opts=3"
2529
2630COPY scripts/sccache.sh /scripts/
......@@ -30,6 +34,10 @@ ENV SCRIPT \
3034 python3 ../x.py check && \
3135 python3 ../x.py clippy ci --stage 2 && \
3236 python3 ../x.py test --stage 1 core alloc std test proc_macro && \
37 # Elsewhere, we run all tests for the host. A number of codegen tests are sensitive to the target pointer
38 # width, for example because they mention a usize. wasm32-wasip1 in test-various, so using it here can't make
39 # PR CI more strict than full CI.
40 python3 ../x.py test --stage 1 tests/codegen-llvm --target wasm32-wasip1 && \
3341 python3 ../x.py test --stage 1 src/tools/compiletest && \
3442 python3 ../x.py doc bootstrap --stage 1 && \
3543 # Build both public and internal documentation.
src/doc/rustc-dev-guide/src/tests/directives.md-1
......@@ -141,7 +141,6 @@ Some examples of `X` in `ignore-X` or `only-X`:
141141- OS: `android`, `emscripten`, `freebsd`, `ios`, `linux`, `macos`, `windows`,
142142 ...
143143- Environment (fourth word of the target triple): `gnu`, `msvc`, `musl`
144- WASM: `wasm32-bare` matches `wasm32-unknown-unknown`.
145144- Pointer width: `32bit`, `64bit`
146145- Endianness: `endian-big`
147146- Stage: `stage1`, `stage2`
src/tools/compiletest/src/directives/cfg.rs-8
......@@ -147,14 +147,6 @@ fn parse_cfg_name_directive<'a>(
147147 message: "when the target family is {name}"
148148 }
149149
150 // `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown
151 // (in contrast to `wasm32` which also matches non-bare targets)
152 condition! {
153 name: "wasm32-bare",
154 condition: config.target == "wasm32-unknown-unknown",
155 message: "when the target is WASM"
156 }
157
158150 condition! {
159151 name: "thumb",
160152 condition: config.target.starts_with("thumb"),
src/tools/compiletest/src/directives/directive_names.rs+2-2
......@@ -125,7 +125,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
125125 "ignore-wasi",
126126 "ignore-wasm",
127127 "ignore-wasm32",
128 "ignore-wasm32-bare",
128 "ignore-wasm32-unknown-unknown",
129129 "ignore-wasm64",
130130 "ignore-watchos",
131131 "ignore-windows",
......@@ -240,7 +240,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
240240 "only-unix",
241241 "only-visionos",
242242 "only-wasm32",
243 "only-wasm32-bare",
243 "only-wasm32-unknown-unknown",
244244 "only-wasm32-wasip1",
245245 "only-watchos",
246246 "only-windows",
src/tools/compiletest/src/directives/tests.rs-4
......@@ -710,18 +710,14 @@ fn wasm_special() {
710710 let ignores = [
711711 ("wasm32-unknown-unknown", "emscripten", false),
712712 ("wasm32-unknown-unknown", "wasm32", true),
713 ("wasm32-unknown-unknown", "wasm32-bare", true),
714713 ("wasm32-unknown-unknown", "wasm64", false),
715714 ("wasm32-unknown-emscripten", "emscripten", true),
716715 ("wasm32-unknown-emscripten", "wasm32", true),
717 ("wasm32-unknown-emscripten", "wasm32-bare", false),
718716 ("wasm32-wasip1", "emscripten", false),
719717 ("wasm32-wasip1", "wasm32", true),
720 ("wasm32-wasip1", "wasm32-bare", false),
721718 ("wasm32-wasip1", "wasi", true),
722719 ("wasm64-unknown-unknown", "emscripten", false),
723720 ("wasm64-unknown-unknown", "wasm32", false),
724 ("wasm64-unknown-unknown", "wasm32-bare", false),
725721 ("wasm64-unknown-unknown", "wasm64", true),
726722 ];
727723 for (target, pattern, ignore) in ignores {
src/tools/compiletest/src/runtest.rs+4-5
......@@ -2766,12 +2766,11 @@ impl<'test> TestCx<'test> {
27662766 .map_err(|err| format!("failed to load expected output from `{}`: {}", path, err))
27672767 }
27682768
2769 /// Attempts to delete a file, succeeding if the file does not exist.
27692770 fn delete_file(&self, file: &Utf8Path) {
2770 if !file.exists() {
2771 // Deleting a nonexistent file would error.
2772 return;
2773 }
2774 if let Err(e) = fs::remove_file(file.as_std_path()) {
2771 if let Err(e) = fs::remove_file(file.as_std_path())
2772 && e.kind() != io::ErrorKind::NotFound
2773 {
27752774 self.fatal(&format!("failed to delete `{}`: {}", file, e,));
27762775 }
27772776 }
src/tools/remote-test-server/src/main.rs+6-6
......@@ -10,13 +10,13 @@
1010//! themselves having support libraries. All data over the TCP sockets is in a
1111//! basically custom format suiting our needs.
1212
13#[cfg(not(windows))]
13#[cfg(all(not(windows), not(target_os = "motor")))]
1414use std::fs::Permissions;
1515use std::fs::{self, File};
1616use std::io::prelude::*;
1717use std::io::{self, BufReader};
1818use std::net::{SocketAddr, TcpListener, TcpStream};
19#[cfg(not(windows))]
19#[cfg(all(not(windows), not(target_os = "motor")))]
2020use std::os::unix::prelude::*;
2121use std::path::{Path, PathBuf};
2222use std::process::{Command, ExitStatus, Stdio};
......@@ -325,7 +325,7 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
325325 ]));
326326}
327327
328#[cfg(not(windows))]
328#[cfg(all(not(windows), not(target_os = "motor")))]
329329fn get_status_code(status: &ExitStatus) -> (u8, i32) {
330330 match status.code() {
331331 Some(n) => (0, n),
......@@ -333,7 +333,7 @@ fn get_status_code(status: &ExitStatus) -> (u8, i32) {
333333 }
334334}
335335
336#[cfg(windows)]
336#[cfg(any(windows, target_os = "motor"))]
337337fn get_status_code(status: &ExitStatus) -> (u8, i32) {
338338 (0, status.code().unwrap())
339339}
......@@ -359,11 +359,11 @@ fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
359359 dst
360360}
361361
362#[cfg(not(windows))]
362#[cfg(all(not(windows), not(target_os = "motor")))]
363363fn set_permissions(path: &Path) {
364364 t!(fs::set_permissions(&path, Permissions::from_mode(0o755)));
365365}
366#[cfg(windows)]
366#[cfg(any(windows, target_os = "motor"))]
367367fn set_permissions(_path: &Path) {}
368368
369369fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs+1-1
......@@ -3,7 +3,7 @@
33//@ ignore-apple slightly different policy on stack protection of arrays
44//@ ignore-msvc stack check code uses different function names
55//@ ignore-nvptx64 stack protector is not supported
6//@ ignore-wasm32-bare
6//@ ignore-wasm32-unknown-unknown
77//@ [all] compile-flags: -Z stack-protector=all
88//@ [strong] compile-flags: -Z stack-protector=strong
99//@ [basic] compile-flags: -Z stack-protector=basic
tests/auxiliary/minicore.rs+18
......@@ -119,6 +119,24 @@ pub struct ManuallyDrop<T: PointeeSized> {
119119}
120120impl<T: Copy + PointeeSized> Copy for ManuallyDrop<T> {}
121121
122#[repr(transparent)]
123#[rustc_layout_scalar_valid_range_start(1)]
124#[rustc_nonnull_optimization_guaranteed]
125pub struct NonNull<T: ?Sized> {
126 pointer: *const T,
127}
128impl<T: ?Sized> Copy for NonNull<T> {}
129
130#[repr(transparent)]
131#[rustc_layout_scalar_valid_range_start(1)]
132#[rustc_nonnull_optimization_guaranteed]
133pub struct NonZero<T>(T);
134
135pub struct Unique<T: ?Sized> {
136 pub pointer: NonNull<T>,
137 pub _marker: PhantomData<T>,
138}
139
122140#[lang = "unsafe_cell"]
123141#[repr(transparent)]
124142pub struct UnsafeCell<T: PointeeSized> {
tests/run-make/wasm-exceptions-nostd/rmake.rs+1-1
......@@ -1,4 +1,4 @@
1//@ only-wasm32-bare
1//@ only-wasm32-unknown-unknown
22
33use std::path::Path;
44
tests/ui/abi/compatibility.rs+12-18
......@@ -13,6 +13,9 @@
1313//@ revisions: arm
1414//@[arm] compile-flags: --target arm-unknown-linux-gnueabi
1515//@[arm] needs-llvm-components: arm
16//@ revisions: thumb
17//@[thumb] compile-flags: --target thumbv8m.main-none-eabi
18//@[thumb] needs-llvm-components: arm
1619//@ revisions: aarch64
1720//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
1821//@[aarch64] needs-llvm-components: aarch64
......@@ -31,12 +34,21 @@
3134//@ revisions: sparc64
3235//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
3336//@[sparc64] needs-llvm-components: sparc
37//@ revisions: powerpc
38//@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
39//@[powerpc] needs-llvm-components: powerpc
3440//@ revisions: powerpc64
3541//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
3642//@[powerpc64] needs-llvm-components: powerpc
43//@ revisions: aix
44//@[aix] compile-flags: --target powerpc64-ibm-aix
45//@[aix] needs-llvm-components: powerpc
3746//@ revisions: riscv
3847//@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu
3948//@[riscv] needs-llvm-components: riscv
49//@ revisions: loongarch32
50//@[loongarch32] compile-flags: --target loongarch32-unknown-none
51//@[loongarch32] needs-llvm-components: loongarch
4052//@ revisions: loongarch64
4153//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
4254//@[loongarch64] needs-llvm-components: loongarch
......@@ -87,19 +99,6 @@ mod prelude {
8799 fn clone(&self) -> Self;
88100 }
89101
90 #[repr(transparent)]
91 #[rustc_layout_scalar_valid_range_start(1)]
92 #[rustc_nonnull_optimization_guaranteed]
93 pub struct NonNull<T: ?Sized> {
94 pointer: *const T,
95 }
96 impl<T: ?Sized> Copy for NonNull<T> {}
97
98 #[repr(transparent)]
99 #[rustc_layout_scalar_valid_range_start(1)]
100 #[rustc_nonnull_optimization_guaranteed]
101 pub struct NonZero<T>(T);
102
103102 // This just stands in for a non-trivial type.
104103 pub struct Vec<T> {
105104 ptr: NonNull<T>,
......@@ -107,11 +106,6 @@ mod prelude {
107106 len: usize,
108107 }
109108
110 pub struct Unique<T: ?Sized> {
111 pub pointer: NonNull<T>,
112 pub _marker: PhantomData<T>,
113 }
114
115109 #[lang = "global_alloc_ty"]
116110 pub struct Global;
117111
tests/ui/autodiff/no_lto_flag.no_lto.stderr created+4
......@@ -0,0 +1,4 @@
1error: using the autodiff feature requires setting `lto="fat"` in your Cargo.toml
2
3error: aborting due to 1 previous error
4
tests/ui/autodiff/no_lto_flag.rs created+31
......@@ -0,0 +1,31 @@
1//@ needs-enzyme
2//@ no-prefer-dynamic
3//@ revisions: with_lto no_lto
4//@[with_lto] compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat
5//@[no_lto] compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=thin
6
7#![feature(autodiff)]
8//@[no_lto] build-fail
9//@[with_lto] build-pass
10
11// Autodiff requires users to enable lto=fat (for now).
12// In the past, autodiff did not run if users forget to enable fat-lto, which caused functions to
13// returning zero-derivatives. That's obviously wrong and confusing to users. We now added a check
14// which will abort compilation instead.
15
16use std::autodiff::autodiff_reverse;
17//[no_lto]~? ERROR using the autodiff feature requires setting `lto="fat"` in your Cargo.toml
18
19#[autodiff_reverse(d_square, Duplicated, Active)]
20fn square(x: &f64) -> f64 {
21 *x * *x
22}
23
24fn main() {
25 let xf64: f64 = std::hint::black_box(3.0);
26
27 let mut df_dxf64: f64 = std::hint::black_box(0.0);
28
29 let _output_f64 = d_square(&xf64, &mut df_dxf64, 1.0);
30 assert_eq!(6.0, df_dxf64);
31}
tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs+1-2
......@@ -31,9 +31,8 @@ async unsafe extern "cmse-nonsecure-entry" fn async_is_not_allowed() {
3131// this file, but they may be moved into `minicore` if/when other `#[no_core]` tests want to use
3232// them.
3333
34// NOTE: in `core` this type uses `NonNull`.
3534#[lang = "ResumeTy"]
36pub struct ResumeTy(*mut Context<'static>);
35pub struct ResumeTy(NonNull<Context<'static>>);
3736
3837#[lang = "future_trait"]
3938pub trait Future {
tests/ui/proc-macro/auxiliary/nonfatal-parsing-body.rs created+143
......@@ -0,0 +1,143 @@
1use std::fmt::Debug;
2use std::panic::catch_unwind;
3use std::str::FromStr;
4
5use proc_macro::*;
6
7use self::Mode::*;
8
9// FIXME: all cases should become `NormalOk` or `NormalErr`
10#[derive(PartialEq, Clone, Copy)]
11enum Mode {
12 NormalOk,
13 NormalErr,
14 OtherError,
15 OtherWithPanic,
16}
17
18fn parse<T>(s: &str, mode: Mode)
19where
20 T: FromStr<Err = LexError> + Debug,
21{
22 match mode {
23 NormalOk => {
24 let t = T::from_str(s);
25 println!("{:?}", t);
26 assert!(t.is_ok());
27 }
28 NormalErr => {
29 let t = T::from_str(s);
30 println!("{:?}", t);
31 assert!(t.is_err());
32 }
33 OtherError => {
34 println!("{:?}", T::from_str(s));
35 }
36 OtherWithPanic => {
37 if catch_unwind(|| println!("{:?}", T::from_str(s))).is_ok() {
38 eprintln!("{s} did not panic");
39 }
40 }
41 }
42}
43
44fn stream(s: &str, mode: Mode) {
45 parse::<TokenStream>(s, mode);
46}
47
48fn lit(s: &str, mode: Mode) {
49 parse::<Literal>(s, mode);
50 if mode == NormalOk {
51 let Ok(lit) = Literal::from_str(s) else {
52 panic!("literal was not ok");
53 };
54 let Ok(stream) = TokenStream::from_str(s) else {
55 panic!("tokenstream was not ok, but literal was");
56 };
57 let Some(tree) = stream.into_iter().next() else {
58 panic!("tokenstream should have a tokentree");
59 };
60 if let TokenTree::Literal(tokenstream_lit) = tree {
61 assert_eq!(lit.to_string(), tokenstream_lit.to_string());
62 }
63 }
64}
65
66pub fn run() {
67 // returns Ok(valid instance)
68 lit("123", NormalOk);
69 lit("\"ab\"", NormalOk);
70 lit("\'b\'", NormalOk);
71 lit("'b'", NormalOk);
72 lit("b\"b\"", NormalOk);
73 lit("c\"b\"", NormalOk);
74 lit("cr\"b\"", NormalOk);
75 lit("b'b'", NormalOk);
76 lit("256u8", NormalOk);
77 lit("-256u8", NormalOk);
78 stream("-256u8", NormalOk);
79 lit("0b11111000000001111i16", NormalOk);
80 lit("0xf32", NormalOk);
81 lit("0b0f32", NormalOk);
82 lit("2E4", NormalOk);
83 lit("2.2E-4f64", NormalOk);
84 lit("18u8E", NormalOk);
85 lit("18.0u8E", NormalOk);
86 lit("cr#\"// /* // \n */\"#", NormalOk);
87 lit("'\\''", NormalOk);
88 lit("'\\\''", NormalOk);
89 lit(&format!("r{0}\"a\"{0}", "#".repeat(255)), NormalOk);
90 stream("fn main() { println!(\"Hello, world!\") }", NormalOk);
91 stream("18.u8E", NormalOk);
92 stream("18.0f32", NormalOk);
93 stream("18.0f34", NormalOk);
94 stream("18.bu8", NormalOk);
95 stream("3//\n4", NormalOk);
96 stream(
97 "\'c\'/*\n
98 */",
99 NormalOk,
100 );
101 stream("/*a*/ //", NormalOk);
102
103 println!("### ERRORS");
104
105 // returns Err(LexError)
106 lit("\'c\'/**/", NormalErr);
107 lit(" 0", NormalErr);
108 lit("0 ", NormalErr);
109 lit("0//", NormalErr);
110 lit("3//\n4", NormalErr);
111 lit("18.u8E", NormalErr);
112 lit("/*a*/ //", NormalErr);
113 // FIXME: all of the cases below should return an Err and emit no diagnostics, but don't yet.
114
115 // emits diagnostics and returns LexError
116 lit("r'r'", OtherError);
117 lit("c'r'", OtherError);
118
119 // emits diagnostic and returns a seemingly valid tokenstream
120 stream("r'r'", OtherError);
121 stream("c'r'", OtherError);
122
123 for parse in [stream as fn(&str, Mode), lit] {
124 // emits diagnostic(s), then panics
125 parse("1 ) 2", OtherWithPanic);
126 parse("( x [ ) ]", OtherWithPanic);
127 parse("r#", OtherWithPanic);
128
129 // emits diagnostic(s), then returns Ok(Literal { kind: ErrWithGuar, .. })
130 parse("0b2", OtherError);
131 parse("0bf32", OtherError);
132 parse("0b0.0f32", OtherError);
133 parse("'\''", OtherError);
134 parse(
135 "'
136'", OtherError,
137 );
138 parse(&format!("r{0}\"a\"{0}", "#".repeat(256)), OtherWithPanic);
139
140 // emits diagnostic, then, when parsing as a lit, returns LexError, otherwise ErrWithGuar
141 parse("/*a*/ 0b2 //", OtherError);
142 }
143}
tests/ui/proc-macro/auxiliary/nonfatal-parsing.rs created+11
......@@ -0,0 +1,11 @@
1extern crate proc_macro;
2use proc_macro::*;
3
4#[path = "nonfatal-parsing-body.rs"]
5mod body;
6
7#[proc_macro]
8pub fn run(_: TokenStream) -> TokenStream {
9 body::run();
10 TokenStream::new()
11}
tests/ui/proc-macro/nonfatal-parsing.rs created+19
......@@ -0,0 +1,19 @@
1//@ proc-macro: nonfatal-parsing.rs
2//@ needs-unwind
3//@ edition: 2024
4//@ dont-require-annotations: ERROR
5//@ ignore-backends: gcc
6// FIXME: should be a run-pass test once invalidly parsed tokens no longer result in diagnostics
7
8extern crate proc_macro;
9extern crate nonfatal_parsing;
10
11#[path = "auxiliary/nonfatal-parsing-body.rs"]
12mod body;
13
14fn main() {
15 nonfatal_parsing::run!();
16 // FIXME: enable this once the standalone backend exists
17 // https://github.com/rust-lang/rust/issues/130856
18 // body::run();
19}
tests/ui/proc-macro/nonfatal-parsing.stderr created+197
......@@ -0,0 +1,197 @@
1error: prefix `r` is unknown
2 --> <proc-macro source code>:1:1
3 |
4LL | r'r'
5 | ^ unknown prefix
6 |
7 = note: prefixed identifiers and literals are reserved since Rust 2021
8help: consider inserting whitespace here
9 |
10LL | r 'r'
11 | +
12
13error: prefix `c` is unknown
14 --> <proc-macro source code>:1:1
15 |
16LL | c'r'
17 | ^ unknown prefix
18 |
19 = note: prefixed identifiers and literals are reserved since Rust 2021
20help: consider inserting whitespace here
21 |
22LL | c 'r'
23 | +
24
25error: unexpected closing delimiter: `)`
26 --> $DIR/nonfatal-parsing.rs:15:5
27 |
28LL | nonfatal_parsing::run!();
29 | ^^^^^^^^^^^^^^^^^^^^^^^^ unexpected closing delimiter
30 |
31 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
32
33error: unexpected closing delimiter: `]`
34 --> $DIR/nonfatal-parsing.rs:15:5
35 |
36LL | nonfatal_parsing::run!();
37 | -^^^^^^^^^^^^^^^^^^^^^^^
38 | |
39 | the nearest open delimiter
40 | missing open `(` for this delimiter
41 | unexpected closing delimiter
42 |
43 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
44
45error: found invalid character; only `#` is allowed in raw string delimitation: \u{0}
46 --> $DIR/nonfatal-parsing.rs:15:5
47 |
48LL | nonfatal_parsing::run!();
49 | ^^^^^^^^^^^^^^^^^^^^^^^^
50 |
51 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
52
53error: invalid digit for a base 2 literal
54 --> $DIR/nonfatal-parsing.rs:15:5
55 |
56LL | nonfatal_parsing::run!();
57 | ^^^^^^^^^^^^^^^^^^^^^^^^
58 |
59 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
60
61error[E0768]: no valid digits found for number
62 --> $DIR/nonfatal-parsing.rs:15:5
63 |
64LL | nonfatal_parsing::run!();
65 | ^^^^^^^^^^^^^^^^^^^^^^^^
66 |
67 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
68
69error: binary float literal is not supported
70 --> $DIR/nonfatal-parsing.rs:15:5
71 |
72LL | nonfatal_parsing::run!();
73 | ^^^^^^^^^^^^^^^^^^^^^^^^
74 |
75 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
76
77error: character constant must be escaped: `'`
78 --> $DIR/nonfatal-parsing.rs:15:5
79 |
80LL | nonfatal_parsing::run!();
81 | ^^^^^^^^^^^^^^^^^^^^^^^^
82 |
83 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
84help: escape the character
85 |
86LL - nonfatal_parsing::run!();
87LL + nonfatal_parsing::run!(\';
88 |
89
90error: character constant must be escaped: `\n`
91 --> $DIR/nonfatal-parsing.rs:15:5
92 |
93LL | nonfatal_parsing::run!();
94 | ^^^^^^^^^^^^^^^^^^^^^^^^
95 |
96 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
97help: escape the character
98 |
99LL - nonfatal_parsing::run!();
100LL + nonfatal_parsing::run!(\n;
101 |
102
103error: too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found 256
104 --> $DIR/nonfatal-parsing.rs:15:5
105 |
106LL | nonfatal_parsing::run!();
107 | ^^^^^^^^^^^^^^^^^^^^^^^^
108 |
109 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
110
111error: invalid digit for a base 2 literal
112 --> $DIR/nonfatal-parsing.rs:15:5
113 |
114LL | nonfatal_parsing::run!();
115 | ^^^^^^^^^^^^^^^^^^^^^^^^
116 |
117 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
118 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
119
120error: unexpected closing delimiter: `)`
121 --> <proc-macro source code>:1:3
122 |
123LL | 1 ) 2
124 | ^ unexpected closing delimiter
125
126error: unexpected closing delimiter: `]`
127 --> <proc-macro source code>:1:10
128 |
129LL | ( x [ ) ]
130 | - - ^ unexpected closing delimiter
131 | | |
132 | | missing open `(` for this delimiter
133 | the nearest open delimiter
134
135error: found invalid character; only `#` is allowed in raw string delimitation: \u{0}
136 --> <proc-macro source code>:1:1
137 |
138LL | r#
139 | ^^
140
141error: invalid digit for a base 2 literal
142 --> <proc-macro source code>:1:3
143 |
144LL | 0b2
145 | ^
146
147error[E0768]: no valid digits found for number
148 --> <proc-macro source code>:1:1
149 |
150LL | 0bf32
151 | ^^
152
153error: binary float literal is not supported
154 --> <proc-macro source code>:1:1
155 |
156LL | 0b0.0f32
157 | ^^^^^
158
159error: character constant must be escaped: `'`
160 --> <proc-macro source code>:1:2
161 |
162LL | '''
163 | ^
164 |
165help: escape the character
166 |
167LL | '\''
168 | +
169
170error: character constant must be escaped: `\n`
171 --> <proc-macro source code>:1:2
172 |
173LL | '
174 | __^
175LL | | '
176 | |_^
177 |
178help: escape the character
179 |
180LL | '\n'
181 | ++
182
183error: too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found 256
184 --> <proc-macro source code>:1:1
185 |
186LL | r#######################################...##################################################
187 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
188
189error: invalid digit for a base 2 literal
190 --> <proc-macro source code>:1:9
191 |
192LL | /*a*/ 0b2 //
193 | ^
194
195error: aborting due to 22 previous errors
196
197For more information about this error, try `rustc --explain E0768`.
tests/ui/proc-macro/nonfatal-parsing.stdout created+54
......@@ -0,0 +1,54 @@
1Ok(Literal { kind: Integer, symbol: "123", suffix: None, span: #44 bytes(361..385) })
2Ok(Literal { kind: Str, symbol: "ab", suffix: None, span: #44 bytes(361..385) })
3Ok(Literal { kind: Char, symbol: "b", suffix: None, span: #44 bytes(361..385) })
4Ok(Literal { kind: Char, symbol: "b", suffix: None, span: #44 bytes(361..385) })
5Ok(Literal { kind: ByteStr, symbol: "b", suffix: None, span: #44 bytes(361..385) })
6Ok(Literal { kind: CStr, symbol: "b", suffix: None, span: #44 bytes(361..385) })
7Ok(Literal { kind: CStrRaw(0), symbol: "b", suffix: None, span: #44 bytes(361..385) })
8Ok(Literal { kind: Byte, symbol: "b", suffix: None, span: #44 bytes(361..385) })
9Ok(Literal { kind: Integer, symbol: "256", suffix: Some("u8"), span: #44 bytes(361..385) })
10Ok(Literal { kind: Integer, symbol: "-256", suffix: Some("u8"), span: #44 bytes(361..385) })
11Ok(TokenStream [Punct { ch: '-', spacing: Alone, span: #44 bytes(361..385) }, Literal { kind: Integer, symbol: "256", suffix: Some("u8"), span: #44 bytes(361..385) }])
12Ok(Literal { kind: Integer, symbol: "0b11111000000001111", suffix: Some("i16"), span: #44 bytes(361..385) })
13Ok(Literal { kind: Integer, symbol: "0xf32", suffix: None, span: #44 bytes(361..385) })
14Ok(Literal { kind: Integer, symbol: "0b0", suffix: Some("f32"), span: #44 bytes(361..385) })
15Ok(Literal { kind: Float, symbol: "2E4", suffix: None, span: #44 bytes(361..385) })
16Ok(Literal { kind: Float, symbol: "2.2E-4", suffix: Some("f64"), span: #44 bytes(361..385) })
17Ok(Literal { kind: Integer, symbol: "18", suffix: Some("u8E"), span: #44 bytes(361..385) })
18Ok(Literal { kind: Float, symbol: "18.0", suffix: Some("u8E"), span: #44 bytes(361..385) })
19Ok(Literal { kind: CStrRaw(1), symbol: "// /* // \n */", suffix: None, span: #44 bytes(361..385) })
20Ok(Literal { kind: Char, symbol: "\'", suffix: None, span: #44 bytes(361..385) })
21Ok(Literal { kind: Char, symbol: "\'", suffix: None, span: #44 bytes(361..385) })
22Ok(Literal { kind: StrRaw(255), symbol: "a", suffix: None, span: #44 bytes(361..385) })
23Ok(TokenStream [Ident { ident: "fn", span: #44 bytes(361..385) }, Ident { ident: "main", span: #44 bytes(361..385) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #44 bytes(361..385) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "println", span: #44 bytes(361..385) }, Punct { ch: '!', spacing: Alone, span: #44 bytes(361..385) }, Group { delimiter: Parenthesis, stream: TokenStream [Literal { kind: Str, symbol: "Hello, world!", suffix: None, span: #44 bytes(361..385) }], span: #44 bytes(361..385) }], span: #44 bytes(361..385) }])
24Ok(TokenStream [Literal { kind: Integer, symbol: "18", suffix: None, span: #44 bytes(361..385) }, Punct { ch: '.', spacing: Alone, span: #44 bytes(361..385) }, Ident { ident: "u8E", span: #44 bytes(361..385) }])
25Ok(TokenStream [Literal { kind: Float, symbol: "18.0", suffix: Some("f32"), span: #44 bytes(361..385) }])
26Ok(TokenStream [Literal { kind: Float, symbol: "18.0", suffix: Some("f34"), span: #44 bytes(361..385) }])
27Ok(TokenStream [Literal { kind: Integer, symbol: "18", suffix: None, span: #44 bytes(361..385) }, Punct { ch: '.', spacing: Alone, span: #44 bytes(361..385) }, Ident { ident: "bu8", span: #44 bytes(361..385) }])
28Ok(TokenStream [Literal { kind: Integer, symbol: "3", suffix: None, span: #44 bytes(361..385) }, Literal { kind: Integer, symbol: "4", suffix: None, span: #44 bytes(361..385) }])
29Ok(TokenStream [Literal { kind: Char, symbol: "c", suffix: None, span: #44 bytes(361..385) }])
30Ok(TokenStream [])
31### ERRORS
32Err(LexError)
33Err(LexError)
34Err(LexError)
35Err(LexError)
36Err(LexError)
37Err(LexError)
38Err(LexError)
39Err(LexError)
40Err(LexError)
41Ok(TokenStream [Ident { ident: "r", span: #44 bytes(361..385) }, Literal { kind: Char, symbol: "r", suffix: None, span: #44 bytes(361..385) }])
42Ok(TokenStream [Ident { ident: "c", span: #44 bytes(361..385) }, Literal { kind: Char, symbol: "r", suffix: None, span: #44 bytes(361..385) }])
43Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: #44 bytes(361..385) }])
44Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b", suffix: Some("f32"), span: #44 bytes(361..385) }])
45Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b0.0", suffix: Some("f32"), span: #44 bytes(361..385) }])
46Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "'''", suffix: None, span: #44 bytes(361..385) }])
47Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "'\n'", suffix: None, span: #44 bytes(361..385) }])
48Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: #44 bytes(361..385) }])
49Ok(Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: #44 bytes(361..385) })
50Ok(Literal { kind: ErrWithGuar, symbol: "0b", suffix: Some("f32"), span: #44 bytes(361..385) })
51Ok(Literal { kind: ErrWithGuar, symbol: "0b0.0", suffix: Some("f32"), span: #44 bytes(361..385) })
52Ok(Literal { kind: ErrWithGuar, symbol: "'''", suffix: None, span: #44 bytes(361..385) })
53Ok(Literal { kind: ErrWithGuar, symbol: "'\n'", suffix: None, span: #44 bytes(361..385) })
54Err(LexError)
triagebot.toml-1
......@@ -1070,7 +1070,6 @@ source file via `./x run src/tools/unicode-table-generator` instead of editing \
10701070message = "Some changes occurred in HTML/CSS/JS."
10711071cc = [
10721072 "@GuillaumeGomez",
1073 "@jsha",
10741073 "@lolbinarycat",
10751074]
10761075