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

return const array from impl function, loses const information #67144

Closed
robinvd opened this issue Dec 8, 2019 · 8 comments · Fixed by #74392
Closed

return const array from impl function, loses const information #67144

robinvd opened this issue Dec 8, 2019 · 8 comments · Fixed by #74392
Labels
A-const-generics Area: const generics (parameters and arguments) A-lazy-normalization Area: Lazy normalization (tracking issue: #60471) C-bug Category: This is a bug. F-const_generics `#![feature(const_generics)]` requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@robinvd
Copy link

robinvd commented Dec 8, 2019

When returning an const length array from an associated function the length is lost and it becomes a [T; _] array.

I tried this code:
(Playground)

#![feature(const_generics)]

struct X;

impl X {
    pub fn getn<const N: usize>(&self) -> [u8; N] {
        getn::<N>()
    }
}

fn getn<const N: usize>() -> [u8; N] {
    unsafe {
        std::mem::zeroed()
    }
}

fn test() {
    // works
    let [a,b,c] = getn::<3>();
    
    // cannot pattern-match on an array without a fixed length
    let [a,b,c] = X.getn::<3>();
    
    // mismatched types, expected array `[u8; 3]` found array `[u8; _]`
    let arr: [u8; 3] = X.getn::<3>();
}

I expected to see this happen:
all lines in test compile

Instead, this happened:
functions from the impl did not return a const array

Meta

rustc --version --verbose:

rustc 1.41.0-nightly (412f43ac5 2019-11-24)
binary: rustc
commit-hash: 412f43ac5b4ae8c3599e71c6972112e9be4758fa
commit-date: 2019-11-24
host: x86_64-unknown-linux-gnu
release: 1.41.0-nightly
LLVM version: 9.0
@jonas-schievink jonas-schievink added A-const-generics Area: const generics (parameters and arguments) C-bug Category: This is a bug. F-const_generics `#![feature(const_generics)]` requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Dec 8, 2019
@robinvd
Copy link
Author

robinvd commented Jan 3, 2020

@varkor I saw in #44580 (comment) that you would be able to help/mentor const_generics issues

I would like to give this issue a go, but have no idea where to start. Maybe you could give me some pointers?

@varkor
Copy link
Member

varkor commented Jan 4, 2020

This is a slightly more minimal reproduction:

#![feature(const_generics)]

struct A<const N: usize>;

struct X;

impl X {
    fn inner<const N: usize>() -> A<N> {
        outer::<N>()
    }
}

fn outer<const N: usize>() -> A<N> {
    A
}

fn main() {
    let i: A<3usize> = outer::<3usize>(); // ok
    let o: A<3usize> = X::inner::<3usize>(); // error
}

@robinvd: This is quite a surprising error to me: I don't have any immediate guesses as to what might be going on. We'll need to do a little investigation here. The error in the example above is:

expected `3usize`, found `3usize`

Clearly, these should unify, so the first step would be to work out why unification doesn't think they're the same value. Hopefully that'll give some clues. The main thing that's different about trait functions is that they have an extra (hidden) generic parameter, which is the Self type, so there's possibly an indexing issue here (the first generic parameter is Self, so that could be getting compared with N and causing issues). Feel free to do some digging — I'll try to update with more detailed instructions if I get a handle on what might be causing this.

@varkor
Copy link
Member

varkor commented Jan 5, 2020

The reason the values don't unify is because we hit this:

_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),

where we have (something like)

a=Const { ty: usize, val: Unevaluated(DefId(0:17 ~ const_trait_error[317d]::main[0]::{{constant}}[3]), []) }
b=Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }

For some reason, it's unable to evaluate one of the constants.

@varkor
Copy link
Member

varkor commented Jan 5, 2020

The issue is that in

| Node::Expr(&hir::Expr {
kind: ExprKind::Path(QPath::Resolved(_, ref path)),
..
}) => Some(&**path),

we only consider QPath::Resolved. We also need to handle QPath::TypeRelative, which occurs whenever we have a path A::B (like in X::inner).

@varkor
Copy link
Member

varkor commented Jan 5, 2020

I've done some refactoring to make the method a little clearer. The bit that needs fixing now is:
master...varkor:const_generics-assoc-method#diff-4ed25c00aceb84666fca639cf8101c7cR1512
What I'd like to be able to do here is something like tcx.typeck_tables_of(def_id).type_dependent_def(hir_id), but this causes a cycle error.

@robinvd
Copy link
Author

robinvd commented Jan 6, 2020

slightly unrelated. I tried some things yesterday, but my edit/compile cycle was 9 minutes with ./x.py test -i --stage 1 src/test/ui/const-generics/const-parameter-in-impl.rs --keep-stage 1. Is this just how big the rust compiler is?

@varkor
Copy link
Member

varkor commented Jan 6, 2020

It does take a little while to compile rustc, yes. I'm using the suggestion options in the rustc guide and it takes 3 – 4 minutes on my computer after making changes in librustc_typeck/collect.rs, for example.

@varkor varkor added the A-lazy-normalization Area: Lazy normalization (tracking issue: #60471) label Apr 8, 2020
@lcnr
Copy link
Contributor

lcnr commented Jun 9, 2020

will probably get fixed by #71154

lcnr added a commit to lcnr/rust that referenced this issue Jul 16, 2020
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-lazy-normalization Area: Lazy normalization (tracking issue: #60471) C-bug Category: This is a bug. F-const_generics `#![feature(const_generics)]` requires-nightly This issue requires a nightly compiler in some way. 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.

4 participants