Skip to content

Const generics in closure arguments result in false "closure/generator type that references itself" error #85665

Open
@mastopgunaf

Description

@mastopgunaf

I tried compiling this code:

#![feature(const_generics)]
#![feature(const_evaluatable_checked)]

use std::convert::TryInto;

pub const PREFIX_LENGTH: usize = 4;

pub struct Foo<T, const L: usize> {
    template: &'static [u8; L],
    item: T
}

impl<T, const L: usize> Foo<T, L> {
    pub fn new<F>(template: &'static [u8; L], constructor: F) -> Self
        where F: Fn(&[u8; L - PREFIX_LENGTH]) -> T
    {
        Self {
            template: template,

            item: constructor(
                &TryInto::<[u8; L - PREFIX_LENGTH]>::try_into(
                    &template[PREFIX_LENGTH..]
                ).unwrap()
            )
        }
    }

    pub fn get(&self) -> &T {
        &self.item
    }
}

const TEMPLATE: &[u8; 12] = b"ABCD12345678";

fn main() {
    let foo = Foo::new(TEMPLATE,
        |x| x.to_vec()
    );

    println!("{}",
        String::from_utf8(
            foo.get().clone()
        ).unwrap()
    );
}

The output is supposed to be 12345678, but instead the compiler throws an error:

error[E0644]: closure/generator type that references itself
  --> src/main.rs:37:9
   |
37 |         |x| x.to_vec()
   |         ^^^^^^^^^^^^^^ cyclic type of infinite size
   |
   = note: closures cannot capture themselves or take themselves as argument;
           this error may be the result of a recent compiler bug-fix,
           see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
           for more information

However, the code above doesn't include closures that capture themselves or take themselves as an argument.

The bug is most likely related to const generics, because omitting - PREFIX_LENGTH such that the const_generics feature is not used fixes the compilation. new function in this case is as follows:

    pub fn new<F>(template: &'static [u8; L], constructor: F) -> Self
        where F: Fn(&[u8; L]) -> T
    {
        Self {
            template: template,

            item: constructor(
                &TryInto::<[u8; L]>::try_into(
                    &template[..]
                ).unwrap()
            )
        }
    }

rustc --version --verbose:

rustc 1.54.0-nightly (126561cb3 2021-05-24)
binary: rustc
commit-hash: 126561cb31e8ebe1e2dd9dfd0d3ca621308dc56f
commit-date: 2021-05-24
host: x86_64-unknown-linux-gnu
release: 1.54.0-nightly
LLVM version: 12.0.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-const-genericsArea: const generics (parameters and arguments)C-bugCategory: This is a bug.F-generic_const_exprs`#![feature(generic_const_exprs)]`P-lowLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.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