about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/liballoc/arc.rs66
-rw-r--r--src/liballoc/rc.rs66
-rw-r--r--src/libcompiler_builtins/lib.rs2
-rw-r--r--src/test/run-pass/i128.rs5
-rw-r--r--src/test/run-pass/u128.rs45
5 files changed, 117 insertions, 67 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 28f6d97756f..182a107e3f7 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -165,18 +165,29 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 
-/// A weak version of [`Arc`][arc].
+/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
+/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
+/// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`.
 ///
-/// `Weak` pointers do not count towards determining if the inner value
-/// should be dropped.
+/// Since a `Weak` reference does not count towards ownership, it will not
+/// prevent the inner value from being dropped, and `Weak` itself makes no
+/// guarantees about the value still being present and may return [`None`]
+/// when [`upgrade`]d.
 ///
-/// The typical way to obtain a `Weak` pointer is to call
-/// [`Arc::downgrade`][downgrade].
+/// A `Weak` pointer is useful for keeping a temporary reference to the value
+/// within [`Arc`] without extending its lifetime. It is also used to prevent
+/// circular references between [`Arc`] pointers, since mutual owning references
+/// would never allow either [`Arc`] to be dropped. For example, a tree could
+/// have strong [`Arc`] pointers from parent nodes to children, and `Weak`
+/// pointers from children back to their parents.
 ///
-/// See the [`Arc`][arc] documentation for more details.
+/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`].
 ///
-/// [arc]: struct.Arc.html
-/// [downgrade]: struct.Arc.html#method.downgrade
+/// [`Arc`]: struct.Arc.html
+/// [`Arc::downgrade`]: struct.Arc.html#method.downgrade
+/// [`upgrade`]: struct.Weak.html#method.upgrade
+/// [`Option`]: ../../std/option/enum.Option.html
+/// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "arc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
     ptr: Shared<ArcInner<T>>,
@@ -766,14 +777,11 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
 }
 
 impl<T> Weak<T> {
-    /// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
-    ///
-    /// This allocates memory for `T`, but does not initialize it. Calling
-    /// [`upgrade`][upgrade] on the return value always gives
-    /// [`None`][option].
+    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
+    /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [upgrade]: struct.Weak.html#method.upgrade
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: struct.Weak.html#method.upgrade
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -798,13 +806,13 @@ impl<T> Weak<T> {
 }
 
 impl<T: ?Sized> Weak<T> {
-    /// Upgrades the `Weak` pointer to an [`Arc`][arc], if possible.
+    /// Attempts to upgrade the `Weak` pointer to an [`Arc`], extending
+    /// the lifetime of the value if successful.
     ///
-    /// Returns [`None`][option] if the strong count has reached zero and the
-    /// inner value was destroyed.
+    /// Returns [`None`] if the value has since been dropped.
     ///
-    /// [arc]: struct.Arc.html
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`Arc`]: struct.Arc.html
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -865,10 +873,7 @@ impl<T: ?Sized> Weak<T> {
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
 impl<T: ?Sized> Clone for Weak<T> {
-    /// Makes a clone of the `Weak` pointer.
-    ///
-    /// This creates another pointer to the same inner value, increasing the
-    /// weak reference count.
+    /// Makes a clone of the `Weak` pointer that points to the same value.
     ///
     /// # Examples
     ///
@@ -900,14 +905,11 @@ impl<T: ?Sized> Clone for Weak<T> {
 
 #[stable(feature = "downgraded_weak", since = "1.10.0")]
 impl<T> Default for Weak<T> {
-    /// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
+    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
+    /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// This allocates memory for `T`, but does not initialize it. Calling
-    /// [`upgrade`][upgrade] on the return value always gives
-    /// [`None`][option].
-    ///
-    /// [upgrade]: struct.Weak.html#method.upgrade
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: struct.Weak.html#method.upgrade
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -926,8 +928,6 @@ impl<T> Default for Weak<T> {
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak` pointer.
     ///
-    /// This will decrement the weak reference count.
-    ///
     /// # Examples
     ///
     /// ```
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 561ccaa5ef5..fed718e9be4 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -922,18 +922,29 @@ impl<T> From<T> for Rc<T> {
     }
 }
 
-/// A weak version of [`Rc`][rc].
+/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
+/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
+/// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
 ///
-/// `Weak` pointers do not count towards determining if the inner value
-/// should be dropped.
+/// Since a `Weak` reference does not count towards ownership, it will not
+/// prevent the inner value from being dropped, and `Weak` itself makes no
+/// guarantees about the value still being present and may return [`None`]
+/// when [`upgrade`]d.
 ///
-/// The typical way to obtain a `Weak` pointer is to call
-/// [`Rc::downgrade`][downgrade].
+/// A `Weak` pointer is useful for keeping a temporary reference to the value
+/// within [`Rc`] without extending its lifetime. It is also used to prevent
+/// circular references between [`Rc`] pointers, since mutual owning references
+/// would never allow either [`Arc`] to be dropped. For example, a tree could
+/// have strong [`Rc`] pointers from parent nodes to children, and `Weak`
+/// pointers from children back to their parents.
 ///
-/// See the [module-level documentation](./index.html) for more details.
+/// The typical way to obtain a `Weak` pointer is to call [`Rc::downgrade`].
 ///
-/// [rc]: struct.Rc.html
-/// [downgrade]: struct.Rc.html#method.downgrade
+/// [`Rc`]: struct.Rc.html
+/// [`Rc::downgrade`]: struct.Rc.html#method.downgrade
+/// [`upgrade`]: struct.Weak.html#method.upgrade
+/// [`Option`]: ../../std/option/enum.Option.html
+/// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "rc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
     ptr: Shared<RcBox<T>>,
@@ -948,14 +959,11 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
 impl<T> Weak<T> {
-    /// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
-    ///
-    /// This allocates memory for `T`, but does not initialize it. Calling
-    /// [`upgrade`][upgrade] on the return value always gives
-    /// [`None`][option].
+    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
+    /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [upgrade]: struct.Weak.html#method.upgrade
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: struct.Weak.html#method.upgrade
+    /// [`None`]: ../../std/option/enum.Option.html
     ///
     /// # Examples
     ///
@@ -980,13 +988,13 @@ impl<T> Weak<T> {
 }
 
 impl<T: ?Sized> Weak<T> {
-    /// Upgrades the `Weak` pointer to an [`Rc`][rc], if possible.
+    /// Attempts to upgrade the `Weak` pointer to an [`Rc`], extending
+    /// the lifetime of the value if successful.
     ///
-    /// Returns [`None`][option] if the strong count has reached zero and the
-    /// inner value was destroyed.
+    /// Returns [`None`] if the value has since been dropped.
     ///
-    /// [rc]: struct.Rc.html
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`Rc`]: struct.Rc.html
+    /// [`None`]: ../../std/option/enum.Option.html
     ///
     /// # Examples
     ///
@@ -1021,8 +1029,6 @@ impl<T: ?Sized> Weak<T> {
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak` pointer.
     ///
-    /// This will decrement the weak reference count.
-    ///
     /// # Examples
     ///
     /// ```
@@ -1061,10 +1067,7 @@ impl<T: ?Sized> Drop for Weak<T> {
 
 #[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized> Clone for Weak<T> {
-    /// Makes a clone of the `Weak` pointer.
-    ///
-    /// This creates another pointer to the same inner value, increasing the
-    /// weak reference count.
+    /// Makes a clone of the `Weak` pointer that points to the same value.
     ///
     /// # Examples
     ///
@@ -1091,14 +1094,11 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
 
 #[stable(feature = "downgraded_weak", since = "1.10.0")]
 impl<T> Default for Weak<T> {
-    /// Constructs a new `Weak<T>`, without an accompanying instance of `T`.
-    ///
-    /// This allocates memory for `T`, but does not initialize it. Calling
-    /// [`upgrade`][upgrade] on the return value always gives
-    /// [`None`][option].
+    /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
+    /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [upgrade]: struct.Weak.html#method.upgrade
-    /// [option]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: struct.Weak.html#method.upgrade
+    /// [`None`]: ../../std/option/enum.Option.html
     ///
     /// # Examples
     ///
diff --git a/src/libcompiler_builtins/lib.rs b/src/libcompiler_builtins/lib.rs
index 58aba11e439..09b3d639507 100644
--- a/src/libcompiler_builtins/lib.rs
+++ b/src/libcompiler_builtins/lib.rs
@@ -180,7 +180,7 @@ pub mod reimpls {
             sr = sr.wrapping_add(1);
 
             // 1 <= sr <= u64::bits() - 1
-            q = n.wrapping_shl(64u32.wrapping_sub(sr));
+            q = n.wrapping_shl(128u32.wrapping_sub(sr));
             r = n.wrapping_shr(sr);
         } else {
             if d.high() == 0 {
diff --git a/src/test/run-pass/i128.rs b/src/test/run-pass/i128.rs
index dc4f0774b97..c5057f70c06 100644
--- a/src/test/run-pass/i128.rs
+++ b/src/test/run-pass/i128.rs
@@ -104,4 +104,9 @@ fn main() {
     assert_eq!(l.checked_sub(l), Some(0));
     assert_eq!(b(1u128).checked_shl(b(127)), Some(1 << 127));
     assert_eq!(o.checked_shl(b(128)), None);
+
+    // https://github.com/rust-lang/rust/issues/41228
+    assert_eq!(b(-87559967289969187895646876466835277875_i128) /
+               b(84285771033834995895337664386045050880_i128),
+               -1i128);
 }
diff --git a/src/test/run-pass/u128.rs b/src/test/run-pass/u128.rs
index ac3dfcdfde1..cfd616c56b4 100644
--- a/src/test/run-pass/u128.rs
+++ b/src/test/run-pass/u128.rs
@@ -77,4 +77,49 @@ fn main() {
     assert_eq!(o.checked_sub(b(18)), None);
     assert_eq!(b(1u128).checked_shl(b(127)), Some(1 << 127));
     assert_eq!(o.checked_shl(b(128)), None);
+
+    // Test cases for all udivmodti4 branches.
+    // case "0X/0X"
+    assert_eq!(b(0x69545bd57727c050_u128) /
+               b(0x3283527a3350d88c_u128),
+               2u128);
+    // case "0X/KX"
+    assert_eq!(b(0x0_8003c9c50b473ae6_u128) /
+               b(0x1_283e8838c30fa8f4_u128),
+               0u128);
+    // case "K0/K0"
+    assert_eq!(b(0xc43f42a207978720_u128 << 64) /
+               b(0x098e62b74c23cf1a_u128 << 64),
+               20u128);
+    // case "KK/K0" for power-of-two D.
+    assert_eq!(b(0xa9008fb6c9d81e42_0e25730562a601c8_u128) /
+               b(1u128 << 120),
+               169u128);
+    // case "KK/K0" with N >= D (https://github.com/rust-lang/rust/issues/41228).
+    assert_eq!(b(0xe4d26e59f0640328_06da5b06efe83a41_u128) /
+               b(0x330fcb030ea4447c_u128 << 64),
+               4u128);
+    assert_eq!(b(3u128 << 64 | 1) /
+               b(3u128 << 64),
+               1u128);
+    // case "KK/K0" with N < D.
+    assert_eq!(b(0x6655c9fb66ca2884_e2d1dfd470158c62_u128) /
+               b(0xb35b667cab7e355b_u128 << 64),
+               0u128);
+    // case "KX/0K" for power-of-two D.
+    assert_eq!(b(0x3e49dd84feb2df59_7b2f97d93a253969_u128) /
+               b(1u128 << 4),
+               0x03e49dd84feb2df5_97b2f97d93a25396_u128);
+    // case "KX/0K" in general.
+    assert_eq!(b(0x299692b3a1dae5bd_6162e6f489d2620e_u128) /
+               b(0x900b6f027571d6f7_u128),
+               0x49e95f54b0442578_u128);
+    // case "KX/KK" with N >= D.
+    assert_eq!(b(0xc7b889180b67b07d_bc1a3c88783d35b5_u128) /
+               b(0x1d7e69f53160b9e2_60074771e852f244_u128),
+               6u128);
+    // case "KX/KK" with N < D.
+    assert_eq!(b(0x679289ac23bb334f_36144401cf882172_u128) /
+               b(0x7b0b271b64865f05_f54a7b72746c062f_u128),
+               0u128);
 }