Skip to content
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

Small refactoring to make this code more clear #30593

Merged
merged 1 commit into from
Dec 31, 2015

Conversation

steveklabnik
Copy link
Member

This hairy conditional doesn't need to be so. It does need to be a
thin pointer, otherwise, it will fail to compile, so let's pull that out
into a temporary for future readers of the source.

/cc @nrc @SimonSapin @gankro @durka , who brought this up on IRC

@rust-highfive
Copy link
Collaborator

r? @brson

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

@brson
Copy link
Contributor

brson commented Dec 28, 2015

@bors r+ rollup

@bors
Copy link
Contributor

bors commented Dec 28, 2015

📌 Commit a1f3781 has been approved by brson

@steveklabnik
Copy link
Member Author

@bors: r-

@steveklabnik
Copy link
Member Author

This failed with a segfault on travis. I thought that my local build worked, double checking now.

@steveklabnik
Copy link
Member Author

Wow, this does segfault locally, and also with this small second change that @aturon pointed out.

Maybe there is some kind of magic in the original mess there...

@steveklabnik
Copy link
Member Author

re-reading again, I noticed that there was one level of indirection at one arm, and another at the other arm. So I did this third commit, and it also segfaults.

At this point, I'm just wondering what magic here is causing this...

if ptr as *mut u8 as usize == 0 || ptr as *mut u8 as usize == mem::POST_DROP_USIZE {
let thin = ptr as *const ();

if !thin.is_null() && thin as usize != mem::POST_DROP_USIZE {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you invert the condition?

It should either be if thin.is_null() || thin as usizee == mem::POST_DROP_USIZE or if !(!thin.is_null() && thin as usize != mem::POST_DROP_USIZE). What you wrote is not equivalent to the old code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... because even simple code is hard. that'd do it, i'd bet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to abstract the condition to a function, so that it can be given a name and re-used? The code itself is trivial, but it's still easy to get it wrong. if already_dropped(ptr) { return; } (or any other better name) would be easy to read and convey the information about what is going on in both places (currently the check at https://github.com/steveklabnik/rust/blob/small_rc_refactoring/src/liballoc/arc.rs#L715 refers to the comment of the other code fragment, which finally explains what is going on).

@steveklabnik
Copy link
Member Author

This no longer segfaults, but it still fails several Arc tests. I have to run, I will fix the tests in the morning. I'm sure I just did something else dumb, time to bust out some truth tables.

@steveklabnik
Copy link
Member Author

Okay! Finally got it to pass. I was just being silly. I've squashed and rebased everything.

@Gankra
Copy link
Contributor

Gankra commented Dec 29, 2015

Is the fact that the two files are divergent intentional?

@steveklabnik
Copy link
Member Author

They were before I got here.

@Gankra
Copy link
Contributor

Gankra commented Dec 30, 2015

Is there a reason to preserve the divergence?

ptr as *const () as usize != mem::POST_DROP_USIZE {
let thin = ptr as *const ();

if !(thin as *const *const ()).is_null() && thin as usize != mem::POST_DROP_USIZE {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular this cast to *const *const () seems pointless?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had re-added it when @aturon pointed out that I was missing the second level. I thought it was pointless, but I thought it might have been causing the segfaults.

On Dec 29, 2015, 19:30 -0500, Alexis Beingessnernotifications@github.com, wrote:

Insrc/liballoc/rc.rs(#30593 (comment)):

@@ -782,8 +782,9 @@ impl<T: ?Sized>Drop for Weak{>fn drop(&mut self) {>unsafe {>let ptr = _self.ptr;>- if !((&ptr as *const _ as *const *const ())).is_null()&&>- ptr as *const () as usize != mem::POST_DROP_USIZE {>+ let thin = ptr as *const ();>+>+ if !(thin as *const *const ()).is_null()&&thin as usize != mem::POST_DROP_USIZE {

In particular this cast seems pointless?


Reply to this email directly orview it on GitHub(https://github.com/rust-lang/rust/pull/30593/files#r48580830).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's causing the segfaults, this should be filed as a bug.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bug open for it generally, I think #30577

but I'm not sure yet, as I didn't really dig into the why.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does work without this cast. PR updated.

@steveklabnik
Copy link
Member Author

Is there a reason to preserve the divergence?

No, other than I'm not the person to write that patch, just trying to do a small cleanup here.

@ranma42
Copy link
Contributor

ranma42 commented Dec 30, 2015

@steveklabnik
Copy link
Member Author

Only because I didn't notice them! I'll do that right now.

@steveklabnik
Copy link
Member Author

@gankro oh, did you mean the divergence of the ! || == != stuff? Yes, there's no reason to preserve that divergence. I thought you meant other things in the file. I'm testing a thing right now with them all having completely identical conditionals, now that I know that the extra cast isn't needed.

@Gankra
Copy link
Contributor

Gankra commented Dec 30, 2015

The & vs | divergence I'm kinda fine with preserving. iirc it "makes sense" for each drop impl.

@steveklabnik
Copy link
Member Author

Okay, so this is very strange:

diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 9109e9d..8318607 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -784,7 +784,7 @@ impl<T: ?Sized> Drop for Weak<T> {
             let ptr = *self._ptr;
             let thin = ptr as *const ();

-            if !thin.is_null() && thin as usize != mem::POST_DROP_USIZE {
+            if thin.is_null() || thin as usize == mem::POST_DROP_USIZE {
                 self.dec_weak();
                 // the weak count starts at 1, and will only go to zero if all
                 // the strong pointers have disappeared.

This diff causes a segfault.

@Gankra
Copy link
Contributor

Gankra commented Dec 30, 2015

That's because it's the exact opposite of the check. You now dec_weak only if the pointer is null or dropped.

You left out a negation in your demorgans.

@steveklabnik
Copy link
Member Author

Oh duh. It still probably shouldn't segfault, but yes, I am just being dumb. :(

@Gankra
Copy link
Contributor

Gankra commented Dec 30, 2015

Nah derefing null/dangling ptrs is pretty much the definition of "should segfault"

@steveklabnik
Copy link
Member Author

I guess this is unsafe.

I should like, not write code until 2pm or something.

@steveklabnik
Copy link
Member Author

I have fixed my errors and also handled the two other places as well.

This hairy conditional doesn't need to be so. It _does_ need to be a
thin pointer, otherwise, it will fail to compile, so let's pull that out
into a temporary for future readers of the source.

Also, after a discussion with @pnkfelix and @gankro, we don't need these
null checks anymore, as zero-on-drop has been gone for a while now.
@steveklabnik
Copy link
Member Author

@pnkfelix and @gankro noticed that we don't need the null checks anymore, either 👍

@Gankra
Copy link
Contributor

Gankra commented Dec 30, 2015

@bors r+

WE DID IT

@bors
Copy link
Contributor

bors commented Dec 30, 2015

📌 Commit 2cff12e has been approved by Gankro

@bors
Copy link
Contributor

bors commented Dec 31, 2015

⌛ Testing commit 2cff12e with merge 8aee582...

bors added a commit that referenced this pull request Dec 31, 2015
This hairy conditional doesn't need to be so. It _does_ need to be a
thin pointer, otherwise, it will fail to compile, so let's pull that out
into a temporary for future readers of the source.

/cc @nrc @SimonSapin @gankro @durka , who brought this up on IRC
@bors bors merged commit 2cff12e into rust-lang:master Dec 31, 2015
@steveklabnik steveklabnik deleted the small_rc_refactoring branch June 19, 2016 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants