From 21f07b55df6e40191446db3414fc115f76c01580 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 15 Aug 2021 18:44:06 +0200 Subject: [PATCH 01/12] Fix the flock fallback implementation --- compiler/rustc_data_structures/src/flock.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_data_structures/src/flock.rs b/compiler/rustc_data_structures/src/flock.rs index 4f5d8d7ea48ba..293ef4caac400 100644 --- a/compiler/rustc_data_structures/src/flock.rs +++ b/compiler/rustc_data_structures/src/flock.rs @@ -222,6 +222,10 @@ cfg_if! { let msg = "file locks not supported on this platform"; Err(io::Error::new(io::ErrorKind::Other, msg)) } + + pub fn error_unsupported(_err: &io::Error) -> bool { + true + } } } } From f33f266a8a20594736b8eb7c95a4d42478bec7cb Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 15 Aug 2021 01:35:03 +0100 Subject: [PATCH 02/12] BTree: remove Ord bound from new --- library/alloc/src/collections/btree/map.rs | 13 +++----- .../alloc/src/collections/btree/map/tests.rs | 8 ++++- library/alloc/src/collections/btree/set.rs | 7 ++-- .../alloc/src/collections/btree/set/tests.rs | 8 ++++- library/alloc/tests/const_fns.rs | 32 +++---------------- 5 files changed, 24 insertions(+), 44 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 4b649e43371de..70a838a35f9d2 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -233,9 +233,7 @@ impl Clone for BTreeMap { } if self.is_empty() { - // Ideally we'd call `BTreeMap::new` here, but that has the `K: - // Ord` constraint, which this method lacks. - BTreeMap { root: None, length: 0 } + BTreeMap::new() } else { clone_subtree(self.root.as_ref().unwrap().reborrow()) // unwrap succeeds because not empty } @@ -499,10 +497,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] - pub const fn new() -> BTreeMap - where - K: Ord, - { + pub const fn new() -> BTreeMap { BTreeMap { root: None, length: 0 } } @@ -522,7 +517,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn clear(&mut self) { - *self = BTreeMap { root: None, length: 0 }; + *self = BTreeMap::new(); } /// Returns a reference to the value corresponding to the key. @@ -1957,7 +1952,7 @@ impl Hash for BTreeMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for BTreeMap { +impl Default for BTreeMap { /// Creates an empty `BTreeMap`. fn default() -> BTreeMap { BTreeMap::new() diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 17e538483431c..a99d6c49ab7b3 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1745,7 +1745,7 @@ fn test_send() { } } -#[allow(dead_code)] +#[test] fn test_ord_absence() { fn map(mut map: BTreeMap) { map.is_empty(); @@ -1784,6 +1784,12 @@ fn test_ord_absence() { fn map_clone(mut map: BTreeMap) { map.clone_from(&map.clone()); } + + #[derive(Debug, Clone)] + struct NonOrd; + map(BTreeMap::::new()); + map_debug(BTreeMap::::new()); + map_clone(BTreeMap::::default()); } #[test] diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 0c268ad32b261..ff0db22e0cc2d 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -246,10 +246,7 @@ impl BTreeSet { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] - pub const fn new() -> BTreeSet - where - T: Ord, - { + pub const fn new() -> BTreeSet { BTreeSet { map: BTreeMap::new() } } @@ -1192,7 +1189,7 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for BTreeSet { +impl Default for BTreeSet { /// Creates an empty `BTreeSet`. fn default() -> BTreeSet { BTreeSet::new() diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 5d590a26281d2..0a87ae12d61a5 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -607,7 +607,7 @@ fn test_send() { } } -#[allow(dead_code)] +#[test] fn test_ord_absence() { fn set(mut set: BTreeSet) { set.is_empty(); @@ -626,6 +626,12 @@ fn test_ord_absence() { fn set_clone(mut set: BTreeSet) { set.clone_from(&set.clone()); } + + #[derive(Debug, Clone)] + struct NonOrd; + set(BTreeSet::::new()); + set_debug(BTreeSet::::new()); + set_clone(BTreeSet::::default()); } #[test] diff --git a/library/alloc/tests/const_fns.rs b/library/alloc/tests/const_fns.rs index da58ae92e1124..f448b3eb7c300 100644 --- a/library/alloc/tests/const_fns.rs +++ b/library/alloc/tests/const_fns.rs @@ -1,29 +1,5 @@ // Test const functions in the library -use core::cmp::Ordering; - -// FIXME remove this struct once we put `K: ?const Ord` on BTreeMap::new. -#[derive(PartialEq, Eq, PartialOrd)] -pub struct MyType; - -impl const Ord for MyType { - fn cmp(&self, _: &Self) -> Ordering { - Ordering::Equal - } - - fn max(self, _: Self) -> Self { - Self - } - - fn min(self, _: Self) -> Self { - Self - } - - fn clamp(self, _: Self, _: Self) -> Self { - Self - } -} - pub const MY_VEC: Vec = Vec::new(); pub const MY_VEC2: Vec = Default::default(); @@ -32,13 +8,13 @@ pub const MY_STRING2: String = Default::default(); use std::collections::{BTreeMap, BTreeSet}; -pub const MY_BTREEMAP: BTreeMap = BTreeMap::new(); -pub const MAP: &'static BTreeMap = &MY_BTREEMAP; +pub const MY_BTREEMAP: BTreeMap = BTreeMap::new(); +pub const MAP: &'static BTreeMap = &MY_BTREEMAP; pub const MAP_LEN: usize = MAP.len(); pub const MAP_IS_EMPTY: bool = MAP.is_empty(); -pub const MY_BTREESET: BTreeSet = BTreeSet::new(); -pub const SET: &'static BTreeSet = &MY_BTREESET; +pub const MY_BTREESET: BTreeSet = BTreeSet::new(); +pub const SET: &'static BTreeSet = &MY_BTREESET; pub const SET_LEN: usize = SET.len(); pub const SET_IS_EMPTY: bool = SET.is_empty(); From 5802f60355b8b9a1eaf0c0fc193de3b9c48853df Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 25 Aug 2021 21:45:37 -0700 Subject: [PATCH 03/12] add support for clobbering xer, cr, and cr[0-7] for asm! on OpenPower/PowerPC Fixes #88315 --- compiler/rustc_codegen_llvm/src/asm.rs | 8 +++ compiler/rustc_span/src/symbol.rs | 2 + compiler/rustc_target/src/asm/mod.rs | 2 +- compiler/rustc_target/src/asm/powerpc.rs | 69 ++++++++++++++++--- .../unstable-book/src/library-features/asm.md | 4 ++ src/test/assembly/asm/powerpc-types.rs | 12 ++++ src/test/codegen/asm-powerpc-clobbers.rs | 48 +++++++++++++ 7 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 src/test/codegen/asm-powerpc-clobbers.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 4387f5301a58d..527ad1c7b0be0 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -615,6 +615,10 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + unreachable!("clobber-only") + } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { @@ -751,6 +755,10 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + unreachable!("clobber-only") + } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f788eb7d2126e..8ce2e7b06f8af 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -478,6 +478,7 @@ symbols! { core_panic_macro, cosf32, cosf64, + cr, crate_id, crate_in_paths, crate_local, @@ -1415,6 +1416,7 @@ symbols! { wreg, write_bytes, x87_reg, + xer, xmm_reg, ymm_reg, zmm_reg, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index bb24f7bb135ef..2a3591566a9c9 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -344,7 +344,7 @@ impl InlineAsmReg { Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))), Self::AArch64(_) => cb(self), Self::RiscV(_) => cb(self), - Self::PowerPC(_) => cb(self), + Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))), Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), Self::Mips(_) => cb(self), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index 42fc25c4ff565..51a4303689e67 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -7,6 +7,8 @@ def_reg_class! { reg, reg_nonzero, freg, + cr, + xer, } } @@ -44,6 +46,7 @@ impl PowerPCInlineAsmRegClass { } } Self::freg => types! { _: F32, F64; }, + Self::cr | Self::xer => &[], } } } @@ -108,6 +111,16 @@ def_regs! { f29: freg = ["f29", "fr29"], f30: freg = ["f30", "fr30"], f31: freg = ["f31", "fr31"], + cr: cr = ["cr"], + cr0: cr = ["cr0"], + cr1: cr = ["cr1"], + cr2: cr = ["cr2"], + cr3: cr = ["cr3"], + cr4: cr = ["cr4"], + cr5: cr = ["cr5"], + cr6: cr = ["cr6"], + cr7: cr = ["cr7"], + xer: xer = ["xer"], #error = ["r1", "1", "sp"] => "the stack pointer cannot be used as an operand for inline asm", #error = ["r2", "2"] => @@ -136,17 +149,55 @@ impl PowerPCInlineAsmReg { _arch: InlineAsmArch, _modifier: Option, ) -> fmt::Result { + macro_rules! do_emit { + ( + $($(($reg:ident, $value:literal)),*;)* + ) => { + out.write_str(match self { + $($(Self::$reg => $value,)*)* + }) + }; + } // Strip off the leading prefix. - if self as u32 <= Self::r28 as u32 { - let index = self as u32 - Self::r28 as u32; - write!(out, "{}", index) - } else if self as u32 >= Self::f0 as u32 && self as u32 <= Self::f31 as u32 { - let index = self as u32 - Self::f31 as u32; - write!(out, "{}", index) - } else { - unreachable!() + do_emit! { + (r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7"); + (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r14, "14"), (r15, "15"); + (r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23"); + (r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28"); + (f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7"); + (f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15"); + (f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23"); + (f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31"); + (cr, "cr"); + (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7"); + (xer, "xer"); } } - pub fn overlapping_regs(self, mut _cb: impl FnMut(PowerPCInlineAsmReg)) {} + pub fn overlapping_regs(self, mut cb: impl FnMut(PowerPCInlineAsmReg)) { + macro_rules! reg_conflicts { + ( + $( + $full:ident : $($field:ident)* + ),*; + ) => { + match self { + $( + Self::$full => { + cb(Self::$full); + $(cb(Self::$field);)* + } + $(Self::$field)|* => { + cb(Self::$full); + cb(self); + } + )* + r => cb(r), + } + }; + } + reg_conflicts! { + cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7; + } + } } diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index 220b74ca6e6e1..fd929d842c94b 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -584,6 +584,8 @@ Here is the list of currently supported register classes: | PowerPC | `reg` | `r[0-31]` | `r` | | PowerPC | `reg_nonzero` | | `r[1-31]` | `b` | | PowerPC | `freg` | `f[0-31]` | `f` | +| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | +| PowerPC | `xer` | `xer` | Only clobbers | | wasm32 | `local` | None\* | `r` | | BPF | `reg` | `r[0-10]` | `r` | | BPF | `wreg` | `w[0-10]` | `w` | @@ -637,6 +639,8 @@ Each register class has constraints on which value types they can be used with. | PowerPC | `reg` | None | `i8`, `i16`, `i32` | | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` | | PowerPC | `freg` | None | `f32`, `f64` | +| PowerPC | `cr` | N/A | Only clobbers | +| PowerPC | `xer` | N/A | Only clobbers | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | | BPF | `reg` | None | `i8` `i16` `i32` `i64` | | BPF | `wreg` | `alu32` | `i8` `i16` `i32` | diff --git a/src/test/assembly/asm/powerpc-types.rs b/src/test/assembly/asm/powerpc-types.rs index 1e263649e860a..55ca8ee836c98 100644 --- a/src/test/assembly/asm/powerpc-types.rs +++ b/src/test/assembly/asm/powerpc-types.rs @@ -194,3 +194,15 @@ check_reg!(reg_f32_f0, f32, "0", "f0", "fmr"); // CHECK: fmr 0, 0 // CHECK: #NO_APP check_reg!(reg_f64_f0, f64, "0", "f0", "fmr"); + +// CHECK-LABEL: reg_f32_f18: +// CHECK: #APP +// CHECK: fmr 18, 18 +// CHECK: #NO_APP +check_reg!(reg_f32_f18, f32, "18", "f18", "fmr"); + +// CHECK-LABEL: reg_f64_f18: +// CHECK: #APP +// CHECK: fmr 18, 18 +// CHECK: #NO_APP +check_reg!(reg_f64_f18, f64, "18", "f18", "fmr"); diff --git a/src/test/codegen/asm-powerpc-clobbers.rs b/src/test/codegen/asm-powerpc-clobbers.rs new file mode 100644 index 0000000000000..91a82c6012029 --- /dev/null +++ b/src/test/codegen/asm-powerpc-clobbers.rs @@ -0,0 +1,48 @@ +// min-llvm-version: 10.0.1 +// revisions: powerpc powerpc64 powerpc64le +//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu +//[powerpc] needs-llvm-components: powerpc +//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//[powerpc64] needs-llvm-components: powerpc +//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu +//[powerpc64le] needs-llvm-components: powerpc + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @cr_clobber +// CHECK: call void asm sideeffect "", "~{cr}"() +#[no_mangle] +pub unsafe fn cr_clobber() { + asm!("", out("cr") _, options(nostack, nomem)); +} + +// CHECK-LABEL: @cr0_clobber +// CHECK: call void asm sideeffect "", "~{cr0}"() +#[no_mangle] +pub unsafe fn cr0_clobber() { + asm!("", out("cr0") _, options(nostack, nomem)); +} + +// CHECK-LABEL: @cr5_clobber +// CHECK: call void asm sideeffect "", "~{cr5}"() +#[no_mangle] +pub unsafe fn cr5_clobber() { + asm!("", out("cr5") _, options(nostack, nomem)); +} + +// CHECK-LABEL: @xer_clobber +// CHECK: call void asm sideeffect "", "~{xer}"() +#[no_mangle] +pub unsafe fn xer_clobber() { + asm!("", out("xer") _, options(nostack, nomem)); +} From fc125a52ec3a342c91ca399cafaeb0504a253991 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Sun, 29 Aug 2021 20:08:40 -0400 Subject: [PATCH 04/12] emit specific warning to clarify that foreign items can't have no_mangle remove extra commented code Deduplicate some diagnostics code add code symbols, machine applicable suggestion clarify error message --- compiler/rustc_passes/src/check_attr.rs | 30 ++++++++++++++++ src/test/ui/extern/extern-no-mangle.rs | 30 ++++++++++++++++ src/test/ui/extern/extern-no-mangle.stderr | 42 ++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 src/test/ui/extern/extern-no-mangle.rs create mode 100644 src/test/ui/extern/extern-no-mangle.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d3dac35d2c9e5..fd438bdc9005a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1331,6 +1331,36 @@ impl CheckAttrVisitor<'tcx> { Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_mangle"); } + // FIXME: #[no_mangle] was previously allowed on non-functions/statics, this should be an error + // The error should specify that the item that is wrong is specifically a *foreign* fn/static + // otherwise the error seems odd + Target::ForeignFn | Target::ForeignStatic => { + let foreign_item_kind = match target { + Target::ForeignFn => "function", + Target::ForeignStatic => "static", + _ => unreachable!(), + }; + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build(&format!( + "`#[no_mangle]` has no effect on a foreign {}", + foreign_item_kind + )) + .warn( + "this was previously accepted by the compiler but is \ + being phased out; it will become a hard error in \ + a future release!", + ) + .span_label(*span, format!("foreign {}", foreign_item_kind)) + .note("symbol names in extern blocks are not mangled") + .span_suggestion( + attr.span, + "remove this attribute", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + }); + } _ => { // FIXME: #[no_mangle] was previously allowed on non-functions/statics and some // crates used this, so only emit a warning. diff --git a/src/test/ui/extern/extern-no-mangle.rs b/src/test/ui/extern/extern-no-mangle.rs new file mode 100644 index 0000000000000..ab7c9824af039 --- /dev/null +++ b/src/test/ui/extern/extern-no-mangle.rs @@ -0,0 +1,30 @@ +#![warn(unused_attributes)] + +// Tests that placing the #[no_mangle] attribute on a foreign fn or static emits +// a specialized warning. +// The previous warning only talks about a "function or static" but foreign fns/statics +// are also not allowed to have #[no_mangle] + +// build-pass + +extern "C" { + #[no_mangle] + //~^ WARNING `#[no_mangle]` has no effect on a foreign static + //~^^ WARNING this was previously accepted by the compiler + pub static FOO: u8; + + #[no_mangle] + //~^ WARNING `#[no_mangle]` has no effect on a foreign function + //~^^ WARNING this was previously accepted by the compiler + pub fn bar(); +} + +fn no_new_warn() { + // Should emit the generic "not a function or static" warning + #[no_mangle] + //~^ WARNING attribute should be applied to a free function, impl method or static + //~^^ WARNING this was previously accepted by the compiler + let x = 0_u8; +} + +fn main() {} diff --git a/src/test/ui/extern/extern-no-mangle.stderr b/src/test/ui/extern/extern-no-mangle.stderr new file mode 100644 index 0000000000000..b56428141141d --- /dev/null +++ b/src/test/ui/extern/extern-no-mangle.stderr @@ -0,0 +1,42 @@ +warning: attribute should be applied to a free function, impl method or static + --> $DIR/extern-no-mangle.rs:24:5 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ +... +LL | let x = 0_u8; + | ------------- not a free function, impl method or static + | +note: the lint level is defined here + --> $DIR/extern-no-mangle.rs:1:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: `#[no_mangle]` has no effect on a foreign static + --> $DIR/extern-no-mangle.rs:11:5 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute +... +LL | pub static FOO: u8; + | ------------------- foreign static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: symbol names in extern blocks are not mangled + +warning: `#[no_mangle]` has no effect on a foreign function + --> $DIR/extern-no-mangle.rs:16:5 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute +... +LL | pub fn bar(); + | ------------- foreign function + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: symbol names in extern blocks are not mangled + +warning: 3 warnings emitted + From 026322c34b2ae68af15b59df69a121209c8364f1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 30 Aug 2021 22:11:25 -0700 Subject: [PATCH 05/12] fix(rustc_typeck): produce better errors for dyn auto trait Fixes #85026 --- compiler/rustc_error_codes/src/error_codes.rs | 1 + .../src/error_codes/E0785.md | 30 +++++++++++++++++++ .../src/coherence/inherent_impls.rs | 11 +++++++ src/test/ui/coherence/issue-85026.rs | 10 +++++++ src/test/ui/coherence/issue-85026.stderr | 19 ++++++++++++ 5 files changed, 71 insertions(+) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0785.md create mode 100644 src/test/ui/coherence/issue-85026.rs create mode 100644 src/test/ui/coherence/issue-85026.stderr diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index c2e62328cb151..45d91c2047d41 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -480,6 +480,7 @@ E0781: include_str!("./error_codes/E0781.md"), E0782: include_str!("./error_codes/E0782.md"), E0783: include_str!("./error_codes/E0783.md"), E0784: include_str!("./error_codes/E0784.md"), +E0785: include_str!("./error_codes/E0785.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/compiler/rustc_error_codes/src/error_codes/E0785.md b/compiler/rustc_error_codes/src/error_codes/E0785.md new file mode 100644 index 0000000000000..b8a03cd109d87 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0785.md @@ -0,0 +1,30 @@ +An inherent `impl` was written on a dyn auto trait. + +Erroneous code example: + +```compile_fail,E0785 +#![feature(auto_traits)] + +auto trait AutoTrait {} + +impl dyn AutoTrait {} +``` + +Dyn objects allow any number of auto traits, plus at most one non-auto trait. +The non-auto trait becomes the "principal trait". + +When checking if an impl on a dyn trait is coherent, the principal trait is +normally the only one considered. Since the erroneous code has no principal +trait, it cannot be implemented at all. + +Working example: + +``` +#![feature(auto_traits)] + +trait PrincipalTrait {} + +auto trait AutoTrait {} + +impl dyn (PrincipalTrait + AutoTrait + Send) {} +``` diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 51698437a305b..05d7dfb9c8ffa 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -60,6 +60,17 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => { self.check_def_id(item, data.principal_def_id().unwrap()); } + ty::Dynamic(..) => { + struct_span_err!( + self.tcx.sess, + ty.span, + E0785, + "cannot define inherent `impl` for a dyn auto trait" + ) + .span_label(ty.span, "impl requires a principal trait") + .note("define and implement a new trait or type instead") + .emit(); + } ty::Bool => { self.check_primitive_impl( item.def_id, diff --git a/src/test/ui/coherence/issue-85026.rs b/src/test/ui/coherence/issue-85026.rs new file mode 100644 index 0000000000000..8b116545aa696 --- /dev/null +++ b/src/test/ui/coherence/issue-85026.rs @@ -0,0 +1,10 @@ +#![feature(auto_traits)] +auto trait AutoTrait {} + +// You cannot impl your own `dyn AutoTrait`. +impl dyn AutoTrait {} //~ERROR E0785 + +// You cannot impl someone else's `dyn AutoTrait` +impl dyn Unpin {} //~ERROR E0785 + +fn main() {} diff --git a/src/test/ui/coherence/issue-85026.stderr b/src/test/ui/coherence/issue-85026.stderr new file mode 100644 index 0000000000000..cf9cd52d2bfdd --- /dev/null +++ b/src/test/ui/coherence/issue-85026.stderr @@ -0,0 +1,19 @@ +error[E0785]: cannot define inherent `impl` for a dyn auto trait + --> $DIR/issue-85026.rs:5:6 + | +LL | impl dyn AutoTrait {} + | ^^^^^^^^^^^^^ impl requires a principal trait + | + = note: define and implement a new trait or type instead + +error[E0785]: cannot define inherent `impl` for a dyn auto trait + --> $DIR/issue-85026.rs:8:6 + | +LL | impl dyn Unpin {} + | ^^^^^^^^^ impl requires a principal trait + | + = note: define and implement a new trait or type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0785`. From 435cdd0f9ab2cb02bb475415279f9542efa449a1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 30 Aug 2021 22:18:55 -0700 Subject: [PATCH 06/12] Update E0785.md --- compiler/rustc_error_codes/src/error_codes/E0785.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0785.md b/compiler/rustc_error_codes/src/error_codes/E0785.md index b8a03cd109d87..373320539ef64 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0785.md +++ b/compiler/rustc_error_codes/src/error_codes/E0785.md @@ -26,5 +26,5 @@ trait PrincipalTrait {} auto trait AutoTrait {} -impl dyn (PrincipalTrait + AutoTrait + Send) {} +impl dyn PrincipalTrait + AutoTrait + Send {} ``` From 6e70678f7d93ad777297c865e35e005520a4eefb Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 31 Aug 2021 08:52:19 -0700 Subject: [PATCH 07/12] Change wording to less jaron-y "non-auto trait" Co-authored-by: Vadim Petrochenkov --- compiler/rustc_typeck/src/coherence/inherent_impls.rs | 2 +- src/test/ui/coherence/issue-85026.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 05d7dfb9c8ffa..c7be9e2123512 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -67,7 +67,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { E0785, "cannot define inherent `impl` for a dyn auto trait" ) - .span_label(ty.span, "impl requires a principal trait") + .span_label(ty.span, "impl requires at least one non-auto trait") .note("define and implement a new trait or type instead") .emit(); } diff --git a/src/test/ui/coherence/issue-85026.stderr b/src/test/ui/coherence/issue-85026.stderr index cf9cd52d2bfdd..a5da19bbfaa47 100644 --- a/src/test/ui/coherence/issue-85026.stderr +++ b/src/test/ui/coherence/issue-85026.stderr @@ -2,7 +2,7 @@ error[E0785]: cannot define inherent `impl` for a dyn auto trait --> $DIR/issue-85026.rs:5:6 | LL | impl dyn AutoTrait {} - | ^^^^^^^^^^^^^ impl requires a principal trait + | ^^^^^^^^^^^^^ impl requires at least one non-auto trait | = note: define and implement a new trait or type instead @@ -10,7 +10,7 @@ error[E0785]: cannot define inherent `impl` for a dyn auto trait --> $DIR/issue-85026.rs:8:6 | LL | impl dyn Unpin {} - | ^^^^^^^^^ impl requires a principal trait + | ^^^^^^^^^ impl requires at least one non-auto trait | = note: define and implement a new trait or type instead From 87e39ac1ec0df8c45a4441cf6bb905d7fd282354 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 23 Aug 2021 10:49:56 -0700 Subject: [PATCH 08/12] Remove bolding on associated constants Associated types don't get bolded, so it looks off to have one kind bolded and one not. --- src/librustdoc/html/render/mod.rs | 2 +- src/test/rustdoc-gui/font-weight.goml | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7704abc9a72c8..620b4cdf9da49 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -753,7 +753,7 @@ fn assoc_const( ) { write!( w, - "{}{}const {}: {}", + "{}{}const {}: {}", extra, it.visibility.print_with_space(it.def_id, cx), naive_assoc_href(it, link, cx), diff --git a/src/test/rustdoc-gui/font-weight.goml b/src/test/rustdoc-gui/font-weight.goml index 92ad92a8c3415..d8411511c5aee 100644 --- a/src/test/rustdoc-gui/font-weight.goml +++ b/src/test/rustdoc-gui/font-weight.goml @@ -13,6 +13,21 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html assert-css: (".impl-items .method", {"font-weight": "600"}, ALL) goto: file://|DOC_PATH|/lib2/trait.Trait.html + +// This is a complex selector, so here's how it works: +// +// * //*[@class='docblock type-decl'] — selects element of any tag with classes docblock and type-decl +// * /pre[@class='rust trait'] — selects immediate child with tag pre and classes rust and trait +// * /code — selects immediate child with tag code +// * /a[@class='constant'] — selects immediate child with tag a and class constant +// * //text() — selects child that is text node +// * /parent::* — selects immediate parent of the text node (the * means it can be any tag) +// +// This uses '/parent::*' as a proxy for the style of the text node. +// We can't just select the '' because intermediate tags could be added. +assert-count: ("//*[@class='docblock type-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*", 1) +assert-css: ("//*[@class='docblock type-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*", {"font-weight": "400"}) + assert-count: (".methods .type", 1) assert-css: (".methods .type", {"font-weight": "600"}) assert-count: (".methods .constant", 1) From 0e0c8aef87fe78c797a455d34e7490254f3d22b2 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 31 Aug 2021 14:11:42 -0400 Subject: [PATCH 09/12] Use the return value of readdir_r() instead of errno POSIX says: > If successful, the readdir_r() function shall return zero; otherwise, > an error number shall be returned to indicate the error. But we were previously using errno instead of the return value. This led to issue #86649. --- library/std/src/sys/unix/fs.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 6075eb5c7c58a..6d7524a733afd 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -506,7 +506,8 @@ impl Iterator for ReadDir { let mut ret = DirEntry { entry: mem::zeroed(), dir: Arc::clone(&self.inner) }; let mut entry_ptr = ptr::null_mut(); loop { - if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 { + let err = readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr); + if err != 0 { if entry_ptr.is_null() { // We encountered an error (which will be returned in this iteration), but // we also reached the end of the directory stream. The `end_of_stream` @@ -514,7 +515,7 @@ impl Iterator for ReadDir { // (instead of looping forever) self.end_of_stream = true; } - return Some(Err(Error::last_os_error())); + return Some(Err(Error::from_raw_os_error(err))); } if entry_ptr.is_null() { return None; From 753dac16abd16411e1833b35ba82cabac6997cec Mon Sep 17 00:00:00 2001 From: inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> Date: Tue, 31 Aug 2021 14:44:13 -0700 Subject: [PATCH 10/12] Stabilize `UnsafeCell::raw_get()` --- library/core/src/cell.rs | 5 ++--- library/std/src/lib.rs | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 85b43f4884760..2adf6a549e641 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1921,7 +1921,7 @@ impl UnsafeCell { } /// Gets a mutable pointer to the wrapped value. - /// The difference to [`get`] is that this function accepts a raw pointer, + /// The difference from [`get`] is that this function accepts a raw pointer, /// which is useful to avoid the creation of temporary references. /// /// The result can be cast to a pointer of any kind. @@ -1937,7 +1937,6 @@ impl UnsafeCell { /// calling `get` would require creating a reference to uninitialized data: /// /// ``` - /// #![feature(unsafe_cell_raw_get)] /// use std::cell::UnsafeCell; /// use std::mem::MaybeUninit; /// @@ -1948,7 +1947,7 @@ impl UnsafeCell { /// assert_eq!(uc.into_inner(), 5); /// ``` #[inline(always)] - #[unstable(feature = "unsafe_cell_raw_get", issue = "66358")] + #[stable(feature = "unsafe_cell_raw_get", since = "1.56.0")] pub const fn raw_get(this: *const Self) -> *mut T { // We can just cast the pointer from `UnsafeCell` to `T` because of // #[repr(transparent)]. This exploits libstd's special status, there is diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 028a066b5a130..43c7ec5fad33a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -331,7 +331,6 @@ #![feature(try_reserve)] #![feature(try_reserve_kind)] #![feature(unboxed_closures)] -#![feature(unsafe_cell_raw_get)] #![feature(unwrap_infallible)] #![feature(vec_into_raw_parts)] #![feature(vec_spare_capacity)] From 06dd4c03a08dccb86337fd7913b2002ac1877aa3 Mon Sep 17 00:00:00 2001 From: inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> Date: Tue, 31 Aug 2021 14:35:12 -0700 Subject: [PATCH 11/12] Stabilize `Iterator::intersperse()` --- library/core/src/iter/adapters/intersperse.rs | 12 ++++++------ library/core/src/iter/adapters/mod.rs | 2 +- library/core/src/iter/mod.rs | 2 +- library/core/src/iter/traits/iterator.rs | 14 ++++---------- library/core/tests/lib.rs | 1 - src/librustdoc/lib.rs | 1 - 6 files changed, 12 insertions(+), 20 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index d8bbd424cf258..bd21872e1ad4b 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -4,7 +4,7 @@ use super::Peekable; /// /// This `struct` is created by [`Iterator::intersperse`]. See its documentation /// for more information. -#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[stable(feature = "iter_intersperse", since = "1.56.0")] #[derive(Debug, Clone)] pub struct Intersperse where @@ -24,7 +24,7 @@ where } } -#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[stable(feature = "iter_intersperse", since = "1.56.0")] impl Iterator for Intersperse where I: Iterator, @@ -61,7 +61,7 @@ where /// /// This `struct` is created by [`Iterator::intersperse_with`]. See its /// documentation for more information. -#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[stable(feature = "iter_intersperse", since = "1.56.0")] pub struct IntersperseWith where I: Iterator, @@ -71,7 +71,7 @@ where needs_sep: bool, } -#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[stable(feature = "iter_intersperse", since = "1.56.0")] impl crate::fmt::Debug for IntersperseWith where I: Iterator + crate::fmt::Debug, @@ -87,7 +87,7 @@ where } } -#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[stable(feature = "iter_intersperse", since = "1.56.0")] impl crate::clone::Clone for IntersperseWith where I: Iterator + crate::clone::Clone, @@ -113,7 +113,7 @@ where } } -#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[stable(feature = "iter_intersperse", since = "1.56.0")] impl Iterator for IntersperseWith where I: Iterator, diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 056ccca1d01c9..f02d278aff5e4 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -42,7 +42,7 @@ pub use self::flatten::Flatten; #[stable(feature = "iter_copied", since = "1.36.0")] pub use self::copied::Copied; -#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[stable(feature = "iter_intersperse", since = "1.56.0")] pub use self::intersperse::{Intersperse, IntersperseWith}; #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 7fb80f954ff40..cd8a26025ffb6 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -414,7 +414,7 @@ pub use self::adapters::{ Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan, Skip, SkipWhile, Take, TakeWhile, Zip, }; -#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[stable(feature = "iter_intersperse", since = "1.56.0")] pub use self::adapters::{Intersperse, IntersperseWith}; pub(crate) use self::adapters::process_results; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 850435b53cc7e..330d3714247c5 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -535,8 +535,6 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_intersperse)] - /// /// let mut a = [0, 1, 2].iter().intersperse(&100); /// assert_eq!(a.next(), Some(&0)); // The first element from `a`. /// assert_eq!(a.next(), Some(&100)); // The separator. @@ -547,9 +545,8 @@ pub trait Iterator { /// ``` /// /// `intersperse` can be very useful to join an iterator's items using a common element: - /// ``` - /// #![feature(iter_intersperse)] /// + /// ``` /// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::(); /// assert_eq!(hello, "Hello World !"); /// ``` @@ -557,7 +554,7 @@ pub trait Iterator { /// [`Clone`]: crate::clone::Clone /// [`intersperse_with`]: Iterator::intersperse_with #[inline] - #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + #[stable(feature = "iter_intersperse", since = "1.56.0")] fn intersperse(self, separator: Self::Item) -> Intersperse where Self: Sized, @@ -582,8 +579,6 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_intersperse)] - /// /// #[derive(PartialEq, Debug)] /// struct NotClone(usize); /// @@ -600,9 +595,8 @@ pub trait Iterator { /// /// `intersperse_with` can be used in situations where the separator needs /// to be computed: - /// ``` - /// #![feature(iter_intersperse)] /// + /// ``` /// let src = ["Hello", "to", "all", "people", "!!"].iter().copied(); /// /// // The closure mutably borrows its context to generate an item. @@ -615,7 +609,7 @@ pub trait Iterator { /// [`Clone`]: crate::clone::Clone /// [`intersperse`]: Iterator::intersperse #[inline] - #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + #[stable(feature = "iter_intersperse", since = "1.56.0")] fn intersperse_with(self, separator: G) -> IntersperseWith where Self: Sized, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 13f483f19b770..7853b571be326 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -48,7 +48,6 @@ #![feature(int_log)] #![feature(iter_advance_by)] #![feature(iter_partition_in_place)] -#![feature(iter_intersperse)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] #![feature(iter_map_while)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index de32e31ca872f..b81acd1a93fc2 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -13,7 +13,6 @@ #![feature(never_type)] #![feature(once_cell)] #![feature(type_ascription)] -#![feature(iter_intersperse)] #![recursion_limit = "256"] #![warn(rustc::internal)] From 227e004d3fda91b72eef2b5e064dcbf3647dc68e Mon Sep 17 00:00:00 2001 From: inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> Date: Tue, 31 Aug 2021 16:32:01 -0700 Subject: [PATCH 12/12] Add a few tests for `UnsafeCell` --- library/core/tests/cell.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/library/core/tests/cell.rs b/library/core/tests/cell.rs index 77517879dd250..85a006c5d5bef 100644 --- a/library/core/tests/cell.rs +++ b/library/core/tests/cell.rs @@ -2,6 +2,38 @@ use core::cell::*; use core::default::Default; use std::mem::drop; +#[test] +fn smoketest_unsafe_cell() { + let mut x = UnsafeCell::new(10); + let ref_mut = &mut x; + unsafe { + // The asserts are repeated in order to ensure that `get()` + // is non-mutating. + assert_eq!(*ref_mut.get(), 10); + assert_eq!(*ref_mut.get(), 10); + *ref_mut.get_mut() += 5; + assert_eq!(*ref_mut.get(), 15); + assert_eq!(*ref_mut.get(), 15); + assert_eq!(x.into_inner(), 15); + } +} + +#[test] +fn unsafe_cell_raw_get() { + let x = UnsafeCell::new(10); + let ptr = &x as *const UnsafeCell; + unsafe { + // The asserts are repeated in order to ensure that `raw_get()` + // is non-mutating. + assert_eq!(*UnsafeCell::raw_get(ptr), 10); + assert_eq!(*UnsafeCell::raw_get(ptr), 10); + *UnsafeCell::raw_get(ptr) += 5; + assert_eq!(*UnsafeCell::raw_get(ptr), 15); + assert_eq!(*UnsafeCell::raw_get(ptr), 15); + assert_eq!(x.into_inner(), 15); + } +} + #[test] fn smoketest_cell() { let x = Cell::new(10);