Skip to content
This repository has been archived by the owner on Nov 27, 2020. It is now read-only.

PanicAdapter + panic auditing #12

Closed
wants to merge 10 commits into from

Conversation

Ericson2314
Copy link
Contributor

@Ericson2314 Ericson2314 commented Nov 30, 2019

As done in rust-lang/rust#60703, I make a PanicAdapter to be the one place we call handle_alloc_error, and carefully thread Error = ! everywhere else (which forces the use of PanicAdapter, something similar, or a magic allocator which truely never fails.

The old way is still much better than the status quo, to be clear, but makes it harder to audit code for allocation handling. Any library, anywhere, may call the regular methods instead of the try_ methods, making it hard to rely on crates.io. The panics are strewn about, and it is hard on the library maintainers to remember what the invariants are.

But with this way, all one needs to do is make sure PanicAdapter is never emitted (check debug symbols perhaps?) and one can be sure that there are no accidental panics by a third party, as the regular methods will be uncallable. (They still can explicitly panic, of course, but that's a lot less likely to be done by accident.)

Taking a step back, people that really care about handling all control flow, and existing users of the standard library simply require different interfaces. Anything less than the full try_ sweet, with ways to guard against the use of the "other half", does a disservice to the control-flow-concious crowd. The conventional wisdom is that we cannot satisfy that need without an entire new stdlib; this PR is meant to show that in fact we can; the interfaces grows faster than the implementation so it's sustainable.

Less this all seem academic, I will point out some cases of tricky allocation failure that I was forced by the types to catch below.

@@ -1819,7 +1822,7 @@ impl<A: DeallocRef> String<A> {
/// # Panics
///
/// Panics if the starting point or end point do not lie on a [`char`]
/// boundary, or if they're out of bounds.
/// boundary, or if they're out of bounds, or if there is an allocation failure
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Previous undocumented panic condition. Splice potentially allocating on drop is a very subtle edge case it's super easy to forget!


impl<T> UncheckedOptionExt<T> for Option<T> {
unsafe fn unwrap_unchecked(self) -> T {
if let Some(t) = self { t } else { unreachable() }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know what the justification of all this was; good thing we don't need it anymore!

@Ericson2314 Ericson2314 force-pushed the infallibility branch 2 times, most recently from 6eaa40f to 005f1b5 Compare November 30, 2019 06:46
@Ericson2314
Copy link
Contributor Author

Ericson2314 commented Nov 30, 2019

Huh. Not sure where this test failure is coming from. It shows up after the second commit, so it must have something to do with the first two. (The first alone doesn't test PanicAdapter.)

@TimDiekmann
Copy link
Owner

Thanks for the PR.

How does this implementation differ from the removed AbortAlloc?

The test failed for the exact same reason why I removed AbortAlloc: it's design is flawed. It tries to allocate isize::MAX and ignores the allocation error. With the panic adaptor it will abort even before try_reserve returns.

@TimDiekmann
Copy link
Owner

Closing in favor of Abort trait.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants