diff --git a/.mailmap b/.mailmap index 4a3e39831e8a2..3fc567081c1ff 100644 --- a/.mailmap +++ b/.mailmap @@ -569,6 +569,7 @@ Philipp Matthias Schäfer phosphorus Pierre Krieger pierwill <19642016+pierwill@users.noreply.github.com> +Pieter-Louis Schoeman <127837395+P8L1@users.noreply.github.com> Pietro Albini Pietro Albini Pradyumna Rahul diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index f83433c2bd503..2ba7e026461f3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -563,8 +563,8 @@ pub(crate) fn reborrow_info<'tcx>( ) .is_ok() { - // Field implements Reborrow. - return Ok(()); + // Field implements Reborrow, check remaining fields. + continue; } // Field does not implement Reborrow: it must be Copy. diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index ed8081ea887f7..886bcc8c21823 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -171,7 +171,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .inspect(|vid| { let origin = self.float_var_origin(*vid); // Show the entire literal in the suggestion to make it clearer. - let literal = self.tcx.sess.source_map().span_to_snippet(origin.span).ok(); + let mut literal = self.tcx.sess.source_map().span_to_snippet(origin.span).ok(); + // A `.` at the end of the literal is no longer necessary if `f32` is explicitly specified + if let Some(ref mut literal) = literal + && literal.ends_with('.') + { + literal.pop(); + } self.tcx.emit_node_span_lint( FLOAT_LITERAL_F32_FALLBACK, origin.lint_id.unwrap_or(CRATE_HIR_ID), diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 7b41023ff31bf..5fe5464ab2cdd 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -144,6 +144,7 @@ #![feature(ptr_metadata)] #![feature(rev_into_inner)] #![feature(set_ptr_value)] +#![feature(share_trait)] #![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] #![feature(slice_index_methods)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 2905170d22a76..8150767339e18 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -245,7 +245,7 @@ use core::any::Any; use core::cell::{Cell, CloneFromCell}; #[cfg(not(no_global_oom_handling))] use core::clone::TrivialClone; -use core::clone::{CloneToUninit, UseCloned}; +use core::clone::{CloneToUninit, Share, UseCloned}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; @@ -2525,6 +2525,9 @@ impl Clone for Rc { #[unstable(feature = "ergonomic_clones", issue = "132290")] impl UseCloned for Rc {} +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for Rc {} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for Rc { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 229fcd2b429cf..17476a4e2b1e7 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -12,7 +12,7 @@ use core::any::Any; use core::cell::CloneFromCell; #[cfg(not(no_global_oom_handling))] use core::clone::TrivialClone; -use core::clone::{CloneToUninit, UseCloned}; +use core::clone::{CloneToUninit, Share, UseCloned}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; @@ -2436,6 +2436,9 @@ impl Clone for Arc { #[unstable(feature = "ergonomic_clones", issue = "132290")] impl UseCloned for Arc {} +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for Arc {} + #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Arc { type Target = T; diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index f2fa6fd0ca3e9..0c3e90b78103a 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -290,6 +290,90 @@ pub macro Clone($item:item) { /* compiler built-in */ } +/// A trait for types whose [`Clone`] operation creates another alias to the same +/// logical resource or shared state. +/// +/// `Share` marks types where cloning creates another handle, reference, or alias +/// to the same logical resource or shared state, rather than an independent owned +/// value. The distinction is semantic, not cost-based: implementing `Share` does +/// not merely mean that cloning is cheap, constant-time, allocation-free, or +/// convenient. +/// +/// Calling [`share`](Share::share) is equivalent to calling [`clone`](Clone::clone) +/// for implementors, but communicates that the resulting value aliases the same +/// underlying resource. +/// +/// Shared references, `Rc`, `Arc`, `Sender`, and `SyncSender` are +/// examples of types that can be shared this way. Types such as `Vec`, +/// `String`, and `Box` are not `Share` even though they implement `Clone`, +/// because cloning them creates another owned value rather than another handle +/// to the same logical resource. +/// +/// # Examples +/// +/// ``` +/// #![feature(share_trait)] +/// +/// use std::cell::Cell; +/// use std::clone::Share; +/// use std::rc::Rc; +/// use std::sync::{ +/// Arc, +/// atomic::{AtomicUsize, Ordering}, +/// }; +/// +/// let value = 1; +/// let reference = &value; +/// assert!(std::ptr::eq(reference, reference.share())); +/// +/// let rc = Rc::new(Cell::new(2)); +/// let shared_rc = rc.share(); +/// assert!(Rc::ptr_eq(&rc, &shared_rc)); +/// shared_rc.set(3); +/// assert_eq!(rc.get(), 3); +/// +/// let arc = Arc::new(AtomicUsize::new(4)); +/// let shared_arc = arc.share(); +/// assert!(Arc::ptr_eq(&arc, &shared_arc)); +/// shared_arc.store(5, Ordering::Relaxed); +/// assert_eq!(arc.load(Ordering::Relaxed), 5); +/// ``` +/// +/// ``` +/// #![feature(share_trait)] +/// +/// use std::clone::Share; +/// use std::sync::mpsc::{channel, sync_channel}; +/// +/// let (sender, receiver) = channel(); +/// let shared_sender = sender.share(); +/// sender.send(1).unwrap(); +/// shared_sender.send(2).unwrap(); +/// +/// let mut received = [receiver.recv().unwrap(), receiver.recv().unwrap()]; +/// received.sort(); +/// assert_eq!(received, [1, 2]); +/// +/// let (sync_sender, sync_receiver) = sync_channel(2); +/// let shared_sync_sender = sync_sender.share(); +/// sync_sender.send(3).unwrap(); +/// shared_sync_sender.send(4).unwrap(); +/// +/// let mut received = [sync_receiver.recv().unwrap(), sync_receiver.recv().unwrap()]; +/// received.sort(); +/// assert_eq!(received, [3, 4]); +/// ``` +#[unstable(feature = "share_trait", issue = "156756")] +pub trait Share: Clone { + /// Creates another alias to the same underlying resource or shared state. + /// + /// This is equivalent to calling [`Clone::clone`]. + #[unstable(feature = "share_trait", issue = "156756")] + fn share(&self) -> Self { + Clone::clone(self) + } +} + /// Trait for objects whose [`Clone`] impl is lightweight (e.g. reference-counted) /// /// Cloning an object implementing this trait should in general: @@ -601,7 +685,7 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr { /// are implemented in `traits::SelectionContext::copy_clone_conditions()` /// in `rustc_trait_selection`. mod impls { - use super::TrivialClone; + use super::{Share, TrivialClone}; use crate::marker::PointeeSized; macro_rules! impl_clone { @@ -689,6 +773,9 @@ mod impls { #[rustc_const_unstable(feature = "const_clone", issue = "142757")] unsafe impl const TrivialClone for &T {} + #[unstable(feature = "share_trait", issue = "156756")] + impl Share for &T {} + /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] impl !Clone for &mut T {} diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index d381402b469f4..cd1987aa959dd 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -33,6 +33,7 @@ pub mod consts { pub const TAU: f128 = 6.28318530717958647692528676655900576839433879875021164194989_f128; /// The golden ratio (φ) + #[doc(alias = "phi")] #[unstable(feature = "f128", issue = "116909")] pub const GOLDEN_RATIO: f128 = 1.61803398874989484820458683436563811772030917980576286213545_f128; diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index c26ae17d870cc..ef8eb3c0b57a0 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -35,6 +35,7 @@ pub mod consts { pub const TAU: f16 = 6.28318530717958647692528676655900577_f16; /// The golden ratio (φ) + #[doc(alias = "phi")] #[unstable(feature = "f16", issue = "116909")] pub const GOLDEN_RATIO: f16 = 1.618033988749894848204586834365638118_f16; diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 24c97a6491c11..2a7506f198589 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -292,6 +292,7 @@ pub mod consts { pub const TAU: f32 = 6.28318530717958647692528676655900577_f32; /// The golden ratio (φ) + #[doc(alias = "phi")] #[stable(feature = "euler_gamma_golden_ratio", since = "1.94.0")] pub const GOLDEN_RATIO: f32 = 1.618033988749894848204586834365638118_f32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index be045033a3553..8b77a3b7b0bde 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -292,6 +292,7 @@ pub mod consts { pub const TAU: f64 = 6.28318530717958647692528676655900577_f64; /// The golden ratio (φ) + #[doc(alias = "phi")] #[stable(feature = "euler_gamma_golden_ratio", since = "1.94.0")] pub const GOLDEN_RATIO: f64 = 1.618033988749894848204586834365638118_f64; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8b863b07ce5d9..cb0f8edb7b852 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -369,6 +369,7 @@ #![feature(random)] #![feature(raw_os_error_ty)] #![feature(seek_io_take_position)] +#![feature(share_trait)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_range)] diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index 8c40f07f0d17d..b74f84ff465c0 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -142,6 +142,8 @@ // not exposed publicly, but if you are curious about the implementation, // that's where everything is. +use core::clone::Share; + use crate::sync::mpmc; use crate::time::{Duration, Instant}; use crate::{error, fmt}; @@ -645,6 +647,9 @@ impl Clone for Sender { } } +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for Sender {} + #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for Sender { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -774,6 +779,9 @@ impl Clone for SyncSender { } } +#[unstable(feature = "share_trait", issue = "156756")] +impl Share for SyncSender {} + #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for SyncSender { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/tests/debuginfo/path.rs b/tests/debuginfo/path.rs index 27b518fd89751..2fffadd8510ce 100644 --- a/tests/debuginfo/path.rs +++ b/tests/debuginfo/path.rs @@ -8,12 +8,8 @@ //@ lldb-command:print pathbuf //@ lldb-check:[...] "/some/path" { inner = "/some/path" { inner = { inner = size=10 { [0] = '/' [1] = 's' [2] = 'o' [3] = 'm' [4] = 'e' [5] = '/' [6] = 'p' [7] = 'a' [8] = 't' [9] = 'h' } } } } -//@ lldb-command:po pathbuf -//@ lldb-check:"/some/path" //@ lldb-command:print path //@ lldb-check:[...] "/some/path" { data_ptr = [...] length = 10 } -//@ lldb-command:po path -//@ lldb-check:"/some/path" use std::path::Path; diff --git a/tests/ui/README.md b/tests/ui/README.md index 39402f78bb5ec..386e77ae2bd3d 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1244,6 +1244,10 @@ In this directory, multiple crates are compiled, but some of them have `inline` Tests on name shadowing. +## `tests/ui/share-trait` + +Tests for the unstable `Share` trait. + ## `tests/ui/shell-argfiles/`: `-Z shell-argfiles` command line flag The `-Zshell-argfiles` compiler flag allows argfiles to be parsed using POSIX "shell-style" quoting. When enabled, the compiler will use shlex to parse the arguments from argfiles specified with `@shell:`. diff --git a/tests/ui/float/f32-into-f32.next-solver.fixed b/tests/ui/float/f32-into-f32.next-solver.fixed index a8d56f4428b91..6bc04ff757eef 100644 --- a/tests/ui/float/f32-into-f32.next-solver.fixed +++ b/tests/ui/float/f32-into-f32.next-solver.fixed @@ -15,6 +15,9 @@ fn main() { foo(1e5_f32); //~^ WARN falling back to `f32` //~| WARN this was previously accepted + foo(0_f32); + //~^ WARN falling back to `f32` + //~| WARN this was previously accepted foo(4f32); // no warning let x = -4.0_f32; //~^ WARN falling back to `f32` diff --git a/tests/ui/float/f32-into-f32.next-solver.stderr b/tests/ui/float/f32-into-f32.next-solver.stderr index fc88f9d2c7f3c..1384f73f09689 100644 --- a/tests/ui/float/f32-into-f32.next-solver.stderr +++ b/tests/ui/float/f32-into-f32.next-solver.stderr @@ -27,7 +27,16 @@ LL | foo(1e5); = note: for more information, see issue #154024 warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:19:14 + --> $DIR/f32-into-f32.rs:18:9 + | +LL | foo(0.); + | ^^ help: explicitly specify the type as `f32`: `0_f32` + | + = 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 #154024 + +warning: falling back to `f32` as the trait bound `f32: From` is not satisfied + --> $DIR/f32-into-f32.rs:22:14 | LL | let x = -4.0; | ^^^ help: explicitly specify the type as `f32`: `4.0_f32` @@ -35,5 +44,5 @@ LL | let x = -4.0; = 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 #154024 -warning: 4 warnings emitted +warning: 5 warnings emitted diff --git a/tests/ui/float/f32-into-f32.old-solver.fixed b/tests/ui/float/f32-into-f32.old-solver.fixed index a8d56f4428b91..6bc04ff757eef 100644 --- a/tests/ui/float/f32-into-f32.old-solver.fixed +++ b/tests/ui/float/f32-into-f32.old-solver.fixed @@ -15,6 +15,9 @@ fn main() { foo(1e5_f32); //~^ WARN falling back to `f32` //~| WARN this was previously accepted + foo(0_f32); + //~^ WARN falling back to `f32` + //~| WARN this was previously accepted foo(4f32); // no warning let x = -4.0_f32; //~^ WARN falling back to `f32` diff --git a/tests/ui/float/f32-into-f32.old-solver.stderr b/tests/ui/float/f32-into-f32.old-solver.stderr index fc88f9d2c7f3c..1384f73f09689 100644 --- a/tests/ui/float/f32-into-f32.old-solver.stderr +++ b/tests/ui/float/f32-into-f32.old-solver.stderr @@ -27,7 +27,16 @@ LL | foo(1e5); = note: for more information, see issue #154024 warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:19:14 + --> $DIR/f32-into-f32.rs:18:9 + | +LL | foo(0.); + | ^^ help: explicitly specify the type as `f32`: `0_f32` + | + = 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 #154024 + +warning: falling back to `f32` as the trait bound `f32: From` is not satisfied + --> $DIR/f32-into-f32.rs:22:14 | LL | let x = -4.0; | ^^^ help: explicitly specify the type as `f32`: `4.0_f32` @@ -35,5 +44,5 @@ LL | let x = -4.0; = 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 #154024 -warning: 4 warnings emitted +warning: 5 warnings emitted diff --git a/tests/ui/float/f32-into-f32.rs b/tests/ui/float/f32-into-f32.rs index b55023453b7e0..3dbdd20bd3098 100644 --- a/tests/ui/float/f32-into-f32.rs +++ b/tests/ui/float/f32-into-f32.rs @@ -15,6 +15,9 @@ fn main() { foo(1e5); //~^ WARN falling back to `f32` //~| WARN this was previously accepted + foo(0.); + //~^ WARN falling back to `f32` + //~| WARN this was previously accepted foo(4f32); // no warning let x = -4.0; //~^ WARN falling back to `f32` diff --git a/tests/ui/reborrow/reborrow_multi_field_validation.rs b/tests/ui/reborrow/reborrow_multi_field_validation.rs new file mode 100644 index 0000000000000..9be4dd89f16c0 --- /dev/null +++ b/tests/ui/reborrow/reborrow_multi_field_validation.rs @@ -0,0 +1,15 @@ +#![feature(reborrow)] + +use std::marker::Reborrow; + +// Regression test: `reborrow_info` must validate ALL data fields, +// not just stop at the first Reborrow field. + +struct Bad<'a> { + first: &'a mut i32, + second: String, //~ ERROR the trait bound `String: Copy` is not satisfied +} + +impl<'a> Reborrow for Bad<'a> {} + +fn main() {} diff --git a/tests/ui/reborrow/reborrow_multi_field_validation.stderr b/tests/ui/reborrow/reborrow_multi_field_validation.stderr new file mode 100644 index 0000000000000..26d52818beeff --- /dev/null +++ b/tests/ui/reborrow/reborrow_multi_field_validation.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/reborrow_multi_field_validation.rs:10:5 + | +LL | second: String, + | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/share-trait/share-trait-arc.rs b/tests/ui/share-trait/share-trait-arc.rs new file mode 100644 index 0000000000000..1a4f421caeeb9 --- /dev/null +++ b/tests/ui/share-trait/share-trait-arc.rs @@ -0,0 +1,31 @@ +//@ run-pass + +#![feature(share_trait)] + +use std::clone::Share; +use std::sync::{Arc, Mutex}; + +trait Value { + fn get(&self) -> i32; +} + +impl Value for Mutex { + fn get(&self) -> i32 { + *self.lock().unwrap() + } +} + +fn main() { + let value = Arc::new(Mutex::new(1)); + let shared = value.share(); + + assert!(Arc::ptr_eq(&value, &shared)); + *shared.lock().unwrap() = 2; + assert_eq!(*value.lock().unwrap(), 2); + + let dyn_value: Arc = Arc::new(Mutex::new(3)); + let shared_dyn_value = dyn_value.share(); + + assert!(Arc::ptr_eq(&dyn_value, &shared_dyn_value)); + assert_eq!(shared_dyn_value.get(), 3); +} diff --git a/tests/ui/share-trait/share-trait-mpsc-sender.rs b/tests/ui/share-trait/share-trait-mpsc-sender.rs new file mode 100644 index 0000000000000..1939b10fbf43a --- /dev/null +++ b/tests/ui/share-trait/share-trait-mpsc-sender.rs @@ -0,0 +1,19 @@ +//@ run-pass + +#![feature(share_trait)] + +use std::clone::Share; +use std::sync::mpsc::channel; + +fn main() { + let (sender, receiver) = channel(); + let shared_sender = sender.share(); + + sender.send(1).unwrap(); + shared_sender.send(2).unwrap(); + + let mut received = [receiver.recv().unwrap(), receiver.recv().unwrap()]; + received.sort(); + + assert_eq!(received, [1, 2]); +} diff --git a/tests/ui/share-trait/share-trait-mpsc-sync-sender.rs b/tests/ui/share-trait/share-trait-mpsc-sync-sender.rs new file mode 100644 index 0000000000000..6b10d05324283 --- /dev/null +++ b/tests/ui/share-trait/share-trait-mpsc-sync-sender.rs @@ -0,0 +1,19 @@ +//@ run-pass + +#![feature(share_trait)] + +use std::clone::Share; +use std::sync::mpsc::sync_channel; + +fn main() { + let (sender, receiver) = sync_channel(2); + let shared_sender = sender.share(); + + sender.send(1).unwrap(); + shared_sender.send(2).unwrap(); + + let mut received = [receiver.recv().unwrap(), receiver.recv().unwrap()]; + received.sort(); + + assert_eq!(received, [1, 2]); +} diff --git a/tests/ui/share-trait/share-trait-no-feature.rs b/tests/ui/share-trait/share-trait-no-feature.rs new file mode 100644 index 0000000000000..2b4791d2eb034 --- /dev/null +++ b/tests/ui/share-trait/share-trait-no-feature.rs @@ -0,0 +1,20 @@ +use std::clone::Share; +//~^ ERROR use of unstable library feature `share_trait` + +#[derive(Clone)] +struct Alias; + +impl Share for Alias {} +//~^ ERROR use of unstable library feature `share_trait` + +fn share_generic(value: &T) -> T { + //~^ ERROR use of unstable library feature `share_trait` + value.share() + //~^ ERROR use of unstable library feature `share_trait` +} + +fn main() { + let value = Alias; + let _ = Share::share(&value); + //~^ ERROR use of unstable library feature `share_trait` +} diff --git a/tests/ui/share-trait/share-trait-no-feature.stderr b/tests/ui/share-trait/share-trait-no-feature.stderr new file mode 100644 index 0000000000000..344f5d8670f63 --- /dev/null +++ b/tests/ui/share-trait/share-trait-no-feature.stderr @@ -0,0 +1,53 @@ +error[E0658]: use of unstable library feature `share_trait` + --> $DIR/share-trait-no-feature.rs:1:5 + | +LL | use std::clone::Share; + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `share_trait` + --> $DIR/share-trait-no-feature.rs:7:6 + | +LL | impl Share for Alias {} + | ^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `share_trait` + --> $DIR/share-trait-no-feature.rs:10:21 + | +LL | fn share_generic(value: &T) -> T { + | ^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `share_trait` + --> $DIR/share-trait-no-feature.rs:18:13 + | +LL | let _ = Share::share(&value); + | ^^^^^^^^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `share_trait` + --> $DIR/share-trait-no-feature.rs:12:11 + | +LL | value.share() + | ^^^^^ + | + = note: see issue #156756 for more information + = help: add `#![feature(share_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/share-trait/share-trait-non-implementors.rs b/tests/ui/share-trait/share-trait-non-implementors.rs new file mode 100644 index 0000000000000..a53f10fb9e6b3 --- /dev/null +++ b/tests/ui/share-trait/share-trait-non-implementors.rs @@ -0,0 +1,19 @@ +#![feature(share_trait)] + +use std::clone::Share; + +fn require_share() {} + +fn main() { + require_share::<&mut i32>(); + //~^ ERROR the trait bound `&mut i32: Share` is not satisfied + + require_share::(); + //~^ ERROR the trait bound `String: Share` is not satisfied + + require_share::>(); + //~^ ERROR the trait bound `Vec: Share` is not satisfied + + require_share::>(); + //~^ ERROR the trait bound `Box: Share` is not satisfied +} diff --git a/tests/ui/share-trait/share-trait-non-implementors.stderr b/tests/ui/share-trait/share-trait-non-implementors.stderr new file mode 100644 index 0000000000000..8056e34beea55 --- /dev/null +++ b/tests/ui/share-trait/share-trait-non-implementors.stderr @@ -0,0 +1,76 @@ +error[E0277]: the trait bound `&mut i32: Share` is not satisfied + --> $DIR/share-trait-non-implementors.rs:8:21 + | +LL | require_share::<&mut i32>(); + | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `&mut i32` + | + = help: the following other types implement trait `Share`: + &T + Arc + Rc + SyncSender + std::sync::mpsc::Sender + = note: `Share` is implemented for `&i32`, but not for `&mut i32` +note: required by a bound in `require_share` + --> $DIR/share-trait-non-implementors.rs:5:21 + | +LL | fn require_share() {} + | ^^^^^ required by this bound in `require_share` + +error[E0277]: the trait bound `String: Share` is not satisfied + --> $DIR/share-trait-non-implementors.rs:11:21 + | +LL | require_share::(); + | ^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `String` + | + = help: the following other types implement trait `Share`: + &T + Arc + Rc + SyncSender + std::sync::mpsc::Sender +note: required by a bound in `require_share` + --> $DIR/share-trait-non-implementors.rs:5:21 + | +LL | fn require_share() {} + | ^^^^^ required by this bound in `require_share` + +error[E0277]: the trait bound `Vec: Share` is not satisfied + --> $DIR/share-trait-non-implementors.rs:14:21 + | +LL | require_share::>(); + | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `Vec` + | + = help: the following other types implement trait `Share`: + &T + Arc + Rc + SyncSender + std::sync::mpsc::Sender +note: required by a bound in `require_share` + --> $DIR/share-trait-non-implementors.rs:5:21 + | +LL | fn require_share() {} + | ^^^^^ required by this bound in `require_share` + +error[E0277]: the trait bound `Box: Share` is not satisfied + --> $DIR/share-trait-non-implementors.rs:17:21 + | +LL | require_share::>(); + | ^^^^^^^^ the nightly-only, unstable trait `Share` is not implemented for `Box` + | + = help: the following other types implement trait `Share`: + &T + Arc + Rc + SyncSender + std::sync::mpsc::Sender +note: required by a bound in `require_share` + --> $DIR/share-trait-non-implementors.rs:5:21 + | +LL | fn require_share() {} + | ^^^^^ required by this bound in `require_share` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/share-trait/share-trait-not-in-prelude.rs b/tests/ui/share-trait/share-trait-not-in-prelude.rs new file mode 100644 index 0000000000000..4876fac2b8c1d --- /dev/null +++ b/tests/ui/share-trait/share-trait-not-in-prelude.rs @@ -0,0 +1,9 @@ +#![feature(share_trait)] + +#[derive(Clone)] +struct Alias; + +impl Share for Alias {} +//~^ ERROR cannot find trait `Share` in this scope + +fn main() {} diff --git a/tests/ui/share-trait/share-trait-not-in-prelude.stderr b/tests/ui/share-trait/share-trait-not-in-prelude.stderr new file mode 100644 index 0000000000000..733c8f2d2b215 --- /dev/null +++ b/tests/ui/share-trait/share-trait-not-in-prelude.stderr @@ -0,0 +1,14 @@ +error[E0405]: cannot find trait `Share` in this scope + --> $DIR/share-trait-not-in-prelude.rs:6:6 + | +LL | impl Share for Alias {} + | ^^^^^ not found in this scope + | +help: consider importing this trait + | +LL + use std::clone::Share; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/share-trait/share-trait-rc.rs b/tests/ui/share-trait/share-trait-rc.rs new file mode 100644 index 0000000000000..7de6936bcc9cb --- /dev/null +++ b/tests/ui/share-trait/share-trait-rc.rs @@ -0,0 +1,32 @@ +//@ run-pass + +#![feature(share_trait)] + +use std::cell::Cell; +use std::clone::Share; +use std::rc::Rc; + +trait Value { + fn get(&self) -> i32; +} + +impl Value for Cell { + fn get(&self) -> i32 { + Cell::get(self) + } +} + +fn main() { + let value = Rc::new(Cell::new(1)); + let shared = value.share(); + + assert!(Rc::ptr_eq(&value, &shared)); + shared.set(2); + assert_eq!(value.get(), 2); + + let dyn_value: Rc = Rc::new(Cell::new(3)); + let shared_dyn_value = dyn_value.share(); + + assert!(Rc::ptr_eq(&dyn_value, &shared_dyn_value)); + assert_eq!(shared_dyn_value.get(), 3); +} diff --git a/tests/ui/share-trait/share-trait-requires-clone.rs b/tests/ui/share-trait/share-trait-requires-clone.rs new file mode 100644 index 0000000000000..a70ae3ade37d0 --- /dev/null +++ b/tests/ui/share-trait/share-trait-requires-clone.rs @@ -0,0 +1,10 @@ +#![feature(share_trait)] + +use std::clone::Share; + +struct NotClone; + +impl Share for NotClone {} +//~^ ERROR the trait bound `NotClone: Clone` is not satisfied + +fn main() {} diff --git a/tests/ui/share-trait/share-trait-requires-clone.stderr b/tests/ui/share-trait/share-trait-requires-clone.stderr new file mode 100644 index 0000000000000..ac775db690a40 --- /dev/null +++ b/tests/ui/share-trait/share-trait-requires-clone.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `NotClone: Clone` is not satisfied + --> $DIR/share-trait-requires-clone.rs:7:16 + | +LL | impl Share for NotClone {} + | ^^^^^^^^ the trait `Clone` is not implemented for `NotClone` + | +note: required by a bound in `Share` + --> $SRC_DIR/core/src/clone.rs:LL:COL +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct NotClone; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/share-trait/share-trait.rs b/tests/ui/share-trait/share-trait.rs new file mode 100644 index 0000000000000..7a099cd96cb85 --- /dev/null +++ b/tests/ui/share-trait/share-trait.rs @@ -0,0 +1,44 @@ +//@ check-pass + +#![feature(share_trait)] + +extern crate core; + +use core::clone::Share; + +#[derive(Debug, PartialEq)] +struct Alias(u8); + +impl Clone for Alias { + fn clone(&self) -> Self { + Alias(self.0 + 1) + } +} + +impl Share for Alias {} + +fn share_generic(value: &T) -> T { + value.share() +} + +fn main() { + let value = Alias(1); + + assert_eq!(Share::share(&value), Alias(2)); + assert_eq!(std::clone::Share::share(&value), Alias(2)); + assert_eq!(value.share(), Alias(2)); + assert_eq!(share_generic(&value), Alias(2)); + + let number = 3; + let shared = &number; + let shared_again = shared.share(); + let shared_fqs: &i32 = Share::share(&shared); + let shared_generic: &i32 = share_generic(&shared); + + assert!(std::ptr::eq(shared, shared_again)); + assert!(std::ptr::eq(shared_fqs, shared)); + assert!(std::ptr::eq(shared_generic, shared)); + + let slice: &[i32] = &[1, 2, 3]; + assert!(std::ptr::eq(slice, slice.share())); +}