diff --git a/RELEASES.md b/RELEASES.md index c1cf337ea8d2a..32d7b4add8c0a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -78,6 +78,17 @@ Stabilized APIs - [`<*const T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked) - [`<*mut T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked-1) - [`<*mut T>::as_mut_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_mut_unchecked) +- [`Vec::push_mut`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.push_mut) +- [`Vec::insert_mut`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.insert_mut) +- [`VecDeque::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.push_front_mut) +- [`VecDeque::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.push_back_mut) +- [`VecDeque::insert_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.insert_mut) +- [`LinkedList::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_front_mut) +- [`LinkedList::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_back_mut) +- [`Layout::dangling_ptr`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.dangling_ptr) +- [`Layout::repeat`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.repeat) +- [`Layout::repeat_packed`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.repeat_packed) +- [`Layout::extend_packed`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.extend_packed) These previously stable APIs are now stable in const contexts: diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 0785942d13a38..24ade7300c33b 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -140,25 +140,19 @@ impl TypedArena { /// Allocates an object in the `TypedArena`, returning a reference to it. #[inline] pub fn alloc(&self, object: T) -> &mut T { + assert!(size_of::() != 0); + if self.ptr == self.end { self.grow(1) } unsafe { - if size_of::() == 0 { - self.ptr.set(self.ptr.get().wrapping_byte_add(1)); - let ptr = ptr::NonNull::::dangling().as_ptr(); - // Don't drop the object. This `write` is equivalent to `forget`. - ptr::write(ptr, object); - &mut *ptr - } else { - let ptr = self.ptr.get(); - // Advance the pointer. - self.ptr.set(self.ptr.get().add(1)); - // Write into uninitialized memory. - ptr::write(ptr, object); - &mut *ptr - } + let ptr = self.ptr.get(); + // Advance the pointer. + self.ptr.set(self.ptr.get().add(1)); + // Write into uninitialized memory. + ptr::write(ptr, object); + &mut *ptr } } @@ -302,16 +296,10 @@ impl TypedArena { let end = self.ptr.get().addr(); // We then calculate the number of elements to be dropped in the last chunk, // which is the filled area's length. - let diff = if size_of::() == 0 { - // `T` is ZST. It can't have a drop flag, so the value here doesn't matter. We get - // the number of zero-sized values in the last and only chunk, just out of caution. - // Recall that `end` was incremented for each allocated value. - end - start - } else { - // FIXME: this should *likely* use `offset_from`, but more - // investigation is needed (including running tests in miri). - (end - start) / size_of::() - }; + assert_ne!(size_of::(), 0); + // FIXME: this should *likely* use `offset_from`, but more + // investigation is needed (including running tests in miri). + let diff = (end - start) / size_of::(); // Pass that to the `destroy` method. unsafe { last_chunk.destroy(diff); diff --git a/compiler/rustc_arena/src/tests.rs b/compiler/rustc_arena/src/tests.rs index eb9406d691b10..751ddd80408a8 100644 --- a/compiler/rustc_arena/src/tests.rs +++ b/compiler/rustc_arena/src/tests.rs @@ -22,7 +22,6 @@ impl TypedArena { if let Some(last_chunk) = chunks_borrow.last_mut() { self.clear_last_chunk(last_chunk); let len = chunks_borrow.len(); - // If `T` is ZST, code below has no effect. for mut chunk in chunks_borrow.drain(..len - 1) { chunk.destroy(chunk.entries); } @@ -117,18 +116,6 @@ fn test_noncopy() { } } -#[test] -fn test_typed_arena_zero_sized() { - let arena = TypedArena::default(); - #[cfg(not(miri))] - const N: usize = 100000; - #[cfg(miri)] - const N: usize = 1000; - for _ in 0..N { - arena.alloc(()); - } -} - #[test] fn test_typed_arena_clear() { let mut arena = TypedArena::default(); @@ -207,7 +194,8 @@ thread_local! { static DROP_COUNTER: Cell = Cell::new(0) } -struct SmallDroppable; +#[allow(unused)] +struct SmallDroppable(u8); impl Drop for SmallDroppable { fn drop(&mut self) { @@ -222,7 +210,7 @@ fn test_typed_arena_drop_small_count() { let arena: TypedArena = TypedArena::default(); for _ in 0..100 { // Allocate something with drop glue to make sure it doesn't leak. - arena.alloc(SmallDroppable); + arena.alloc(SmallDroppable(0)); } // dropping }; diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 97cfc648b7cb0..c94376c7673da 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, ty}; use rustc_span::sym; use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; -use rustc_target::spec::{Arch, BinaryFormat}; +use rustc_target::spec::{Arch, BinaryFormat, Env}; use crate::common; use crate::mir::AsmCodegenMethods; @@ -128,6 +128,8 @@ fn prefix_and_suffix<'tcx>( let is_arm = tcx.sess.target.arch == Arch::Arm; let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode); + let function_sections = + tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections); // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden @@ -218,8 +220,6 @@ fn prefix_and_suffix<'tcx>( let mut end = String::new(); match asm_binary_format { BinaryFormat::Elf => { - let section = link_section.unwrap_or_else(|| format!(".text.{asm_name}")); - let progbits = match is_arm { true => "%progbits", false => "@progbits", @@ -230,7 +230,13 @@ fn prefix_and_suffix<'tcx>( false => "@function", }; - writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); + if let Some(section) = &link_section { + writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); + } else if function_sections { + writeln!(begin, ".pushsection .text.{asm_name},\"ax\", {progbits}").unwrap(); + } else { + writeln!(begin, ".text").unwrap(); + } writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); match visibility { @@ -249,14 +255,20 @@ fn prefix_and_suffix<'tcx>( // pattern match on assembly generated by LLVM. writeln!(end, ".Lfunc_end_{asm_name}:").unwrap(); writeln!(end, ".size {asm_name}, . - {asm_name}").unwrap(); - writeln!(end, ".popsection").unwrap(); + if link_section.is_some() || function_sections { + writeln!(end, ".popsection").unwrap(); + } if !arch_suffix.is_empty() { writeln!(end, "{}", arch_suffix).unwrap(); } } BinaryFormat::MachO => { - let section = link_section.unwrap_or_else(|| "__TEXT,__text".to_string()); - writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap(); + // NOTE: LLVM ignores `-Zfunction-sections` on macos. Instead the Mach-O symbol + // subsection splitting feature is used, which can be enabled with the + // `.subsections_via_symbols` global directive. LLVM already enables this directive. + if let Some(section) = &link_section { + writeln!(begin, ".pushsection {section},regular,pure_instructions").unwrap(); + } writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); match visibility { @@ -267,7 +279,9 @@ fn prefix_and_suffix<'tcx>( writeln!(end).unwrap(); writeln!(end, ".Lfunc_end_{asm_name}:").unwrap(); - writeln!(end, ".popsection").unwrap(); + if link_section.is_some() { + writeln!(end, ".popsection").unwrap(); + } if !arch_suffix.is_empty() { writeln!(end, "{}", arch_suffix).unwrap(); } @@ -278,8 +292,30 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".type 32").unwrap(); writeln!(begin, ".endef").unwrap(); - let section = link_section.unwrap_or_else(|| format!(".text.{asm_name}")); - writeln!(begin, ".pushsection {},\"xr\"", section).unwrap(); + if let Some(section) = &link_section { + writeln!(begin, ".section {section},\"xr\"").unwrap() + } else if !function_sections { + // Function sections are enabled by default on MSVC and windows-gnullvm, + // but disabled by default on GNU. + writeln!(begin, ".text").unwrap(); + } else { + // LLVM uses an extension to the section directive to support defining multiple + // sections with the same name and comdat. It adds `unique,` at the end of the + // `.section` directive. We have no way of generating that unique ID here, so don't + // emit it. + // + // See https://llvm.org/docs/Extensions.html#id2. + match &tcx.sess.target.options.env { + Env::Gnu => { + writeln!(begin, ".section .text${asm_name},\"xr\",one_only,{asm_name}") + .unwrap(); + } + Env::Msvc => { + writeln!(begin, ".section .text,\"xr\",one_only,{asm_name}").unwrap(); + } + other => bug!("invalid coff env {other:?}"), + } + } write_linkage(&mut begin).unwrap(); writeln!(begin, ".balign {align_bytes}").unwrap(); writeln!(begin, "{asm_name}:").unwrap(); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8af8f40d69f56..8007dc1203959 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -5559,7 +5559,8 @@ declare_lint! { /// /// ### Example /// - /// ```rust + #[cfg_attr(bootstrap, doc = "```rust")] + #[cfg_attr(not(bootstrap), doc = "```rust,compile_fail")] /// // Using `...` in non-foreign function definitions is unstable, however stability is /// // currently only checked after attributes are expanded, so using `#[cfg(false)]` here will /// // allow this to compile on stable Rust. @@ -5567,7 +5568,7 @@ declare_lint! { /// fn foo(...) { /// /// } - /// ``` + #[doc = "```"] /// /// {{produces}} /// @@ -5591,11 +5592,11 @@ declare_lint! { /// /// [future-incompatible]: ../index.md#future-incompatible-lints pub VARARGS_WITHOUT_PATTERN, - Warn, + Deny, "detects usage of `...` arguments without a pattern in non-foreign items", @future_incompatible = FutureIncompatibleInfo { reason: fcw!(FutureReleaseError #145544), - report_in_deps: false, + report_in_deps: true, }; } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 969d654941800..f04b4873f395c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -508,8 +508,21 @@ impl<'tcx> SizeSkeleton<'tcx> { } } - // Pattern types are always the same size as their base. - ty::Pat(base, _) => SizeSkeleton::compute(base, tcx, typing_env), + ty::Pat(base, pat) => { + // Pattern types are always the same size as their base. + let base = SizeSkeleton::compute(base, tcx, typing_env); + match *pat { + ty::PatternKind::Range { .. } | ty::PatternKind::Or(_) => base, + // But in the case of `!null` patterns we need to note that in the + // raw pointer. + ty::PatternKind::NotNull => match base? { + SizeSkeleton::Known(..) | SizeSkeleton::Generic(_) => base, + SizeSkeleton::Pointer { non_zero: _, tail } => { + Ok(SizeSkeleton::Pointer { non_zero: true, tail }) + } + }, + } + } _ => Err(err), } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5fa5c7b0519ac..501420bdc88fc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -235,7 +235,8 @@ fn generate_item_with_correct_attrs( attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline)); is_inline = is_inline || import_is_inline; } - add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None); + let keep_target_cfg = is_inline || matches!(kind, ItemKind::TypeAliasItem(..)); + add_without_unwanted_attributes(&mut attrs, target_attrs, keep_target_cfg, None); attrs } else { // We only keep the item's attributes. diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 2fa680a8e2334..e8645e00e1852 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -449,6 +449,16 @@ impl Rustc { self.cmd.arg("-Zcodegen-source-order"); self } + + /// Specify `-Z function-sections={yes, no}`. + pub fn function_sections(&mut self, enable: bool) -> &mut Self { + let flag = match enable { + true => "-Zfunction-sections=yes", + false => "-Zfunction-sections=no", + }; + self.cmd.arg(flag); + self + } } /// Query the sysroot path corresponding `rustc --print=sysroot`. diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs index b5c84ede8f063..a782ab5310e34 100644 --- a/tests/codegen-llvm/naked-fn/naked-functions.rs +++ b/tests/codegen-llvm/naked-fn/naked-functions.rs @@ -1,12 +1,21 @@ +// ignore-tidy-linelength +// //@ add-minicore -//@ revisions: linux win_x86 win_i686 macos thumb +//@ revisions: linux linux_no_function_sections macos thumb +//@ revisions: win_x86_msvc win_x86_gnu win_i686_gnu win_x86_gnu_function_sections // //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 -//@[win_x86] compile-flags: --target x86_64-pc-windows-gnu -//@[win_x86] needs-llvm-components: x86 -//@[win_i686] compile-flags: --target i686-pc-windows-gnu -//@[win_i686] needs-llvm-components: x86 +//@[linux_no_function_sections] compile-flags: --target x86_64-unknown-linux-gnu -Zfunction-sections=false +//@[linux_no_function_sections] needs-llvm-components: x86 +//@[win_x86_gnu] compile-flags: --target x86_64-pc-windows-gnu +//@[win_x86_gnu] needs-llvm-components: x86 +//@[win_x86_gnu_function_sections] compile-flags: --target x86_64-pc-windows-gnu -Zfunction-sections +//@[win_x86_gnu_function_sections] needs-llvm-components: x86 +//@[win_x86_msvc] compile-flags: --target x86_64-pc-windows-msvc +//@[win_x86_msvc] needs-llvm-components: x86 +//@[win_i686_gnu] compile-flags: --target i686-pc-windows-gnu +//@[win_i686_gnu] needs-llvm-components: x86 //@[macos] compile-flags: --target aarch64-apple-darwin //@[macos] needs-llvm-components: aarch64 //@[thumb] compile-flags: --target thumbv7em-none-eabi @@ -19,15 +28,22 @@ extern crate minicore; use minicore::*; -// linux,win_x86,win_i686: .intel_syntax +// linux,win_x86_gnu,win_i686_gnu: .intel_syntax // // linux: .pushsection .text.naked_empty,\22ax\22, @progbits -// macos: .pushsection __TEXT,__text,regular,pure_instructions +// linux_no_function_sections: .text +// macos-NOT: .pushsection +// +// win_x86_msvc: .section .text,\22xr\22,one_only,naked_empty +// win_x86_gnu_function_sections: .section .text$naked_empty,\22xr\22,one_only,naked_empty +// win_x86_gnu-NOT: .section +// win_i686_gnu-NOT: .section +// // thumb: .pushsection .text.naked_empty,\22ax\22, %progbits // // linux, macos, thumb: .balign 4 // -// linux,thumb: .globl naked_empty +// linux,win_x86_gnu,thumb: .globl naked_empty // macos: .globl _naked_empty // // CHECK-NOT: .private_extern @@ -35,12 +51,12 @@ use minicore::*; // // linux: .type naked_empty, @function // -// win_x86: .def naked_empty -// win_i686: .def _naked_empty +// win_x86_msvc,win_x86_gnu: .def naked_empty +// win_i686_gnu: .def _naked_empty // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // // win_x86: .pushsection .text.naked_empty,\22xr\22 // win_i686: .pushsection .text._naked_empty,\22xr\22 @@ -56,10 +72,11 @@ use minicore::*; // // CHECK-LABEL: naked_empty: // -// linux,macos,win_x86,win_x86: ret +// linux,macos,win_x86_msvc,win_x86_gnu,win_i686_gnu: ret // thumb: bx lr // -// linux,macos,thumb: .popsection +// linux,windows,win_x86_msvc,thumb: .popsection +// win_x86_gnu-NOT,win_i686_gnu-NOT: .popsection // // thumb: .thumb // @@ -78,15 +95,22 @@ pub extern "C" fn naked_empty() { } } -// linux,win_x86,win_i686: .intel_syntax +// linux,win_x86_gnu,win_i686_gnu,win_x86_msvc: .intel_syntax // // linux: .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits -// macos: .pushsection __TEXT,__text,regular,pure_instructions +// linux_no_function_sections: .text +// macos-NOT: .pushsection +// +// win_x86_msvc: .section .text,\22xr\22,one_only,naked_with_args_and_return +// win_x86_gnu_function_sections: .section .text$naked_with_args_and_return,\22xr\22,one_only,naked_with_args_and_return +// win_x86_gnu-NOT: .section +// win_i686_gnu-NOT: .section +// // thumb: .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits // // linux, macos, thumb: .balign 4 // -// linux,thumb: .globl naked_with_args_and_return +// linux,win_x86_gnu,win_x86_msvc,win_i686_gnu,thumb: .globl naked_with_args_and_return // macos: .globl _naked_with_args_and_return // // CHECK-NOT: .private_extern @@ -94,12 +118,12 @@ pub extern "C" fn naked_empty() { // // linux: .type naked_with_args_and_return, @function // -// win_x86: .def naked_with_args_and_return -// win_i686: .def _naked_with_args_and_return +// win_x86_msvc,win_x86_gnu: .def naked_with_args_and_return +// win_i686_gnu: .def _naked_with_args_and_return // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // // win_x86: .pushsection .text.naked_with_args_and_return,\22xr\22 // win_i686: .pushsection .text._naked_with_args_and_return,\22xr\22 @@ -115,14 +139,15 @@ pub extern "C" fn naked_empty() { // // CHECK-LABEL: naked_with_args_and_return: // -// linux, win_x86,win_i686: lea rax, [rdi + rsi] +// linux,win_x86_msvc,win_x86_gnu,win_i686_gnu: lea rax, [rdi + rsi] // macos: add x0, x0, x1 // thumb: adds r0, r0, r1 // -// linux,macos,win_x86,win_i686: ret +// linux,macos,win_x86_msvc,win_x86_gnu,win_i686_gnu: ret // thumb: bx lr // -// linux,macos,thumb: .popsection +// linux,windows,win_x86_msvc,thumb: .popsection +// win_x86_gnu-NOT,win_i686_gnu-NOT: .popsection // // thumb: .thumb // @@ -144,9 +169,10 @@ pub extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize { } } -// linux: .pushsection .text.some_different_name,\22ax\22, @progbits +// linux,linux_no_function_sections: .pushsection .text.some_different_name,\22ax\22, @progbits // macos: .pushsection .text.some_different_name,regular,pure_instructions -// win_x86,win_i686: .pushsection .text.some_different_name,\22xr\22 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .section .text.some_different_name,\22xr\22 +// win_x86_gnu_function_sections: .section .text.some_different_name,\22xr\22 // thumb: .pushsection .text.some_different_name,\22ax\22, %progbits // CHECK-LABEL: test_link_section: #[no_mangle] @@ -163,15 +189,15 @@ pub extern "C" fn test_link_section() { } } -// win_x86: .def fastcall_cc -// win_i686: .def @fastcall_cc@4 +// win_x86_msvc,win_x86_gnu: .def fastcall_cc +// win_i686_gnu: .def @fastcall_cc@4 // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // -// win_x86-LABEL: fastcall_cc: -// win_i686-LABEL: @fastcall_cc@4: +// win_x86_msvc-LABEL,win_x86_gnu-LABEL: fastcall_cc: +// win_i686_gnu-LABEL: @fastcall_cc@4: #[cfg(target_os = "windows")] #[no_mangle] #[unsafe(naked)] diff --git a/tests/run-make/naked-dead-code-elimination/main.rs b/tests/run-make/naked-dead-code-elimination/main.rs new file mode 100644 index 0000000000000..83da62d314587 --- /dev/null +++ b/tests/run-make/naked-dead-code-elimination/main.rs @@ -0,0 +1,42 @@ +#![feature(cfg_target_object_format)] +use std::arch::naked_asm; + +#[unsafe(naked)] +#[unsafe(no_mangle)] +extern "C" fn used() { + naked_asm!("ret") +} + +#[unsafe(no_mangle)] +extern "C" fn unused_clothed() -> i32 { + 42 +} + +#[unsafe(naked)] +#[unsafe(no_mangle)] +extern "C" fn unused() { + naked_asm!("ret") +} + +#[unsafe(naked)] +#[unsafe(link_section = cfg_select!( + target_object_format = "mach-o" => "__TEXT,foobar", + _ => ".foobar", +))] +#[unsafe(no_mangle)] +extern "C" fn unused_link_section() { + naked_asm!("ret") +} + +#[unsafe(link_section = cfg_select!( + target_object_format = "mach-o" => "__TEXT,baz", + _ => ".baz", +))] +#[unsafe(no_mangle)] +extern "C" fn unused_link_section_clothed() -> i32 { + 43 +} + +fn main() { + used(); +} diff --git a/tests/run-make/naked-dead-code-elimination/rmake.rs b/tests/run-make/naked-dead-code-elimination/rmake.rs new file mode 100644 index 0000000000000..a29212084b127 --- /dev/null +++ b/tests/run-make/naked-dead-code-elimination/rmake.rs @@ -0,0 +1,22 @@ +//@ needs-asm-support + +use run_make_support::symbols::object_contains_any_symbol; +use run_make_support::{bin_name, rustc}; + +fn main() { + rustc().input("main.rs").opt().function_sections(true).run(); + + let bin = bin_name("main"); + + // Check that the naked symbol is eliminated when the "clothed" one is. + + assert_eq!( + object_contains_any_symbol(&bin, &["unused_clothed"]), + object_contains_any_symbol(&bin, &["unused"]) + ); + + assert_eq!( + object_contains_any_symbol(&bin, &["unused_link_section_clothed"]), + object_contains_any_symbol(&bin, &["unused_link_section"]) + ); +} diff --git a/tests/rustdoc-html/reexport/type-alias-reexport.rs b/tests/rustdoc-html/reexport/type-alias-reexport.rs new file mode 100644 index 0000000000000..34e2d7208f88d --- /dev/null +++ b/tests/rustdoc-html/reexport/type-alias-reexport.rs @@ -0,0 +1,32 @@ +// Regression test for . +// This test ensures that auto-generated and explicit `doc(cfg)` attributes are correctly +// preserved for locally re-exported type aliases. + +#![crate_name = "foo"] +#![feature(doc_cfg)] + +mod inner { + #[cfg(target_os = "linux")] + pub type One = u32; + + #[doc(cfg(target_os = "linux"))] + pub type Two = u32; +} + +//@ has 'foo/index.html' +// There should be two items in the type aliases table. +//@ count - '//*[@class="item-table"]/dt' 2 +// Both of them should have the portability badge in the module index. +//@ count - '//*[@class="item-table"]/dt/*[@class="stab portability"]' 2 + +//@ has 'foo/type.One.html' +// Check that the individual type page has the portability badge. +//@ count - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' 1 +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' 'Linux' + +//@ has 'foo/type.Two.html' +// Check the explicit doc(cfg) type page as well. +//@ count - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' 1 +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' 'Linux' + +pub use self::inner::{One, Two}; diff --git a/tests/ui/c-variadic/parse-errors.e2015.stderr b/tests/ui/c-variadic/parse-errors.e2015.stderr index de9362c4380de..e4939cb4b0e91 100644 --- a/tests/ui/c-variadic/parse-errors.e2015.stderr +++ b/tests/ui/c-variadic/parse-errors.e2015.stderr @@ -44,3 +44,60 @@ LL | unsafe extern "C" fn f(_: ...) {} error: aborting due to 3 previous errors +Future incompatibility report: Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:11:28 + | +LL | unsafe extern "C" fn f(...) { + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) { + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:14:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:20:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + diff --git a/tests/ui/c-variadic/parse-errors.e2018.stderr b/tests/ui/c-variadic/parse-errors.e2018.stderr index a7d5f79bf1339..eac0f6f07311a 100644 --- a/tests/ui/c-variadic/parse-errors.e2018.stderr +++ b/tests/ui/c-variadic/parse-errors.e2018.stderr @@ -57,3 +57,79 @@ LL | unsafe extern "C" fn f(_: ...) {} error: aborting due to 4 previous errors +Future incompatibility report: Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:11:28 + | +LL | unsafe extern "C" fn f(...) { + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) { + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:14:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:20:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:26:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + diff --git a/tests/ui/thir-print/c-variadic.stderr b/tests/ui/thir-print/c-variadic.stderr new file mode 100644 index 0000000000000..a4050695944d4 --- /dev/null +++ b/tests/ui/thir-print/c-variadic.stderr @@ -0,0 +1,12 @@ +Future incompatibility report: Future breakage diagnostic: +warning: missing pattern for `...` argument + --> $DIR/c-variadic.rs:7:34 + | +LL | unsafe extern "C" fn foo(_: i32, ...) {} + | ^^^ + | +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn foo(_: i32, _: ...) {} + | ++ + diff --git a/tests/ui/transmute/raw-ptr-non-null.rs b/tests/ui/transmute/raw-ptr-non-null.rs new file mode 100644 index 0000000000000..af518095b3fbd --- /dev/null +++ b/tests/ui/transmute/raw-ptr-non-null.rs @@ -0,0 +1,11 @@ +//! After the use of pattern types inside `NonNull`, +//! transmuting between a niche optimized enum wrapping a +//! generic `NonNull` and raw pointers stopped working. +//@ check-pass + +use std::ptr::NonNull; +pub const fn is_null<'a, T: ?Sized>(ptr: *const T) -> bool { + unsafe { matches!(core::mem::transmute::<*const T, Option>>(ptr), None) } +} + +fn main() {}