Skip to content

generic_const_exprs and a (non const generic) array size expression allow recursive generic type parameters #108725

Open
@peter-lyons-kehl

Description

@peter-lyons-kehl

The following does compile (surprisingly - as opposed to #53191):

#![allow(incomplete_features)]

// Without `generic_const_exprs`, this fails to compile and `T` is reported as "never unused",
// regardless of whether the array size below is a (`const`) expression (`0*0`) or a literal (`0`).
//
// Note that `generic_const_exprs` "shouldn't" need to be required for this at all - there are no
// `const` generic parameters here.
#![feature(generic_const_exprs)]

// Based on LeafNode and InternalNode in BTreeMap's internals.
pub struct Node<T> {
    // When we change the array size from a `const` expression  (such as `0*0`) to a literal (such
    // as `0`), we get an error: parameter `T` is never used.
    //
    // For anyone using this as a workaround (instead of `PhantomData`): Even if you have `0*0` as
    // the array size here (and hence it takes no space), such an empty array field can affect
    // alignment its owner struct.
    _links: [Option<Box<Node<T>>>; 0*0],
}

However, the same code (without comments), and with the only change being in the array size changed from a (const) expression 0*0 to a literal 0, then fails to compile:

#![allow(incomplete_features)]
#![feature(generic_const_exprs)]

pub struct Node<T> {
    _links: [Option<Box<Node<T>>>; 0], // <-- array size changed from 0*0 to 0
}

The problem reported here is not whether this should compile or not. Rather, it's the inconsistency depending on the array size's being an expression vs. literal.

But while you're at it, please also shed some light on the the intended behavior, or planned behavior.

Side note: Putting the array size within braces makes it compile, too:

#![allow(incomplete_features)]
#![feature(generic_const_exprs)]

pub struct Node<T> {
    #[allow(unused_braces)]
    _links: [Option<Box<Node<T>>>; {0}],
}

Motivation: This took hours to pinpoint/minimize (while I was hoping to minimize another issue, so that I can progress with co-allocation in library/alloc). So I hope this will save people's time.

Update: The above minimization is not fully narrowed down - beyond my current bandwidth. Under some circumstances, recursive types with a generic parameter that is used solely for recursion (that is, not in any PhantomData-based field) do compile even without generic_const_exprs. See LeafNode and InternalNode in BTreeMap's internals: it compiles, even though library/alloc/src/lib.rs does not use generic_const_exprs. (NodeRef itself does use PhantomData, but the (indirectly) recursive types LeafNode and InternalNode themselves do not.)
However, that doesn't affect the inconsistency reported in this ticket.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.F-generic_const_exprs`#![feature(generic_const_exprs)]`requires-incomplete-featuresThis issue requires the use of incomplete features.requires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions