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

Error using associated constant in return type of generic function #56605

Open
richardmatheson opened this issue Dec 7, 2018 · 5 comments
Open
Labels
A-associated-items Area: Associated items (types, constants & functions) A-const-generics Area: const generics (parameters and arguments) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@richardmatheson
Copy link

richardmatheson commented Dec 7, 2018

Consider the following code:

trait ArrayGenerator {
  const LEN: usize;
}

fn generate<T>(obj: T) -> [u8; T::LEN] where T: ArrayGenerator {
  [0; T::LEN]
}

struct Foo { }

impl ArrayGenerator for Foo {
  const LEN: usize = 8;
}

fn main() {
  println!("{:?}", generate(Foo{}));
}

The compiler will error with:

error[E0599]: no associated item named `LEN` found for type `T` in the current scope
 --> src/main.rs:5:32
  |
5 | fn generate<T>(obj: T) -> [u8; T::LEN] where T: ArrayGenerator {
  |                                ^^^^^^ associated item not found in `T`
  |
  = help: items from traits can only be used if the trait is implemented and in scope
  = note: the following trait defines an item `LEN`, perhaps you need to implement it:
          candidate #1: `ArrayGenerator`

Now there is a clear constraint on T, meaning that LEN should be valid. I'm guessing the return type is being evaluated before the constraint, whereas it should check after, at which point it would know this this ought to be valid.

Tested in 1.31 stable and 1.32 nightly (Dec 7 2018)

@estebank
Copy link
Contributor

estebank commented Dec 7, 2018

Even worse, we suggest the code that's already there in the following case:

trait ArrayGenerator {
  const LEN: usize;
}

fn generate<T>(obj: T) -> [u8; <T as ArrayGenerator>::LEN] where T: ArrayGenerator {
  [0; T::LEN]
}

struct Foo { }

impl ArrayGenerator for Foo {
  const LEN: usize = 8;
}

fn main() {
  println!("{:?}", generate(Foo{}));
}
error[E0277]: the trait bound `T: ArrayGenerator` is not satisfied
 --> src/main.rs:5:32
  |
5 | fn generate<T>(obj: T) -> [u8; <T as ArrayGenerator>::LEN] where T: ArrayGenerator {
  |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ArrayGenerator` is not implemented for `T`
  |
  = help: consider adding a `where T: ArrayGenerator` bound
note: required by `ArrayGenerator::LEN`
 --> src/main.rs:2:3
  |
2 |   const LEN: usize;
  |   ^^^^^^^^^^^^^^^^^

error: aborting due to previous error

@estebank estebank added A-diagnostics Area: Messages for errors, warnings, and lints A-associated-items Area: Associated items (types, constants & functions) T-lang Relevant to the language team, which will review and decide on the PR/issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed A-diagnostics Area: Messages for errors, warnings, and lints labels Dec 7, 2018
@estebank
Copy link
Contributor

estebank commented Dec 7, 2018

Seems to be a variation of #56605

@varkor
Copy link
Member

varkor commented Dec 19, 2018

@estebank: did you mean to reference a different issue? #56605 is this one.

@aschampion
Copy link
Contributor

Ran into this bug and suspect the related bug he meant to link was #43408

@RodBurman
Copy link

With current latest toolchain:

% cargo -v -V
cargo 1.85.0 (d73d2caf9 2024-12-31)
release: 1.85.0
commit-hash: d73d2caf9e41a39daf2a8d6ce60ec80bf354d2a7
commit-date: 2024-12-31
host: aarch64-apple-darwin
libgit2: 1.8.1 (sys:0.19.0 vendored)
libcurl: 8.7.1 (sys:0.4.74+curl-8.9.0 system ssl:(SecureTransport) LibreSSL/3.3.6)
ssl: OpenSSL 1.1.1w  11 Sep 2023
os: Mac OS 15.3.1 [64-bit]

the sample code

trait ArrayGenerator {
  const LEN: usize;
}

fn generate<T>(obj: T) -> [u8; <T as ArrayGenerator>::LEN] where T: ArrayGenerator {
  [0; T::LEN]
}

struct Foo { } 

impl ArrayGenerator for Foo {
  const LEN: usize = 8;
}

fn main() {
  println!("{:?}", generate(Foo{}));
}

does not compile but the errors given are completely different:

% cargo build
   Compiling errasscon v0.1.0 (/Users/rod/code/rust/triage/errasscon)
error: generic parameters may not be used in const operations
 --> src/main.rs:5:33
  |
5 | fn generate<T>(obj: T) -> [u8; <T as ArrayGenerator>::LEN] where T: ArrayGenerator {
  |                                 ^ cannot perform const operation using `T`
  |
  = note: type parameters may not be used in const expressions

error: constant expression depends on a generic parameter
 --> src/main.rs:6:7
  |
6 |   [0; T::LEN]
  |       ^^^^^^
  |
  = note: this may fail depending on what value the parameter takes

error: could not compile `errasscon` (bin "errasscon") due to 2 previous errors

@estebank estebank added the A-const-generics Area: const generics (parameters and arguments) label Mar 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items (types, constants & functions) A-const-generics Area: const generics (parameters and arguments) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants