Change:
While trying to isolate what kinds of preconditions the trait is going to require and post-conditions it ensures, I made a test program to explore what happens with our current pair of low-level allocators. As far as I can tell so far, jemalloc always ensures that it never gives back an unaligned address. but on OS X, the system allocator (linked via ) can produce addresses that do not meet the alignment request, namely if you ask for values with starting addresses of alignment greater than or equal to . (Like i said, we're talking about huge alignments here.) (on Linux, for both jemalloc and the system allocator, I never observed either returning non-null addresses that did not meet the alignment request. In other words, they handled absurdly large alignments "properly") I talk a little about this further in my Digression section below, but in summary, I think we should do something about this. It seems like an easy short term solution is this: We should be able to pre-determine which allocator + platform combinations fall victim to this problem, and for those cases, make the (and , etc) methods validate their results. If validation fails, then we can just free the original address and return null. The main problem with this is that it adds overhead to the allocation path. (Admittedly a (aka divide) and branch doesn't seem like much in the context of an allocation, but still...) Anyway, if you're interested in alternative ideas, see the Digression/Discussion section below When Rust the jemalloc support PR, it stated the following requirement on the method: depending on what the phrase "the largest supported page size" is supposed to mean, perhaps even moderately sized values are not legal inputs for the alignment... (was that phrase supposed to be something like "allocated block size" rather than "page size" ? The notion of more than one memory page size on a given platform is not something I'm familiar with...) ... so arguably there has always been a precondition to not feed in ridiculously large values for alignment. However, even if that is the case, here are some things to consider if we want to continue to impose this precondition, then we must provide the programmer with a way to query what the value of "the largest supported page size on the platform" actually is. (I didn't see a way to do this via a couple of greps of the code base, but it doesn't help that I don't understand what is actually meant by the above phrase.) (I don't think the phrase is meant to denote the same thing as ; so I don't think that would be a way to query the actual value, though certainly it would provide a bound that a programmer can use in the meantime...) IMO, if we were to add a method to query the value of "largest supported alignment", it should be part of the low-level allocator interface (see ), since presumably the largest supported value would be connected to the allocator implementation. Given that at least some alloc-crate + target combinations are not imposing the above requirement (in the sense that they return null when the given alignment is unsatisfiable), it seems somewhat reasonable to me to add the post-allocation check that I described above, as long as we do it in a conditionalized manner. Instead of conditionalizing based on the target OS, we might be able to write the injected code in a way where the compiler can optimize away the check when the given alignment is known and falls beneath some reasonable bound, like , working under the assumptions that all allocators will behave properly with such an input. (I suspect in a vast number of cases, the alignment is statically known, so this would probably be a fine solution.) Also, the man page for on my version of OS X says nothing about an upper bound on the value for . This to me indicates that this is a bug in OS X itself, which we can report and workaround via post-validation in the short term. (If we did conditionalize based on target OS, then longer term, I don't know how we would best deal with trying to conditionally inject the post-validation in question; perhaps the default crate linking could choose between the two variants depending on which version of OS X is targetted.) Here is that sample program (you can toggle the different allocates with or ). When you run it, the thing to look for is when there is an output line that has on the end, which is only printed for non-zero remainder (when one divides the address by the alignment). (Also, here's a , though I repeat that the problematic behavior does not exhibit itself on versions of Linux that I have tried.) ((Updated to fit new )) See following gist:
Another possible course of action could be just saying that alignment over some reasonably high value is not guaranteed to be respected and part of the contract of these functions is that you need to respect that. That being said some post-validation seems pretty harmless to me!
I would place that into the "Requirements should be checkable" bucket. I don't mind it personally, as long as someone would specify the "reasonably high value" in question.
The Windows system allocator has no way to specify alignment so the Rust code that invokes it is responsible for over-allocating and aligning. Therefore any concerns about whether it handles silly huge alignments can easily be resolved by just fixing the Rust code if any problems turn up.

Discussion:
impl Layout { /// Constructs a `Layout` from a given `size` and `align`, <del> /// or returns `None` if either of the following conditions </del> <ins> /// or returns `None` if any of the following conditions </ins> /// are not met: /// /// * `align` must be a power of two, /// <ins> /// * `align` must not exceed 2^31 (i.e. `1 << 31`), /// </ins> /// * `size`, when rounded up to the nearest multiple of `align`, ///    must not overflow (i.e. the rounded value must be less than ///    `usize::MAX`).

return None; } <ins> if align > (1 << 31) { return None; } </ins> // (power-of-two implies align != 0.) // Rounded up size is:

/// /// # Unsafety /// <del> /// This function is unsafe as it does not verify that `align` is a power of /// two nor that `size` aligned to `align` fits within the address space. </del> <ins> /// This function is unsafe as it does not verify that `align` is /// a power-of-two that is also less than or equal to 2^31, nor /// that `size` aligned to `align` fits within the address space /// (i.e. the `Layout::from_size_align` preconditions). </ins> #[inline] pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Layout { Layout { size: size, align: align }

Some(alloc_size) => alloc_size, }; <del> // We can assume that `self.align` is a power-of-two. // Furthermore, `alloc_size` has alreayd been rounded up // to a multiple of `self.align`; therefore, the call // to `Layout::from_size_align` below should never panic. </del> <ins> // We can assume that `self.align` is a power-of-two that does // not exceed 2^31. Furthermore, `alloc_size` has already been // rounded up to a multiple of `self.align`; therefore, the // call to `Layout::from_size_align` below should never panic. </ins> Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size)) }