Skip to content

Missed optimization when using const-blocks for MaybeUninit arrays #138625

Closed
@kmdreko

Description

@kmdreko

Please see the assembly from these functions (Rust 1.85.0 --release):

use std::mem::MaybeUninit;

pub struct SmallVec<T> {
    pub len: usize,
    pub arr: [MaybeUninit<T>; 24],
}

#[unsafe(no_mangle)]
pub fn uninit_arr_via_const() -> SmallVec<String> {
    SmallVec { len: 0, arr: [const { MaybeUninit::uninit() }; 24] }
}

#[unsafe(no_mangle)]
pub fn uninit_arr_via_assume_init() -> SmallVec<String> {
    SmallVec { len: 0, arr: unsafe { MaybeUninit::uninit().assume_init() } }
}
uninit_arr_via_const:
	pushq	%rbx
	movq	%rdi, %rbx
	movl	$584, %edx
	xorl	%esi, %esi
	callq	*memset@GOTPCREL(%rip)
	movq	%rbx, %rax
	popq	%rbx
	retq

uninit_arr_via_assume_init:
	movq	%rdi, %rax
	movq	$0, 576(%rdi)
	retq

The const {} variant compiles with code that seems to zero-out the arr field. This should not be necessary and the other version (correctly) only initializes the len field.

This is particularly troublesome because the documentation in multiple places expresses that const-blocks are the preferred way to create a [MaybeUnint; _].

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationC-bugCategory: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions