Incorrect (or misleading) error [E0599] caused when `where` has a `const` expression with local `fn`

Not sure how to report a compiler issue so posting it here:

Consider the following code where I am validating a template const value at compile time... which results in [E0599] when:

  • expression in the where clause has a local function (i.e. { const fn _local(C) {...}; _local()}.
  • And the struct implements 1 or more trait in addition to its own impl
  • The error is misleading as the trait and its where is already satisfied but the expression is complex.

It works when the expression in where calls a global const fn or has a simple expression.

An ideal/expected behaviour would be:

  • It works with complex const expressions
  • but of course, an acceptable/helpful behaviour would be if the error message indicated that the where clause is too complex

(p.s. this is related to my previous post: ( Help with [E0599] when implementing trait - The Rust Programming Language Forum

Minimal sample to reproduce the issues:

#![allow(incomplete_features)]
#![allow(internal_features)]
#![feature(generic_const_exprs)]

use std::ops::Index;

struct Guard<const U: bool>;
trait Protect {}
impl Protect for Guard<true> {}

enum Nucleotide {
    A,
    C,
}

struct NucleotideCount<const C: usize> {
    a: usize,
    c: usize,
}

const fn a_global_const_fn(c: usize) -> bool {
    c <= 100
}

impl <const C: usize> NucleotideCount<C>
where
    Guard<{
        // BEGIN => causes E0599
        const fn _a_local_const_fn<const C: usize>() -> bool {
            C <= 100
        }
        _a_local_const_fn::<C>()
        // END 

        // C <= 100  // <== uncomment me and comment above to get it  working
        // a_global_const_fn(C) // <=== OR uncumment me.. also works!!
    }>: Protect,
{
    pub fn get(&self, nucleotide: Nucleotide) -> Option<&usize> {
        match nucleotide {
            Nucleotide::A => Some(&self.a),
            Nucleotide::C => Some(&self.c),
        } 
    }
}

impl <const C: usize> Index<Nucleotide> for NucleotideCount<C>
where
    Guard<{
        // BEGIN => causes E0599
        const fn _a_local_const_fn<const C: usize>() -> bool {
            C <= 100
        }
        _a_local_const_fn::<C>()
        // END 

        // C <= 100  // <== uncomment me and comment above to get it  working
        // a_global_const_fn(C) // <=== OR uncumment me.. also works!!
    }>: Protect,
{
    type Output = usize;

    fn index(&self, nucleotide: Nucleotide) -> &Self::Output {
        self.get(nucleotide).unwrap()
    }
}

fn main() {
    let nucleotide_count: NucleotideCount<10> = NucleotideCount {a: 14, c: 9};
    assert_eq!(nucleotide_count[Nucleotide::A], 14);
    assert_eq!(nucleotide_count[Nucleotide::C], 9);
    println!("SUCCESS!")
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `get` found for reference `&NucleotideCount<C>` in the current scope
  --> src/main.rs:64:14
   |
64 |         self.get(nucleotide).unwrap()
   |              ^^^ method cannot be called on `&NucleotideCount<C>` due to unsatisfied trait bounds
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `get`, perhaps you need to implement it:
           candidate #1: `SliceIndex`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` (bin "playground") due to 1 previous error

The right place to report an misleading error is on the rust-lang/rust issue tracker, specifically using the diagnostic issue template. However, you are using a feature marked as incomplete.

It’s unlikely to be a good idea to spend any effort on improving the errors until the more fundamental issues are resolved β€” particularly as the additional error reporting code might get in the way of making the rest better.

If your goal is to write a useful Rust program, you should avoid all incomplete_features and find alternative solutions.

2 Likes

Thanks @kpreid (Kevin) ... with 10_000+ open bugs I guess I'll leave it here :slightly_smiling_face:.

Coming from C++, few of the very useful features are incomplete, especially when it comes to developing a generic templated library or template metaprogramming and compile time / static checks. (e.g. const generics). Kind of reminds me of limitations with templates in C++ 11.

Anyway, I guess focus/philosophy for Rust compiler designers is different from C++ compiler designers.