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

Clean up the stack implementations #54

Closed
wants to merge 1 commit into from
Closed

Conversation

Amanieu
Copy link
Collaborator

@Amanieu Amanieu commented Sep 17, 2016

Changes:

  • The valgrind stuff is moved out of the generators and into the stack implementations.
  • Stack is now an unsafe trait since it has a contract that must be upheld by an implementation.
  • SliceStack will now automatically align a slice on construction. However this means that its fields are now private.
  • Various cleanups and moving code around.

@whitequark
Copy link
Contributor

First, can you please separate the "clean ups" into distinct commits?

The valgrind stuff is moved out of the generators and into the stack implementations.

Uh, how about no. Now anyone implementing a stack externally will now have to 1) implement the Valgrind interface 2) implement interfaces of any other debugging tools we may be interested in the future 3) predicate on the architecture-specific availability of Valgrind themselves. This significantly decreases ergonomics (and also it's not a cleanup, it creates duplication).

SliceStack will now automatically align a slice on construction. However this means that its fields are now private.

Again, how about no. This makes it completely useless for its original purpose, that is using a static mut for a stack, since you cannot construct it. You could as well just remove SliceStack entirely now.

@Amanieu
Copy link
Collaborator Author

Amanieu commented Sep 17, 2016

Again, how about no. This makes it completely useless for its original purpose, that is using a static mut for a stack, since you cannot construct it. You could as well just remove SliceStack entirely now.

Can't you just use a static mut [u8; N] and create a SliceStack from that?

Uh, how about no. Now anyone implementing a stack externally will now have to 1) implement the Valgrind interface 2) implement interfaces of any other debugging tools we may be interested in the future 3) predicate on the architecture-specific availability of Valgrind themselves. This significantly decreases ergonomics (and also it's not a cleanup, it creates duplication).

The motivation here was to associate the debug info with the stacks rather than with the generators. Consider the case where a stack is reused for multiple generators, this would cause the stack to be registered and de-registered multiple times.

///
/// This function will automatically align the slice to make it suitable for
/// use as a stack. However this function may panic if the slice is smaller
/// than `STACK_ALIGNMENT`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Where does it panic in release builds?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This may panic even in release builds: &mut slice[offset..(offset + adjusted_len)]

Copy link
Contributor

Choose a reason for hiding this comment

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

Worth a comment, I think.

@whitequark
Copy link
Contributor

The motivation here was to associate the debug info with the stacks rather than with the generators. Consider the case where a stack is reused for multiple generators, this would cause the stack to be registered and de-registered multiple times.

I don't see how this is a problem. You're sacrificing ergonomics in a misguided attempt to improve efficiency of a feature only useful for debugging in the first place. (And we should also gate the valgrind stuff behind #[cfg(build = "debug")].)

Can't you just use a static mut [u8; N] and create a SliceStack from that?

Hm, I tried that and encountered some sort of problem, but I don't recall it now. Disregard that comment then.

That said, if SliceStack::new didn't mess with valgrind then it could be a const fn.

@Amanieu
Copy link
Collaborator Author

Amanieu commented Sep 17, 2016

I reverted the valgrind changes.

@whitequark
Copy link
Contributor

LGTM. SliceStack's new can be made a const fn later if necessary, or the field exposed anyway, or something to that degree. As it is it is definitely nicer than what I had, so your change there is a net win.

@whitequark
Copy link
Contributor

There's no real point in making Stack unsafe but since people persistently point that out I suppose there is no real harm either.

@Amanieu
Copy link
Collaborator Author

Amanieu commented Sep 17, 2016

I don't think SliceStack::new can be made a const fn since it needs to inspect the address of the slice to ensure that it is properly aligned.

Also, publicly exposing the field would allow safety violations (in particular, the alignment restriction won't be enforced).

@whitequark
Copy link
Contributor

I don't think SliceStack::new can be made a const fn since it needs to inspect the address of the slice to ensure that it is properly aligned.

Right.

Also, publicly exposing the field would allow safety violations (in particular, the alignment restriction won't be enforced).

Using SliceStack is already unsafe since it provides no guard page; exposing the field could be seen as inelegant design since it lets you violate what's supposed to be an invariant, but it does not add any more unsafety.

let adjusted_len = (slice.len() - offset) & !(::STACK_ALIGNMENT - 1);

// This may panic if offset is larger than the size of the slice
SliceStack(&mut slice[offset..(offset + adjusted_len)])
Copy link
Contributor

Choose a reason for hiding this comment

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

Please group these two panics into one explicit one, and write a test for both conditions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The only panic is the explicit one. adjusted_len is guaranteed to be less than slice.len() - offset.

Copy link
Contributor

Choose a reason for hiding this comment

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

So the comment is wrong now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oops, forgot about that one. Fixed.

Copy link
Contributor

Choose a reason for hiding this comment

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

And the test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Test added.

}
}

#[cfg(test)]
Copy link
Contributor

Choose a reason for hiding this comment

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

These tests don't poke into any implementation details as far as I see, so shouldn't they go to tests/?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well I feel that the precise behavior of whether it panics or not is a bit of an implementation detail. The only thing the interface guarantees is that it won't panic if the slice is larger than STACK_ALIGNMENT, and it may panic if it is smaller.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's a weird contract...

@Amanieu
Copy link
Collaborator Author

Amanieu commented Sep 29, 2016

I moved the tests into tests/stack.rs.

@Amanieu Amanieu changed the base branch from master to next-major September 29, 2016 17:35
@Amanieu Amanieu changed the base branch from next-major to master September 29, 2016 17:39
@edef1c edef1c closed this in 400adf3 Oct 1, 2016
edef1c pushed a commit that referenced this pull request Feb 25, 2017
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.

None yet

2 participants