Skip to content

Const-generics don't work with constants #69816

@Boscop

Description

@Boscop

This compiles:

use arrayvec::{Array, ArrayVec};

#[ext(pub, name = IterExt)]
impl<T: Iterator<Item = U>, U> T {
    fn collect_arr<const N: usize>(self) -> [U; N]
    where
        [U; N]: Array<Item = U>,
        ArrayVec<[U; N]>: Debug,
    {
        self.collect::<ArrayVec<[U; N]>>().into_inner().expect("collect_arr")
    }
}

(Using the extend and arrayvec crates.)

But using it with a constant doesn't compile:
image

Even though pub const CUE_POINT_COUNT: usize = 8; is in scope!
If I write .collect_arr::<8usize>() instead, it compiles.
Also, if I don't use the extension trait method but inline it (.collect::<ArrayVec<[_; CUE_POINT_COUNT]>>().into_inner().unwrap()) it works with the constant!
So for some reason rustc can't see that CUE_POINT_COUNT == 8 here.

Activity

rodrimati1992

rodrimati1992 commented on Mar 8, 2020

@rodrimati1992
Contributor

Sorry for all the edits,apparently this only errors if the function is a method, when defined as a free function it doesn't error.

As a method

When it's defined as a method,this code:

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=cdf1b7f44fe0c7ae24ef2df775f841d8

#![feature(const_generics)]

use arrayvec::{Array, ArrayVec};
use std::fmt::Debug;

trait IterExt: Sized + Iterator {
    fn collect_arr<const N: usize>(self) -> [Self::Item; N]
    where
        [Self::Item; N]: Array<Item = Self::Item>,
        ArrayVec<[Self::Item; N]>: Debug,
    {
        self.into_iter()
            .collect::<ArrayVec<[Self::Item; N]>>()
            .into_inner()
            .expect("collect_arr")
    }
}

impl<This:Iterator> IterExt for This{}

fn main(){
    const N:usize=10;
    let arr:[u32;10]=(0..10).collect_arr::<N>();
}
Emits this error message
error[E0277]: the trait bound `[{integer}; _]: arrayvec::array::Array` is not satisfied
  --> src/main.rs:24:30
   |
24 |     let arr:[u32;10]=(0..10).collect_arr::<N>();
   |                              ^^^^^^^^^^^ the trait `arrayvec::array::Array` is not implemented for `[{integer}; _]`
   |
   = help: the following implementations were found:
             <[T; 0] as arrayvec::array::Array>
             <[T; 100] as arrayvec::array::Array>
             <[T; 1024] as arrayvec::array::Array>
             <[T; 10] as arrayvec::array::Array>
           and 53 others

error[E0308]: mismatched types
  --> src/main.rs:24:22
   |
24 |     let arr:[u32;10]=(0..10).collect_arr::<N>();
   |             -------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `10usize`, found `N`
   |             |
   |             expected due to this
   |
   = note: expected array `[u32; 10]`
              found array `[{integer}; _]`

Curiously,by changing the method call line to
let arr:[u32;10]=IterExt::collect_arr::<N>((0..10));
it compiles without errors.
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=7aff9f76b3d31e931ef1b66077d40e6f

As a free function

When it's defined as a free function no error happens:

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9e7bae5d74089c7177aaa22226e1013c

#![feature(const_generics)]

use arrayvec::{Array, ArrayVec};
use std::fmt::Debug;

fn collect_arr<T, const N: usize>(this: T) -> [T::Item; N]
where
    T: IntoIterator,
    [T::Item; N]: Array<Item = T::Item>,
    ArrayVec<[T::Item; N]>: Debug,
{
    this.into_iter()
        .collect::<ArrayVec<[T::Item; N]>>()
        .into_inner()
        .expect("collect_arr")
}

fn main(){
    const N:usize=10;
    let arr:[u32;10]=collect_arr::<_,N>(0..10);
}
rodrimati1992

rodrimati1992 commented on Mar 8, 2020

@rodrimati1992
Contributor

This is the most minimal code I could get to output a very similar error:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=f45606455c01151f0b16cd1484b3222c

#![feature(const_generics)]

trait IterExt: Sized + Iterator {
    fn default_for_size<const N: usize>(self) -> [Self::Item; N]
    where
        [Self::Item; N]: Default,
    {
        Default::default()
    }
}

impl<This:Iterator> IterExt for This{}

fn main(){
    const N:usize=10;
    let arr:[u32;10]=(0..10).default_for_size::<N>();
}
The error message for that code
error[E0277]: the trait bound `[{integer}; _]: std::default::Default` is not satisfied
  --> src/main.rs:16:30
   |
16 |     let arr:[u32;10]=(0..10).default_for_size::<N>();
   |                              ^^^^^^^^^^^^^^^^ the trait `std::default::Default` is not implemented for `[{integer}; _]`
   |
   = help: the following implementations were found:
             <&[T] as std::default::Default>
             <&mut [T] as std::default::Default>
             <[T; 0] as std::default::Default>
             <[T; 10] as std::default::Default>
           and 31 others

error[E0308]: mismatched types
  --> src/main.rs:16:22
   |
16 |     let arr:[u32;10]=(0..10).default_for_size::<N>();
   |             -------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `10usize`, found `N`
   |             |
   |             expected due to this
   |
   = note: expected array `[u32; 10]`
              found array `[{integer}; _]`
added
A-const-genericsArea: const generics (parameters and arguments)
C-bugCategory: This is a bug.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Mar 8, 2020
Boscop

Boscop commented on Mar 8, 2020

@Boscop
Author

@rodrimati1992 But your minimized example behaves differently when writing 10usize instead of N! Instead of compiling fine (like with my original example), the compiler panics:

error: internal compiler error: unexpected const parent in type_of_def_id(): Expr(expr(HirId { owner: DefIndex(10), local_id: 20 }: ::std::ops::Range{start: 0, end: 10,}.default_for_size::<>()))

error: internal compiler error: mir_const_qualif: MIR had errors
  --> src/main.rs:16:49
   |
16 |     let arr:[u32;10]=(0..10).default_for_size::<10usize>();
   |                                                 ^^^^^^^

error: internal compiler error: PromoteTemps: MIR had errors
  --> src/main.rs:16:49
   |
16 |     let arr:[u32;10]=(0..10).default_for_size::<10usize>();
   |                                                 ^^^^^^^

error: internal compiler error: broken MIR in DefId(0:13 ~ playground[a375]::main[0]::{{constant}}[1]) ("return type"): bad type [type error]
  --> src/main.rs:16:49
   |
16 |     let arr:[u32;10]=(0..10).default_for_size::<10usize>();
   |                                                 ^^^^^^^

error: internal compiler error: broken MIR in DefId(0:13 ~ playground[a375]::main[0]::{{constant}}[1]) (LocalDecl { mutability: Mut, local_info: Other, internal: false, is_block_tail: None, ty: [type error], user_ty: UserTypeProjections { contents: [] }, source_info: SourceInfo { span: src/main.rs:16:49: 16:56, scope: scope[0] } }): bad type [type error]
  --> src/main.rs:16:49
   |
16 |     let arr:[u32;10]=(0..10).default_for_size::<10usize>();
   |                                                 ^^^^^^^

thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:355:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

error: internal compiler error: unexpected panic

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=2bbd3b7f2d16e643a8dedb82659aa0c4

Boscop

Boscop commented on Mar 8, 2020

@Boscop
Author

Btw, instead of writing 8usize in .collect_arr::<8usize>(), the compiler should be able to infer that 8 is an usize. IOW, this should compile: .collect_arr::<8>(). Is there already a ticket for this?

10 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-const-genericsArea: const generics (parameters and arguments)A-inferenceArea: Type inferenceC-bugCategory: This is a bug.F-const_generics`#![feature(const_generics)]`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

      Participants

      @Boscop@Centril@rodrimati1992

      Issue actions

        Const-generics don't work with constants · Issue #69816 · rust-lang/rust