Code change:
Consider the following code with custom DSTs: The generated assembly for x86_64 is as follows (with my comments ): This can be seen on . Why does the compiler check for zero alignment? It seems that it's impossible, as the alignment cannot be zero. :
Why alignment can't be zero ? Are you sure it's check for alignment ? As I read the asm using for ref: test if is zero, use 1 as default, move rcx if it was not zero. make sense for me but asm is not my field of expertise and even less vtable so I don't really understand why put 1 instead of just move rcx assuming the alignment should be correct but I guess I miss a crucial information about rust internal. I guess is why rust need to test since it's "maybe" sized
Adding gets me So, at least as far as the compiler is concerned, there is no obvious reason it could not be a zero-sized type. I could believe this is a missed optimization, where the compiler could infer that because of the i8 field, it has to be aligned to at least 1, but I do not believe it is a bug. It seems to satisfy the current reasoning around alignment and DSTs.
As stated in , Yes. The references to consist of two pointers, one of with is a base pointer ( in the assembly above) and the second one ( in the assembly above) is the pointer to vtable. The entry of vtable with index (written as in assembly) is the alignment (as it can be seen ).
How does the compilation error above indicate that? Also, ZSTs has alignment 1, as you can check using Why it's not a bug? The compiler generates a seemingly unnecessary instruction, which is an optimization issue. I agree that the issue is quite minor, though, and most probably it doesn't cause observable slowdown. Maybe there are some reasons why the alignment in vtable can be zero, but it seems to contradict the documentation.
I fail to see any explanation in the link that say that, is about the alignment of the vtable not its position or whatever registry contain it. For me it's make more sense it's the size of the object or something, why this code would need the vtable anyway ? It's probably search the alignement of to know the offset of the strucutre: Again just random guess.
It's the alignment of the type corresponding to this vtable, not the alignment of vtable itself. Yes, it is. The issue is that while calculating the offset dynamically, it does redundantly check whether the alignment is zero.
why do you suppose rust internal doesn't need this ? having a zero alignment could mean something like unknown alignment ? I mean you first need to prove test for zero is useless before say it's seem useless. We don't know for sure what Rust really need to do here, the type is dyn, maybe Sized. That not trivial, one should perfectly know Rust internal to know if this check is useless. Sorry for my poor knowledge in this if my comment are just losing your time just ignore them, I just try to understand your point.
I didn't dive into Rust internals code, but I know that the compiler doesn't always check for zero alignment. Here's the example: gives just But, even if I add the transparent wrapper, the check for zero is generated. See the following example: The generated assembly becomes much more complex: I don't have an idea on why the check happens. If it's omitted sometimes, then the compiler kind of knows that the alignment in vtables cannot be zero, yet it generates the check in a more complex example.
I think the diff is caused by versus but you use transparent so here I agree with you it's look strange. You convince me.
This check is generated by the following code: and is used to determine the runtime alignment of the field, which is . In the general case, this check is required, because the alignment of may be 1. You can see this if you change the field in to an , which has 2-byte alignment: In the specific cases you've identified, where the alignment of is 1, I agree that it is unnecessary. When loading alignment from the vtable, we should be adding range metadata to tell LLVM that it's nonzero. (opened for this)

Related discussion:
text: <ins> // compile-flags: -O #![crate_type = "lib"] // This test checks that we annotate alignment loads from vtables with nonzero range metadata, // and that this allows LLVM to eliminate redundant `align >= 1` checks. pub trait Trait { fn f(&self); } pub struct WrapperWithAlign1<T: ?Sized> { x: u8, y: T } pub struct WrapperWithAlign2<T: ?Sized> { x: u16, y: T } pub struct Struct<W: ?Sized> { _field: i8, dst: W, } // CHECK-LABEL: @eliminates_runtime_check_when_align_1 #[no_mangle] pub fn eliminates_runtime_check_when_align_1( x: &Struct<WrapperWithAlign1<dyn Trait>> ) -> &WrapperWithAlign1<dyn Trait> { // CHECK: load [[USIZE:i[0-9]+]], {{.+}} !range [[RANGE_META:![0-9]+]] // CHECK-NOT: icmp // CHECK-NOT: select // CHECK: ret &x.dst } // CHECK-LABEL: @does_not_eliminate_runtime_check_when_align_2 #[no_mangle] pub fn does_not_eliminate_runtime_check_when_align_2( x: &Struct<WrapperWithAlign2<dyn Trait>> ) -> &WrapperWithAlign2<dyn Trait> { // CHECK: [[X0:%[0-9]+]] = load [[USIZE]], {{.+}} !range [[RANGE_META]] // CHECK: [[X1:%[0-9]+]] = icmp {{.+}} [[X0]] // CHECK: [[X2:%[0-9]+]] = select {{.+}} [[X1]] // CHECK: ret &x.dst } // CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] 0} </ins>