diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index e29b29fc6ccb0..9049639925ddb 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -60,12 +60,18 @@ fn eii_( ) -> Vec { let eii_attr_span = ecx.with_def_site_ctxt(eii_attr_span); - let (item, stmt) = if let Annotatable::Item(item) = item { - (item, false) + let (item, wrap_item): (_, &dyn Fn(_) -> _) = if let Annotatable::Item(item) = item { + (item, &Annotatable::Item) } else if let Annotatable::Stmt(ref stmt) = item && let StmtKind::Item(ref item) = stmt.kind { - (item.clone(), true) + (item.clone(), &|item| { + Annotatable::Stmt(Box::new(Stmt { + id: DUMMY_NODE_ID, + kind: StmtKind::Item(item), + span: eii_attr_span, + })) + }) } else { ecx.dcx().emit_err(EiiSharedMacroExpectedFunction { span: eii_attr_span, @@ -74,23 +80,25 @@ fn eii_( return vec![item]; }; - let orig_item = item.clone(); - - let item = *item; - - let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } = item else { + let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } = + item.as_ref() + else { ecx.dcx().emit_err(EiiSharedMacroExpectedFunction { span: eii_attr_span, name: path_to_string(&meta_item.path), }); - return vec![Annotatable::Item(Box::new(item))]; + return vec![wrap_item(item)]; }; + // only clone what we need + let attrs = attrs.clone(); + let func = (**func).clone(); + let vis = vis.clone(); let attrs_from_decl = filter_attrs_for_multiple_eii_attr(ecx, attrs, eii_attr_span, &meta_item.path); let Ok(macro_name) = name_for_impl_macro(ecx, &func, &meta_item) else { - return vec![Annotatable::Item(orig_item)]; + return vec![wrap_item(item)]; }; // span of the declaring item without attributes @@ -115,7 +123,7 @@ fn eii_( ecx, eii_attr_span, item_span, - *func, + func, vis, &attrs_from_decl, ))); @@ -128,20 +136,7 @@ fn eii_( decl_span, ))); - if stmt { - return_items - .into_iter() - .map(|i| { - Annotatable::Stmt(Box::new(Stmt { - id: DUMMY_NODE_ID, - kind: StmtKind::Item(i), - span: eii_attr_span, - })) - }) - .collect() - } else { - return_items.into_iter().map(|i| Annotatable::Item(i)).collect() - } + return_items.into_iter().map(wrap_item).collect() } /// Decide on the name of the macro that can be used to implement the EII. diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index d49f4ded010bb..0f31de60a8a49 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -144,9 +144,7 @@ pub(crate) fn expand_include<'cx>( let mut p = unwrap_or_emit_fatal(new_parser_from_file( self.psess, &self.path, - // Don't strip frontmatter for backward compatibility, `---` may be the start of a - // manifold negation. FIXME: Ideally, we wouldn't strip shebangs here either. - StripTokens::Shebang, + StripTokens::Nothing, Some(self.span), )); let expr = parse_expr(&mut p).ok()?; diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 9f75578aa636c..cd1e573ea28df 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -416,7 +416,7 @@ impl<'a> Id<'a> { /// it in the generated .dot file. They can also provide more /// elaborate (and non-unique) label text that is used in the graphviz /// rendered output. - +/// /// The graph instance is responsible for providing the DOT compatible /// identifiers for the nodes and (optionally) rendered labels for the nodes and /// edges, as well as an identifier for the graph itself. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 471bd1d937e94..9e4692b96418e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2654,7 +2654,7 @@ struct InternedInSet<'tcx, T: ?Sized + PointeeSized>(&'tcx T); impl<'tcx, T: 'tcx + ?Sized + PointeeSized> Clone for InternedInSet<'tcx, T> { fn clone(&self) -> Self { - InternedInSet(self.0) + *self } } diff --git a/compiler/rustc_mir_build/src/builder/matches/buckets.rs b/compiler/rustc_mir_build/src/builder/matches/buckets.rs index 6c5f0ed28a82d..8cbbb8e14095a 100644 --- a/compiler/rustc_mir_build/src/builder/matches/buckets.rs +++ b/compiler/rustc_mir_build/src/builder/matches/buckets.rs @@ -218,7 +218,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &TestKind::Len { len: test_len, op: BinOp::Eq }, &TestableCase::Slice { len, variable_length }, ) => { - match (test_len.cmp(&(len as u64)), variable_length) { + match (test_len.cmp(&len), variable_length) { (Ordering::Equal, false) => { // on true, min_len = len = $actual_length, // on false, len != $actual_length @@ -251,7 +251,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &TestableCase::Slice { len, variable_length }, ) => { // the test is `$actual_len >= test_len` - match (test_len.cmp(&(len as u64)), variable_length) { + match (test_len.cmp(&len), variable_length) { (Ordering::Equal, true) => { // $actual_len >= test_len = pat_len, // so we can match. diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 6b4ba92434793..9b9ee18369564 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -256,7 +256,7 @@ impl<'tcx> MatchPairTree<'tcx> { None } else { Some(TestableCase::Slice { - len: prefix.len() + suffix.len(), + len: u64::try_from(prefix.len() + suffix.len()).unwrap(), variable_length: slice.is_some(), }) } diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 66e36a99d3c4e..8897ca7c72107 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -1264,7 +1264,7 @@ enum TestableCase<'tcx> { Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx }, Constant { value: ty::Value<'tcx> }, Range(Arc>), - Slice { len: usize, variable_length: bool }, + Slice { len: u64, variable_length: bool }, Deref { temp: Place<'tcx>, mutability: Mutability }, Never, Or { pats: Box<[FlatPat<'tcx>]> }, diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index 55e21ff18aae4..402587bff7e86 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestableCase::Slice { len, variable_length } => { let op = if variable_length { BinOp::Ge } else { BinOp::Eq }; - TestKind::Len { len: len as u64, op } + TestKind::Len { len, op } } TestableCase::Deref { temp, mutability } => TestKind::Deref { temp, mutability }, diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index d9bb93a829b59..f3308086ddc64 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -141,7 +141,7 @@ pub struct MatchArm<'p, Cx: PatCx> { impl<'p, Cx: PatCx> Clone for MatchArm<'p, Cx> { fn clone(&self) -> Self { - Self { pat: self.pat, has_guard: self.has_guard, arm_data: self.arm_data } + *self } } diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 901b72e53995e..51d0703f9c5ce 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -174,10 +174,7 @@ pub(crate) enum PatOrWild<'p, Cx: PatCx> { impl<'p, Cx: PatCx> Clone for PatOrWild<'p, Cx> { fn clone(&self) -> Self { - match self { - PatOrWild::Wild => PatOrWild::Wild, - PatOrWild::Pat(pat) => PatOrWild::Pat(pat), - } + *self } } diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 19446a1efe9cb..971616b189148 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -824,7 +824,7 @@ struct PlaceCtxt<'a, Cx: PatCx> { impl<'a, Cx: PatCx> Copy for PlaceCtxt<'a, Cx> {} impl<'a, Cx: PatCx> Clone for PlaceCtxt<'a, Cx> { fn clone(&self) -> Self { - Self { cx: self.cx, ty: self.ty } + *self } } diff --git a/compiler/rustc_thread_pool/src/registry.rs b/compiler/rustc_thread_pool/src/registry.rs index 4a018ea743aea..92bb8961e7dfc 100644 --- a/compiler/rustc_thread_pool/src/registry.rs +++ b/compiler/rustc_thread_pool/src/registry.rs @@ -153,8 +153,8 @@ pub struct Registry { terminate_count: AtomicUsize, } -/// //////////////////////////////////////////////////////////////////////// -/// Initialization +/////////////////////////////////////////////////////////////////////////// +// Initialization static mut THE_REGISTRY: Option> = None; static THE_REGISTRY_SET: Once = Once::new(); @@ -407,12 +407,12 @@ impl Registry { } } - /// //////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// MAIN LOOP /// /// So long as all of the worker threads are hanging out in their /// top-level loop, there is no work to be done. - + /// /// Push a job into the given `registry`. If we are running on a /// worker thread for the registry, this will push onto the /// deque. Else, it will inject from the outside (which is slower). @@ -668,8 +668,8 @@ impl ThreadInfo { } } -/// //////////////////////////////////////////////////////////////////////// -/// WorkerThread identifiers +/////////////////////////////////////////////////////////////////////////// +// WorkerThread identifiers pub(super) struct WorkerThread { /// the "worker" half of our local deque @@ -1019,8 +1019,6 @@ impl WorkerThread { } } -/// //////////////////////////////////////////////////////////////////////// - unsafe fn main_loop(thread: ThreadBuilder) { let worker_thread = &WorkerThread::from(thread); unsafe { WorkerThread::set_current(worker_thread) }; diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 6c71e2216a71b..af4469fad2cc6 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -353,7 +353,8 @@ impl OnceCell { } #[stable(feature = "once_cell", since = "1.70.0")] -impl Default for OnceCell { +#[rustc_const_unstable(feature = "const_default", issue = "143894")] +impl const Default for OnceCell { #[inline] fn default() -> Self { Self::new() diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 977fd1926fd0c..a5d9a5352dfcf 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -118,13 +118,6 @@ pub use crate::macros::builtin::deref; )] pub use crate::macros::builtin::define_opaque; -#[unstable( - feature = "derive_from", - issue = "144889", - reason = "`derive(From)` is unstable" -)] -pub use crate::macros::builtin::From; - #[unstable(feature = "extern_item_impls", issue = "125418")] pub use crate::macros::builtin::{eii, unsafe_eii}; diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 0601019abbd5c..1eae06ebd33e7 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1151,8 +1151,8 @@ impl AtomicBool { /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// - /// let foo = AtomicBool::new(true); - /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true); + /// let foo = AtomicBool::new(false); + /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); diff --git a/library/coretests/tests/fmt/mod.rs b/library/coretests/tests/fmt/mod.rs index d0ae7124f4742..0fb099ef41911 100644 --- a/library/coretests/tests/fmt/mod.rs +++ b/library/coretests/tests/fmt/mod.rs @@ -30,6 +30,12 @@ fn test_format_flags() { assert_eq!(format!("{:p} {:x}", p, 16), format!("{p:p} 10")); assert_eq!(format!("{: >3}", 'a'), " a"); + + /// Regression test for . + fn show(a: fn() -> f32, b: fn(&Vec) -> f32) { + println!("the two pointers: {:p} {:p}", a, b); + } + show(|| 1.0, |_| 2.0); } #[test] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 508a6ed852610..4fcaff4339085 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -274,6 +274,7 @@ #![feature(cfg_sanitizer_cfi)] #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] +#![feature(const_default)] #![feature(const_trait_impl)] #![feature(core_float_math)] #![feature(decl_macro)] diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index d1bbe0ff843cf..b9a7077e420e6 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -582,7 +582,8 @@ impl RefUnwindSafe for OnceLock {} impl UnwindSafe for OnceLock {} #[stable(feature = "once_cell", since = "1.70.0")] -impl Default for OnceLock { +#[rustc_const_unstable(feature = "const_default", issue = "143894")] +impl const Default for OnceLock { /// Creates a new uninitialized cell. /// /// # Example diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index e3a0a77f53f08..cff2aa7b08b93 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -73,11 +73,28 @@ cfg_select! { } _ => { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] + #[link(name = "gcc_s", cfg(all(not(target_feature = "crt-static"), not(target_arch = "hexagon"))))] unsafe extern "C" {} } } +// Hexagon with musl uses llvm-libunwind by default +#[cfg(all(target_env = "musl", target_arch = "hexagon"))] +cfg_select! { + feature = "llvm-libunwind" => { + #[link(name = "unwind", kind = "static", modifiers = "-bundle")] + unsafe extern "C" {} + } + feature = "system-llvm-libunwind" => { + #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] + #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] + unsafe extern "C" {} + } + _ => { + // Fallback: should not happen since hexagon defaults to llvm-libunwind + } +} + // This is the same as musl except that we default to using the system libunwind // instead of libgcc. #[cfg(target_env = "ohos")] diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index ed154133dec2e..84ab983dc7c6f 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -354,7 +354,10 @@ fn copy_third_party_objects( if target == "x86_64-fortanix-unknown-sgx" || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree - && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix")) + && (target.contains("linux") + || target.contains("fuchsia") + || target.contains("aix") + || target.contains("hexagon")) { let libunwind_path = copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target)); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index a81b8ccb9140a..683128a5e1532 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1856,7 +1856,7 @@ impl Config { .get(&target) .and_then(|t| t.llvm_libunwind) .or(self.llvm_libunwind_default) - .unwrap_or(if target.contains("fuchsia") { + .unwrap_or(if target.contains("fuchsia") || target.contains("hexagon") { LlvmLibunwind::InTree } else { LlvmLibunwind::No diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 1ac6889352786..fa2b6cf268063 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -173,6 +173,10 @@ impl TestContext { p.envs.push(("RUSTC_SNAPSHOT".into(), Some(rustc.into()))); p.envs.push(("RUSTC_SNAPSHOT_LIBDIR".into(), Some(libdir.into()))); p.envs.push(("RUSTC_SYSROOT".into(), Some(sysroot.into()))); + // Ensure we rebuild the dependencies when the sysroot changes. + // (Bootstrap usually sets this automatically, but since we invoke cargo + // ourselves we have to do it.) + p.args.push("-Zbinary-dep-depinfo".into()); } p }, diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index 4ef5ce35bd6cf..8a3ab658b6694 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -133,7 +133,11 @@ fn miri_config( program: miri_path() .with_file_name(format!("cargo-miri{}", env::consts::EXE_SUFFIX)), // There is no `cargo miri build` so we just use `cargo miri run`. - args: ["miri", "run"].into_iter().map(Into::into).collect(), + // Add `-Zbinary-dep-depinfo` since it is needed for bootstrap builds (and doesn't harm otherwise). + args: ["miri", "run", "--quiet", "-Zbinary-dep-depinfo"] + .into_iter() + .map(Into::into) + .collect(), // Reset `RUSTFLAGS` to work around . envs: vec![("RUSTFLAGS".into(), None)], ..CommandBuilder::cargo() diff --git a/tests/assembly-llvm/some-non-zero-from-atomic-optimization.rs b/tests/assembly-llvm/some-non-zero-from-atomic-optimization.rs new file mode 100644 index 0000000000000..6cff090188cbc --- /dev/null +++ b/tests/assembly-llvm/some-non-zero-from-atomic-optimization.rs @@ -0,0 +1,45 @@ +//! Regression test for . + +//@ assembly-output: emit-asm +//@ only-x86_64 + +// We want to check that the None case is optimized away +//@ compile-flags: -O + +// Simplify the generated assembly +//@ compile-flags: -Cforce-unwind-tables=no + +#![crate_type = "lib"] + +use std::num::NonZeroUsize; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::Relaxed; + +pub static X: AtomicUsize = AtomicUsize::new(1); + +/// This function function shall look like this: +/// ``` +/// some_non_zero_from_atomic_get: +/// movq _RNvCs7C4TuIcXqwO_25some_non_zero_from_atomic1X@GOTPCREL(%rip), %rax +/// movq (%rax), %rax +/// retq +/// ``` +// CHECK-LABEL: some_non_zero_from_atomic_get: +// CHECK-NEXT: movq {{[_a-zA-Z0-9]+}}@GOTPCREL(%rip), %rax +// CHECK-NEXT: movq (%rax), %rax +// CHECK-NEXT: retq +#[no_mangle] +pub unsafe fn some_non_zero_from_atomic_get() -> Option { + let x = X.load(Relaxed); + Some(NonZeroUsize::new_unchecked(x)) +} + +/// This function shall be identical to the above, which means: +// CHECK-DAG: some_non_zero_from_atomic_get2 = some_non_zero_from_atomic_get +#[no_mangle] +pub unsafe fn some_non_zero_from_atomic_get2() -> usize { + match some_non_zero_from_atomic_get() { + Some(x) => x.get(), + None => unreachable!(), // shall be optimized out + } +} diff --git a/tests/ui/eii/error_statement_position.rs b/tests/ui/eii/error_statement_position.rs new file mode 100644 index 0000000000000..cf81e7e6a8b23 --- /dev/null +++ b/tests/ui/eii/error_statement_position.rs @@ -0,0 +1,16 @@ +#![feature(extern_item_impls)] +// EIIs can, despite not being super useful, be declared in statement position +// nested inside items. Items in statement position, when expanded as part of a macro, +// need to be wrapped slightly differently (in an `ast::Statement`). +// We did this on the happy path (no errors), but when there was an error, we'd +// replace it with *just* an `ast::Item` not wrapped in an `ast::Statement`. +// This caused an ICE (https://github.com/rust-lang/rust/issues/149980). +// this test fails to build, but demonstrates that no ICE is produced. + +fn main() { + struct Bar; + + #[eii] + //~^ ERROR `#[eii]` is only valid on functions + impl Bar {} +} diff --git a/tests/ui/eii/error_statement_position.stderr b/tests/ui/eii/error_statement_position.stderr new file mode 100644 index 0000000000000..01b7394ef00fa --- /dev/null +++ b/tests/ui/eii/error_statement_position.stderr @@ -0,0 +1,8 @@ +error: `#[eii]` is only valid on functions + --> $DIR/error_statement_position.rs:13:5 + | +LL | #[eii] + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/include-macros/auxiliary/shebang-expr.rs b/tests/ui/include-macros/auxiliary/shebang-expr.rs new file mode 100644 index 0000000000000..73e92b5a889ee --- /dev/null +++ b/tests/ui/include-macros/auxiliary/shebang-expr.rs @@ -0,0 +1,3 @@ +#!/usr/bin/env my-rust-expr-evaluator + +2 * (1 + 3) diff --git a/tests/ui/include-macros/auxiliary/shebang-items.rs b/tests/ui/include-macros/auxiliary/shebang-items.rs new file mode 100644 index 0000000000000..b9011b62cc911 --- /dev/null +++ b/tests/ui/include-macros/auxiliary/shebang-items.rs @@ -0,0 +1,3 @@ +#!/usr/bin/env my-rust-script-runner + +fn main() {} diff --git a/tests/ui/include-macros/shebang-in-expr-ctxt.rs b/tests/ui/include-macros/shebang-in-expr-ctxt.rs new file mode 100644 index 0000000000000..b6d3fa9e076fd --- /dev/null +++ b/tests/ui/include-macros/shebang-in-expr-ctxt.rs @@ -0,0 +1,16 @@ +// Check that we *don't* strip shebang in files that were `include`d in an expression or +// expression statement context. +// We do that to be consistent with frontmatter (see test `frontmatter/include-in-expr-ctxt.rs`). +// While there could be niche use cases for such shebang, it seems more confusing than beneficial. + +fn main() { + // expr ctxt + _ = include!("auxiliary/shebang-expr.rs"); + //~^ ERROR non-expression macro in expression position + //~? ERROR expected `[`, found `/` + + // stmt ctxt (reuses expr expander) + include!("auxiliary/shebang-expr.rs"); + //~^ ERROR non-statement macro in statement position + //~? ERROR expected `[`, found `/` +} diff --git a/tests/ui/include-macros/shebang-in-expr-ctxt.stderr b/tests/ui/include-macros/shebang-in-expr-ctxt.stderr new file mode 100644 index 0000000000000..9e95b02a78dcb --- /dev/null +++ b/tests/ui/include-macros/shebang-in-expr-ctxt.stderr @@ -0,0 +1,33 @@ +error: expected `[`, found `/` + --> $DIR/auxiliary/shebang-expr.rs:1:3 + | +LL | #!/usr/bin/env my-rust-expr-evaluator + | ^ expected `[` + | + = note: the token sequence `#!` here looks like the start of a shebang interpreter directive but it is not + = help: if you meant this to be a shebang interpreter directive, move it to the very start of the file + +error: non-expression macro in expression position: include + --> $DIR/shebang-in-expr-ctxt.rs:8:9 + | +LL | _ = include!("auxiliary/shebang-expr.rs"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected `[`, found `/` + --> $DIR/auxiliary/shebang-expr.rs:1:3 + | +LL | #!/usr/bin/env my-rust-expr-evaluator + | ^ expected `[` + | + = note: the token sequence `#!` here looks like the start of a shebang interpreter directive but it is not + = help: if you meant this to be a shebang interpreter directive, move it to the very start of the file + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: non-statement macro in statement position: include + --> $DIR/shebang-in-expr-ctxt.rs:13:5 + | +LL | include!("auxiliary/shebang-expr.rs"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/include-macros/shebang-in-item-ctxt.rs b/tests/ui/include-macros/shebang-in-item-ctxt.rs new file mode 100644 index 0000000000000..3e0718e287f07 --- /dev/null +++ b/tests/ui/include-macros/shebang-in-item-ctxt.rs @@ -0,0 +1,4 @@ +// Ensure that we strip shebang in files `include`d in item contexts. +//@ check-pass + +include!("auxiliary/shebang-items.rs");