Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Const-generics don't work with constants #69816

Closed
Boscop opened this issue Mar 8, 2020 · 4 comments · Fixed by #74392
Closed

Const-generics don't work with constants #69816

Boscop opened this issue Mar 8, 2020 · 4 comments · Fixed by #74392
Labels
A-const-generics Area: const generics (parameters and arguments) A-inference Area: Type inference C-bug Category: This is a bug. F-const_generics `#![feature(const_generics)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Boscop
Copy link

Boscop commented Mar 8, 2020

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.

@rodrimati1992
Copy link
Contributor

rodrimati1992 commented Mar 8, 2020

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
Copy link
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}; _]`

@Centril Centril added A-const-generics Area: const generics (parameters and arguments) C-bug Category: This is a bug. F-const_generics `#![feature(const_generics)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-inference Area: Type inference labels Mar 8, 2020
@Boscop
Copy link
Author

Boscop commented Mar 8, 2020

@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
Copy link
Author

Boscop commented Mar 8, 2020

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?

Manishearth added a commit to Manishearth/rust that referenced this issue Jul 16, 2020
const generics triage

I went through all const generics issues and closed all issues which are already fixed.

Some issues already have a regression test but were not closed. Also doing this as part of this PR.

uff r? @eddyb @varkor

closes rust-lang#61936
closes rust-lang#62878
closes rust-lang#63695
closes rust-lang#67144
closes rust-lang#68596
closes rust-lang#69816
closes rust-lang#70217
closes rust-lang#70507
closes rust-lang#70586
closes rust-lang#71348
closes rust-lang#71805
closes rust-lang#73120
closes rust-lang#73508
closes rust-lang#73730
closes rust-lang#74255
@bors bors closed this as completed in c354524 Jul 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-generics Area: const generics (parameters and arguments) A-inference Area: Type inference C-bug Category: This is a bug. F-const_generics `#![feature(const_generics)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants