New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Weak.ptr_eq #55987

Merged
merged 3 commits into from Dec 6, 2018

Conversation

Projects
None yet
8 participants
@Thomasdezeeuw
Copy link
Contributor

Thomasdezeeuw commented Nov 15, 2018

I hope the doc tests alone are good enough.

We also might want to discuss the dangling pointer case (from Weak::new()).

Updates #55981.

@rust-highfive

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Nov 15, 2018

r? @sfackler

(rust_highfive has picked a reviewer for you, use r? to override)

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Nov 15, 2018

There's no ABA problem here since the underlying Rc allocation isn't freed while there are outstanding Weaks, right?

I agree with the behavior for dangling Weaks.

We should define this for both Arc's and Rc's Weak.

@Thomasdezeeuw

This comment has been minimized.

Copy link
Contributor

Thomasdezeeuw commented Nov 15, 2018

@sfackler the memory is only deallocated once the weak count hits 0 (starts at 1), see https://github.com/rust-lang/rust/blob/master/src/liballoc/rc.rs#L855-L857 and https://github.com/rust-lang/rust/blob/master/src/liballoc/rc.rs#L1297-L1301.

As for the dangling pointers; I don't think Rc or Arc allows for dangling pointers, they can only be created with an actual value, at least when using safe code. Only Weak::new will create a dangling pointer to avoid allocating.

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Nov 15, 2018

Ok cool, this approach should work then. Let's add the same method for Arc and this should be good to go.

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Nov 15, 2018

@Thomasdezeeuw

This comment has been minimized.

Copy link
Contributor

Thomasdezeeuw commented Nov 15, 2018

Do you want the Arc and sync::Weak change in this PR? Or should I make another?

Also what should I do with the stable/unstable attribute?

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Nov 15, 2018

Let's add it in this PR.

The new functions should be added as unstable initially. We can repurpose #55981 as the tracking issue.

@rust-highfive

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Nov 15, 2018

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:18499f1b:start=1542304911622934307,finish=1542304972295575162,duration=60672640855
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#Pull-Requests-and-Security-Restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export IMAGE=x86_64-gnu-llvm-5.0
---
[00:55:21] .................................................................................................... 100/5021
[00:55:24] .................................................................................................... 200/5021
[00:55:27] .............................ii............................................ii...................ii.. 300/5021
[00:55:30] ..............................................................................................iii... 400/5021
[00:55:34] .....iiiiiiii.iii............................iii...........................................i........ 500/5021
[00:55:41] .................................................................................................... 700/5021
[00:55:48] .................................................................................i...........i...... 800/5021
[00:55:51] .................................................................................................... 900/5021
[00:55:55] iiiii..................ii.iiii...................................................................... 1000/5021
---
[00:56:35] .................................................................................................... 2200/5021
[00:56:40] .................................................................................................... 2300/5021
[00:56:44] .................................................................................................... 2400/5021
[00:56:48] .................................................................................................... 2500/5021
[00:56:51] .................................................................................iiiiiiiii.......... 2600/5021
[00:56:59] ...............................................ii................................................... 2800/5021
[00:57:03] .................................................................................................... 2900/5021
[00:57:07] .................................................................................................... 3000/5021
[00:57:10] ..........................................i......................................................... 3100/5021
---
travis_time:start:test_codegen
Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:12:03] 
[01:12:03] running 116 tests
[01:12:06] i..ii...iii..iiii.....i...i.........i..iii...........i.....i.....ii...i..i.ii..............i...ii..i 100/116
[01:12:06] i.i....iiii.....
[01:12:06] 
[01:12:06]  finished in 3.808
[01:12:06] travis_fold:end:test_codegen

---
travis_time:start:test_debuginfo
Check compiletest suite=debuginfo mode=debuginfo-both (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:12:23] 
[01:12:23] running 118 tests
[01:12:50] .iiiii...i.....i..i...i..i.i..i.i..i.....i..i....i..........iiii.........i.i....i...i.......ii.i.i.i 100/118
[01:12:54] ......iii.i.....ii
[01:12:54] 
[01:12:54]  finished in 31.617
[01:12:54] travis_fold:end:test_debuginfo

---
[01:24:58] 
[01:24:58] running 408 tests
[01:25:19] .................................................................................................... 100/408
[01:25:34] .....................................................................i.............................. 200/408
[01:25:49] ...................FF............................................................................... 300/408
[01:26:04] ........
[01:26:04] failures:
[01:26:04] 
[01:26:04] ---- rc.rs - rc::Weak<T>::ptr_eq (line 1291) stdout ----
[01:26:04] ---- rc.rs - rc::Weak<T>::ptr_eq (line 1291) stdout ----
[01:26:04] error[E0425]: cannot find value `third` in this scope
[01:26:04]   --> rc.rs:1300:13
[01:26:04]    |
[01:26:04] 12 | let third = third.downgrade();
[01:26:04] 
[01:26:04] 
[01:26:04] error[E0658]: use of unstable library feature 'weak_ptr_eq'
[01:26:04]  --> rc.rs:1297:10
[01:26:04]   |
[01:26:04] 9 | assert!(!Weak::ptr_eq(&first, &second));
[01:26:04]   |
[01:26:04]   |
[01:26:04]   = help: add #![feature(weak_ptr_eq)] to the crate attributes to enable
[01:26:04] 
[01:26:04] error[E0658]: use of unstable library feature 'weak_ptr_eq'
[01:26:04]   --> rc.rs:1302:10
[01:26:04]    |
[01:26:04] 14 | assert!(!Weak::ptr_eq(&first, &third));
[01:26:04]    |
[01:26:04]    |
[01:26:04]    = help: add #![feature(weak_ptr_eq)] to the crate attributes to enable
[01:26:04] thread 'rc.rs - rc::Weak<T>::ptr_eq (line 1291)' panicked at 'couldn't compile the test', librustdoc/test.rs:323:13
[01:26:04] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[01:26:04] 
[01:26:04] ---- rc.rs - rc::Weak<T>::ptr_eq (line 1270) stdout ----
[01:26:04] ---- rc.rs - rc::Weak<T>::ptr_eq (line 1270) stdout ----
[01:26:04] error[E0599]: no method named `downgrade` found for type `std::rc::Rc<{integer}>` in the current scope
[01:26:04]  --> rc.rs:1274:22
[01:26:04]   |
[01:26:04] 7 | let first = first_rc.downgrade();
[01:26:04]   |             |        |
[01:26:04]   |             |        this is an associated function, not a method
[01:26:04]   |             |        this is an associated function, not a method
[01:26:04]   |             help: use associated function syntax instead: `std::rc::Rc<{integer}>::downgrade`
[01:26:04]   |
[01:26:04]   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:26:04]   = note: the candidate is defined in an impl for the type `std::rc::Rc<_>`
[01:26:04] 
[01:26:04] error[E0599]: no method named `downgrade` found for type `std::rc::Rc<{integer}>` in the current scope
[01:26:04]  --> rc.rs:1275:23
[01:26:04]   |
[01:26:04] 8 | let second = first_rc.downgrade();
[01:26:04]   |              |        |
[01:26:04]   |              |        this is an associated function, not a method
[01:26:04]   |              |        this is an associated function, not a method
[01:26:04]   |              help: use associated function syntax instead: `std::rc::Rc<{integer}>::downgrade`
[01:26:04]   |
[01:26:04]   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:26:04]   = note: the candidate is defined in an impl for the type `std::rc::Rc<_>`
[01:26:04] 
[01:26:04] error[E0658]: use of unstable library feature 'weak_ptr_eq'
[01:26:04]   --> rc.rs:1277:9
[01:26:04]    |
[01:26:04] 10 | assert!(Weak::ptr_eq(&first, &second));
[01:26:04]    |
[01:26:04]    |
[01:26:04]    = help: add #![feature(weak_ptr_eq)] to the crate attributes to enable
[01:26:04] 
[01:26:04] error[E0599]: no method named `downgrade` found for type `std::rc::Rc<{integer}>` in the current scope
[01:26:04]   --> rc.rs:1280:22
[01:26:04]    |
[01:26:04] 13 | let third = third_rc.downgrade();
[01:26:04]    |             |        |
[01:26:04]    |             |        this is an associated function, not a method
[01:26:04]    |             |        this is an associated function, not a method
[01:26:04]    |             help: use associated function syntax instead: `std::rc::Rc<{integer}>::downgrade`
[01:26:04]    |
[01:26:04]    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:26:04]    = note: the candidate is defined in an impl for the type `std::rc::Rc<_>`
[01:26:04] 
[01:26:04] error[E0658]: use of unstable library feature 'weak_ptr_eq'
[01:26:04]   --> rc.rs:1282:10
[01:26:04]    |
[01:26:04] 15 | assert!(!Weak::ptr_eq(&first, &third));
[01:26:04]    |
[01:26:04]    |
[01:26:04]    = help: add #![feature(weak_ptr_eq)] to the crate attributes to enable
[01:26:04] thread 'rc.rs - rc::Weak<T>::ptr_eq (line 1270)' panicked at 'couldn't compile the test', librustdoc/test.rs:323:13
[01:26:04] 
[01:26:04] 
[01:26:04] failures:
---
[01:26:04] 
[01:26:04] error: test failed, to rerun pass '--doc'
[01:26:04] 
[01:26:04] 
[01:26:04] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "test" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" "panic-unwind backtrace" "--manifest-path" "/checkout/src/libstd/Cargo.toml" "-p" "alloc" "--" "--quiet"
[01:26:04] 
[01:26:04] 
[01:26:04] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:26:04] Build completed unsuccessfully in 0:34:51
[01:26:04] Build completed unsuccessfully in 0:34:51
[01:26:04] Makefile:58: recipe for target 'check' failed
[01:26:04] make: *** [check] Error 1
The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:08f317a8
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
Thu Nov 15 19:29:08 UTC 2018

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Nov 15, 2018

oh, we should also add some basic tests.

@Thomasdezeeuw Thomasdezeeuw force-pushed the Thomasdezeeuw:weak-ptr_eq branch from c621328 to 1d1beaf Nov 15, 2018

@Thomasdezeeuw

This comment has been minimized.

Copy link
Contributor

Thomasdezeeuw commented Nov 15, 2018

@sfackler I've add examples which also serve as tests. I explicitly added the example of the dangling pointer. What other tests would you like to see?

@rust-highfive

This comment has been minimized.

Copy link
Collaborator

rust-highfive commented Nov 15, 2018

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:0e54aaee:start=1542311928272529443,finish=1542311981984741777,duration=53712212334
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#Pull-Requests-and-Security-Restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export IMAGE=x86_64-gnu-llvm-5.0
---
[00:51:26] .................................................................................................... 100/5021
[00:51:29] .................................................................................................... 200/5021
[00:51:32] .............................ii............................................ii...................ii.. 300/5021
[00:51:35] ..............................................................................................iii... 400/5021
[00:51:38] .....iiiiiiii.iii............................iii...........................................i........ 500/5021
[00:51:45] .................................................................................................... 700/5021
[00:51:51] .................................................................................i...........i...... 800/5021
[00:51:55] .................................................................................................... 900/5021
[00:51:58] iiiii..................ii.iiii...................................................................... 1000/5021
---
[00:52:34] .................................................................................................... 2200/5021
[00:52:38] .................................................................................................... 2300/5021
[00:52:42] .................................................................................................... 2400/5021
[00:52:46] .................................................................................................... 2500/5021
[00:52:49] .................................................................................iiiiiiiii.......... 2600/5021
[00:52:56] ................................................ii.................................................. 2800/5021
[00:52:59] .................................................................................................... 2900/5021
[00:53:03] .................................................................................................... 3000/5021
[00:53:06] ..........................................i......................................................... 3100/5021
---
travis_time:start:test_codegen
Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:06:56] 
[01:06:56] running 116 tests
[01:06:59] i..ii...iii..iiii.....i...i.........i..iii...........i.....i.....ii...i..i.ii..............i...ii..i 100/116
[01:07:00] i.i....iiii.....
[01:07:00] 
[01:07:00]  finished in 3.545
[01:07:00] travis_fold:end:test_codegen

---
travis_time:start:test_debuginfo
Check compiletest suite=debuginfo mode=debuginfo-both (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:07:14] 
[01:07:14] running 118 tests
[01:07:39] .iiiii...i.....i..i...i..i.i..i.i..i.....i..i....i..........iiii.........i.i....i...i.......ii.i.i.i 100/118
[01:07:43] ......iii.i.....ii
[01:07:43] 
[01:07:43]  finished in 29.172
[01:07:43] travis_fold:end:test_debuginfo

---
[01:19:02] 
[01:19:02] running 410 tests
[01:19:20] .................................................................................................... 100/410
[01:19:34] .....................................................................i.............................. 200/410
[01:19:46] ...................F.F.............................................................................. 300/410
[01:19:58] ...............................................FF................................................... 400/410
[01:19:59] failures:
[01:19:59] 
[01:19:59] ---- rc.rs - rc::Weak<T>::ptr_eq (line 1270) stdout ----
[01:19:59] ---- rc.rs - rc::Weak<T>::ptr_eq (line 1270) stdout ----
[01:19:59] error[E0599]: no method named `downgrade` found for type `std::rc::Rc<{integer}>` in the current scope
[01:19:59]  --> rc.rs:1275:22
[01:19:59]   |
[01:19:59] 8 | let first = first_rc.downgrade();
[01:19:59]   |             |        |
[01:19:59]   |             |        this is an associated function, not a method
[01:19:59]   |             |        this is an associated function, not a method
[01:19:59]   |             help: use associated function syntax instead: `std::rc::Rc<{integer}>::downgrade`
[01:19:59]   |
[01:19:59]   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:19:59]   = note: the candidate is defined in an impl for the type `std::rc::Rc<_>`
[01:19:59] 
[01:19:59] error[E0599]: no method named `downgrade` found for type `std::rc::Rc<{integer}>` in the current scope
[01:19:59]  --> rc.rs:1276:23
[01:19:59]   |
[01:19:59] 9 | let second = first_rc.downgrade();
[01:19:59]   |              |        |
[01:19:59]   |              |        this is an associated function, not a method
[01:19:59]   |              |        this is an associated function, not a method
[01:19:59]   |              help: use associated function syntax instead: `std::rc::Rc<{integer}>::downgrade`
[01:19:59]   |
[01:19:59]   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:19:59]   = note: the candidate is defined in an impl for the type `std::rc::Rc<_>`
[01:19:59] 
[01:19:59] error[E0599]: no method named `downgrade` found for type `std::rc::Rc<{integer}>` in the current scope
[01:19:59]   --> rc.rs:1281:22
[01:19:59]    |
[01:19:59] 14 | let third = third_rc.downgrade();
[01:19:59]    |             |        |
[01:19:59]    |             |        this is an associated function, not a method
[01:19:59]    |             |        this is an associated function, not a method
[01:19:59]    |             help: use associated function syntax instead: `std::rc::Rc<{integer}>::downgrade`
[01:19:59]    |
[01:19:59]    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:19:59]    = note: the candidate is defined in an impl for the type `std::rc::Rc<_>`
[01:19:59] thread 'rc.rs - rc::Weak<T>::ptr_eq (line 1270)' panicked at 'couldn't compile the test', librustdoc/test.rs:323:13
[01:19:59] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[01:19:59] 
[01:19:59] ---- rc.rs - rc::Weak<T>::ptr_eq (line 1292) stdout ----
[01:19:59] ---- rc.rs - rc::Weak<T>::ptr_eq (line 1292) stdout ----
[01:19:59] error[E0599]: no method named `downgrade` found for type `std::rc::Rc<()>` in the current scope
[01:19:59]   --> rc.rs:1302:22
[01:19:59]    |
[01:19:59] 13 | let third = third_rc.downgrade();
[01:19:59]    |             |        |
[01:19:59]    |             |        this is an associated function, not a method
[01:19:59]    |             |        this is an associated function, not a method
[01:19:59]    |             help: use associated function syntax instead: `std::rc::Rc<()>::downgrade`
[01:19:59]    |
[01:19:59]    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:19:59]    = note: the candidate is defined in an impl for the type `std::rc::Rc<_>`
[01:19:59] thread 'rc.rs - rc::Weak<T>::ptr_eq (line 1292)' panicked at 'couldn't compile the test', librustdoc/test.rs:323:13
[01:19:59] 
[01:19:59] ---- sync.rs - sync::Weak<T>::ptr_eq (line 1140) stdout ----
[01:19:59] ---- sync.rs - sync::Weak<T>::ptr_eq (line 1140) stdout ----
[01:19:59] error[E0599]: no method named `downgrade` found for type `std::sync::Arc<{integer}>` in the current scope
[01:19:59]  --> sync.rs:1145:22
[01:19:59]   |
[01:19:59] 8 | let first = first_rc.downgrade();
[01:19:59]   |             |        |
[01:19:59]   |             |        this is an associated function, not a method
[01:19:59]   |             |        this is an associated function, not a method
[01:19:59]   |             help: use associated function syntax instead: `std::sync::Arc<{integer}>::downgrade`
[01:19:59]   |
[01:19:59]   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:19:59]   = note: the candidate is defined in an impl for the type `std::sync::Arc<_>`
[01:19:59] 
[01:19:59] error[E0599]: no method named `downgrade` found for type `std::sync::Arc<{integer}>` in the current scope
[01:19:59]  --> sync.rs:1146:23
[01:19:59]   |
[01:19:59] 9 | let second = first_rc.downgrade();
[01:19:59]   |              |        |
[01:19:59]   |              |        this is an associated function, not a method
[01:19:59]   |              |        this is an associated function, not a method
[01:19:59]   |              help: use associated function syntax instead: `std::sync::Arc<{integer}>::downgrade`
[01:19:59]   |
[01:19:59]   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:19:59]   = note: the candidate is defined in an impl for the type `std::sync::Arc<_>`
[01:19:59] 
[01:19:59] error[E0599]: no method named `downgrade` found for type `std::sync::Arc<{integer}>` in the current scope
[01:19:59]   --> sync.rs:1151:22
[01:19:59]    |
[01:19:59] 14 | let third = third_rc.downgrade();
[01:19:59]    |             |        |
[01:19:59]    |             |        this is an associated function, not a method
[01:19:59]    |             |        this is an associated function, not a method
[01:19:59]    |             help: use associated function syntax instead: `std::sync::Arc<{integer}>::downgrade`
[01:19:59]    |
[01:19:59]    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:19:59]    = note: the candidate is defined in an impl for the type `std::sync::Arc<_>`
[01:19:59] thread 'sync.rs - sync::Weak<T>::ptr_eq (line 1140)' panicked at 'couldn't compile the test', librustdoc/test.rs:323:13
[01:19:59] 
[01:19:59] ---- sync.rs - sync::Weak<T>::ptr_eq (line 1162) stdout ----
[01:19:59] ---- sync.rs - sync::Weak<T>::ptr_eq (line 1162) stdout ----
[01:19:59] error[E0599]: no method named `downgrade` found for type `std::sync::Arc<()>` in the current scope
[01:19:59]   --> sync.rs:1172:22
[01:19:59]    |
[01:19:59] 13 | let third = third_rc.downgrade();
[01:19:59]    |             |        |
[01:19:59]    |             |        this is an associated function, not a method
[01:19:59]    |             |        this is an associated function, not a method
[01:19:59]    |             help: use associated function syntax instead: `std::sync::Arc<()>::downgrade`
[01:19:59]    |
[01:19:59]    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
[01:19:59]    = note: the candidate is defined in an impl for the type `std::sync::Arc<_>`
[01:19:59] thread 'sync.rs - sync::Weak<T>::ptr_eq (line 1162)' panicked at 'couldn't compile the test', librustdoc/test.rs:323:13
[01:19:59] 
[01:19:59] 
[01:19:59] failures:
---
[01:19:59] 
[01:19:59] error: test failed, to rerun pass '--doc'
[01:19:59] 
[01:19:59] 
[01:19:59] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "test" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" "panic-unwind backtrace" "--manifest-path" "/checkout/src/libstd/Cargo.toml" "-p" "alloc" "--" "--quiet"
[01:19:59] 
[01:19:59] 
[01:19:59] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:19:59] Build completed unsuccessfully in 0:32:21
[01:19:59] Build completed unsuccessfully in 0:32:21
[01:19:59] Makefile:58: recipe for target 'check' failed
[01:19:59] make: *** [check] Error 1
The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:2350481c
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
Thu Nov 15 21:19:52 UTC 2018

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Nov 17, 2018

☔️ The latest upstream changes (presumably #55627) made this pull request unmergeable. Please resolve the merge conflicts.

@Thomasdezeeuw Thomasdezeeuw force-pushed the Thomasdezeeuw:weak-ptr_eq branch from 59b1198 to 90d2914 Nov 17, 2018

@Thomasdezeeuw

This comment has been minimized.

Copy link
Contributor

Thomasdezeeuw commented Nov 21, 2018

Anything I can do to progress this?

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Nov 21, 2018

Oh whoops - Github doesn't email on force pushes so I didn't see it was rebased :(

@bors r+

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Nov 21, 2018

📌 Commit 90d2914 has been approved by sfackler

///
/// When using `Weak::new` the `Weak` is never equal to any other `Weak`
/// until it points to actual data (e.g. by setting it to a value created by
/// calling [`Arc::downgrade`]).

This comment has been minimized.

@jethrogb

jethrogb Nov 22, 2018

Contributor

I think this documentation is slightly confusion. Outside of std, I don't think there is any way to turn a reference obtained through Weak::new into a reference to something real. I think it should just say something like:

References obtained through Weak::new are not equal to any other references, including other invocations of Weak::new.

(same applies to rc::Weak)

This comment has been minimized.

@Thomasdezeeuw

Thomasdezeeuw Nov 22, 2018

Contributor

Outside of std, I don't think there is any way to turn a reference obtained through Weak::new into a reference to something real.

I'm not sure what you mean by that. You can overwrite the value, e.g.

let mut weak_value = Weak::new();
let value = Rc::new(5);
weak_value = Rc::dowgrade(&value);

As for the comparing two Weak::new() with another I agree, but isn't the example enough? Currently no pointer created via Weak::new() is equal to any other pointer, including pointers also created via Weak::new(). That is what the documentations currently says.

This comment has been minimized.

@jethrogb

jethrogb Nov 22, 2018

Contributor

The way the documentation is written implies that you can take a Weak::new and somehow turn it into something that's not a dangling pointer. For example some fn(self: &mut Weak<T>). Assignment and mem::replace don't count.

This comment has been minimized.

@Thomasdezeeuw

Thomasdezeeuw Nov 23, 2018

Contributor

Sorry @jethrogb I still don't really see your point. You keep mentioning "dangling pointer", but the public documentation doesn't. Furthermore you can turn a variable with the current value of Weak::new into something else by using plain assignment. That is also possible in any function that takes &mut Weak<T>, so I don't get why that doesn't "count".

This comment has been minimized.

@jethrogb

jethrogb Nov 23, 2018

Contributor

"dangling pointer" and Weak::new are equivalent.

Furthermore you can turn a variable with the current value of Weak::new into something else by using plain assignment.

Dropping the old value and moving something new in its place is not the same as changing the value.

This comment has been minimized.

@Thomasdezeeuw

Thomasdezeeuw Nov 23, 2018

Contributor

@jethrogb "dangling pointer" and Weak::new are not equivalent. That is only how the current API is implementated. Previous versions of Rust (not sure what version changed it) actually allocated on the heap when calling Weak::new. A change was made to not allocate by default for most (collection) types, including Weak. However this happend without a change in the API. This means we could go back to that implementation and then Weak::new and "dangling pointer" aren't equivalent anymore.

But maybe someone else can can help here, this discussion is going off the rails and we're clearing not understanding each other.

This comment has been minimized.

@jethrogb

jethrogb Nov 23, 2018

Contributor

@jethrogb "dangling pointer" and Weak::new are not equivalent. That is only how the current API is implementated. Previous versions of Rust (not sure what version changed it) actually allocated on the heap when calling Weak::new. A change was made to not allocate by default for most (collection) types, including Weak. However this happend without a change in the API. This means we could go back to that implementation and then Weak::new and "dangling pointer" aren't equivalent anymore.

Ok fine, I was using them equivalently, but I meant Weak::new. This point is completely orthogonal to my main point about the phrasing of the documentation.

This comment has been minimized.

@jethrogb

jethrogb Nov 23, 2018

Contributor

When using Weak::new the Weak is never equal to any other Weak until it points to actual data

The "until it points to actual data" part clearly implies you can take a Weak::new and somehow change it to a value that is real. Dropping the old value and moving something new in its place is not the same as changing the value.

@stjepang

This comment has been minimized.

Copy link
Contributor

stjepang commented Nov 22, 2018

I disagree with the handling of the dangling case.

Suppose we had an AtomicWeak<T> type and then wanted to implement a get method that loads it or initializes to 0 when dangling:

fn get(a: &AtomicWeak<i32>) -> Arc<i32> {
    loop {
        let weak = a.load();
        match weak.upgrade() {
            Some(arc) => return arc,
            None => {
                let arc = Arc::new(0);
                let prev = a.compare_and_swap(&weak, Arc::downgrade(&arc));
                if Weak::ptr_eq(&prev, &weak) {
                    return arc;
                }
            }
        }
    }
}

With the current behavior of Weak::ptr_eq for dangling pointers, the CAS operation and the if check would not work. In fact, I think it would be impossible to implement this function as intended.

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Nov 23, 2018

So what should the handling be then? Are dangling weaks equal to each other? To all pointers?

@stjepang

This comment has been minimized.

Copy link
Contributor

stjepang commented Nov 23, 2018

@sfackler Ah, I misunderstood by thinking "dangling weak" means "weak with strong_count = 0". :(

Never mind then, the current behavior seems good to me.

@Thomasdezeeuw

This comment has been minimized.

Copy link
Contributor

Thomasdezeeuw commented Nov 23, 2018

@stjepang but that still doesn't make you example work, does it? I mean you can remove the if statement and upgrade on the next loop, but that does mean some more atomic instructions.

@SimonSapin

This comment has been minimized.

Copy link
Contributor

SimonSapin commented Nov 23, 2018

It feels surprising that Weak::new() would not equal itself (not just results of other calls to Weak::new()).

@stjepang

This comment has been minimized.

Copy link
Contributor

stjepang commented Nov 23, 2018

@Thomasdezeeuw Hmmm, right... if AtomicWeak is initialized to Weak::new(), then it doesn't work.

@SimonSapin also has a good point.

I think there are two ways to interpret a dangling Weak::new() pointer:

  1. It is like an uninitialized pointer and every such pointer is (potentially?) different.
  2. It is like a null pointer and all such pointers are equal.

Given these two choices, I'd prefer to go with the second one and make all dangling pointers equal.
EDIT: Not so sure anymore.

@stjepang

This comment has been minimized.

Copy link
Contributor

stjepang commented Nov 23, 2018

Btw, a small nit: in the docs for std::rc::Weak::new, the link to upgrade is dangling. Might be good to fix it in this PR.

@Thomasdezeeuw

This comment has been minimized.

Copy link
Contributor

Thomasdezeeuw commented Nov 23, 2018

@SimonSapin I agree that it is surprising, but I went of the docs from Rc::ptr_eq which says:

Returns true if the two Rcs point to the same value (not just values that compare as equal).

Since Weak::new points to no value it can't ever point to the same value as any other Weak.

But if everybody agress that they should be equal to one another then I'm willing to change it.

@Thomasdezeeuw

This comment has been minimized.

Copy link
Contributor

Thomasdezeeuw commented Nov 30, 2018

It's a week later, are we any closer to consensus whether or Weak::ptr_eq(Weak::new(), Weak::new()) should return true or false?

@Thomasdezeeuw Thomasdezeeuw force-pushed the Thomasdezeeuw:weak-ptr_eq branch from 4a4aacd to 38e21f9 Dec 3, 2018

@Thomasdezeeuw

This comment has been minimized.

Copy link
Contributor

Thomasdezeeuw commented Dec 3, 2018

I've pushed changes to make Weak::new() equal itself. Can this be merged now? If people disagree with handling of Weak::new(), or any other cases, we have a stabilisation period for that right?

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Dec 3, 2018

Seems reasonable.

@bors r+

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Dec 3, 2018

📌 Commit 38e21f9 has been approved by sfackler

kennytm added a commit to kennytm/rust that referenced this pull request Dec 4, 2018

Rollup merge of rust-lang#55987 - Thomasdezeeuw:weak-ptr_eq, r=sfackler
Add Weak.ptr_eq

I hope the doc tests alone are good enough.

We also might want to discuss the dangling pointer case (from `Weak::new()`).

Updates rust-lang#55981.

bors added a commit that referenced this pull request Dec 4, 2018

Auto merge of #56506 - kennytm:rollup, r=kennytm
Rollup of 12 pull requests

Successful merges:

 - #55466 (syntax: Use iterator and pattern APIs instead of `char_at` )
 - #55563 (Improve no result found sentence in doc search)
 - #55987 (Add Weak.ptr_eq)
 - #56332 ([rustdoc] Specific crate search)
 - #56372 (Refer to the second borrow as the "second borrow" in E0501.rs)
 - #56388 (More MIR borrow check cleanup)
 - #56424 (Mention raw-ident syntax)
 - #56441 (rustbuild: Fix issues with compiler docs)
 - #56444 (Move compile-fail-fulldeps tests to UI)
 - #56456 (Handle existential types in dead code analysis)
 - #56466 (data_structures: remove tuple_slice)
 - #56497 (cleanup: remove static lifetimes from consts in libstd)

Failed merges:

r? @ghost
@kennytm

This comment has been minimized.

Copy link
Member

kennytm commented Dec 4, 2018

@bors rollup

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Dec 4, 2018

Rollup merge of rust-lang#55987 - Thomasdezeeuw:weak-ptr_eq, r=sfackler
Add Weak.ptr_eq

I hope the doc tests alone are good enough.

We also might want to discuss the dangling pointer case (from `Weak::new()`).

Updates rust-lang#55981.

bors added a commit that referenced this pull request Dec 4, 2018

Auto merge of #56521 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 15 pull requests

Successful merges:

 - #51753 (Document `From` implementations)
 - #55519 (Add example of using the indexing operator to HashMap docs)
 - #55563 (Improve no result found sentence in doc search)
 - #55987 (Add Weak.ptr_eq)
 - #56119 (Utilize `?` instead of `return None`.)
 - #56332 ([rustdoc] Specific crate search)
 - #56372 (Refer to the second borrow as the "second borrow" in E0501.rs)
 - #56388 (More MIR borrow check cleanup)
 - #56424 (Mention raw-ident syntax)
 - #56452 (Remove redundant clones)
 - #56456 (Handle existential types in dead code analysis)
 - #56466 (data_structures: remove tuple_slice)
 - #56476 (Fix invalid line number match)
 - #56497 (cleanup: remove static lifetimes from consts in libstd)
 - #56498 (Fix line numbers display)

Failed merges:

r? @ghost

bors added a commit that referenced this pull request Dec 5, 2018

Auto merge of #56521 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 15 pull requests

Successful merges:

 - #51753 (Document `From` implementations)
 - #55519 (Add example of using the indexing operator to HashMap docs)
 - #55563 (Improve no result found sentence in doc search)
 - #55987 (Add Weak.ptr_eq)
 - #56119 (Utilize `?` instead of `return None`.)
 - #56332 ([rustdoc] Specific crate search)
 - #56372 (Refer to the second borrow as the "second borrow" in E0501.rs)
 - #56388 (More MIR borrow check cleanup)
 - #56424 (Mention raw-ident syntax)
 - #56452 (Remove redundant clones)
 - #56456 (Handle existential types in dead code analysis)
 - #56466 (data_structures: remove tuple_slice)
 - #56476 (Fix invalid line number match)
 - #56497 (cleanup: remove static lifetimes from consts in libstd)
 - #56498 (Fix line numbers display)

Failed merges:

r? @ghost

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Dec 5, 2018

Rollup merge of rust-lang#55987 - Thomasdezeeuw:weak-ptr_eq, r=sfackler
Add Weak.ptr_eq

I hope the doc tests alone are good enough.

We also might want to discuss the dangling pointer case (from `Weak::new()`).

Updates rust-lang#55981.

bors added a commit that referenced this pull request Dec 5, 2018

Auto merge of #56531 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 19 pull requests

Successful merges:

 - #51753 (Document `From` implementations)
 - #55563 (Improve no result found sentence in doc search)
 - #55933 (emit error when doc generation fails)
 - #55987 (Add Weak.ptr_eq)
 - #56119 (Utilize `?` instead of `return None`.)
 - #56250 (Introduce ptr::hash for references)
 - #56332 ([rustdoc] Specific crate search)
 - #56372 (Refer to the second borrow as the "second borrow" in E0501.rs)
 - #56388 (More MIR borrow check cleanup)
 - #56424 (Mention raw-ident syntax)
 - #56441 (rustbuild: Fix issues with compiler docs)
 - #56452 (Remove redundant clones)
 - #56456 (Handle existential types in dead code analysis)
 - #56466 (data_structures: remove tuple_slice)
 - #56476 (Fix invalid line number match)
 - #56497 (cleanup: remove static lifetimes from consts in libstd)
 - #56498 (Fix line numbers display)
 - #56523 (Added a bare-bones eslint config (removing jslint))
 - #56525 (Avoid extra copy and syscall in std::env::current_exe)

bors added a commit that referenced this pull request Dec 5, 2018

Auto merge of #56531 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 19 pull requests

Successful merges:

 - #51753 (Document `From` implementations)
 - #55563 (Improve no result found sentence in doc search)
 - #55987 (Add Weak.ptr_eq)
 - #56010 (fix intra-link resolution spans in block comments)
 - #56119 (Utilize `?` instead of `return None`.)
 - #56250 (Introduce ptr::hash for references)
 - #56332 ([rustdoc] Specific crate search)
 - #56372 (Refer to the second borrow as the "second borrow" in E0501.rs)
 - #56388 (More MIR borrow check cleanup)
 - #56424 (Mention raw-ident syntax)
 - #56441 (rustbuild: Fix issues with compiler docs)
 - #56452 (Remove redundant clones)
 - #56456 (Handle existential types in dead code analysis)
 - #56466 (data_structures: remove tuple_slice)
 - #56476 (Fix invalid line number match)
 - #56497 (cleanup: remove static lifetimes from consts in libstd)
 - #56498 (Fix line numbers display)
 - #56523 (Added a bare-bones eslint config (removing jslint))
 - #56525 (Avoid extra copy and syscall in std::env::current_exe)

pietroalbini added a commit to pietroalbini/rust that referenced this pull request Dec 5, 2018

Rollup merge of rust-lang#55987 - Thomasdezeeuw:weak-ptr_eq, r=sfackler
Add Weak.ptr_eq

I hope the doc tests alone are good enough.

We also might want to discuss the dangling pointer case (from `Weak::new()`).

Updates rust-lang#55981.

pietroalbini added a commit to pietroalbini/rust that referenced this pull request Dec 5, 2018

Rollup merge of rust-lang#55987 - Thomasdezeeuw:weak-ptr_eq, r=sfackler
Add Weak.ptr_eq

I hope the doc tests alone are good enough.

We also might want to discuss the dangling pointer case (from `Weak::new()`).

Updates rust-lang#55981.

bors added a commit that referenced this pull request Dec 5, 2018

Auto merge of #56549 - pietroalbini:rollup, r=pietroalbini
Rollup of 15 pull requests

Successful merges:

 - #51753 (Document `From` implementations)
 - #55563 (Improve no result found sentence in doc search)
 - #55987 (Add Weak.ptr_eq)
 - #56119 (Utilize `?` instead of `return None`.)
 - #56372 (Refer to the second borrow as the "second borrow" in E0501.rs)
 - #56388 (More MIR borrow check cleanup)
 - #56424 (Mention raw-ident syntax)
 - #56452 (Remove redundant clones)
 - #56456 (Handle existential types in dead code analysis)
 - #56466 (data_structures: remove tuple_slice)
 - #56476 (Fix invalid line number match)
 - #56497 (cleanup: remove static lifetimes from consts in libstd)
 - #56498 (Fix line numbers display)
 - #56523 (Added a bare-bones eslint config (removing jslint))
 - #56538 (Use inner iterator may_have_side_effect for Cloned)

Failed merges:

r? @ghost

@bors bors merged commit 38e21f9 into rust-lang:master Dec 6, 2018

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

@Thomasdezeeuw Thomasdezeeuw referenced this pull request Dec 6, 2018

Open

Tracking issue for weak_ptr_eq #55981

1 of 2 tasks complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment