llvm / llvm/llvm-project

Improve diagnostic when concept doesn't match because required operation is private

Open
#158,902 1 comment 0 reactions 0 assignees View on GitHub
clang:diagnostics concepts
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Consider the easy mistake of forgetting to put `public:` at the top of a `class`:

```cpp
class AlmostPred {
void operator()(int) const;
};

void f(std::predicate auto p) {}
```

When you try to invoke `f` you get a very confusing error that stops with: `because 'is_invocable_v' evaluated to false`. If you don't already know the problem, it can be very frustrating to see that error because the `operator()` with identical arguments is **RIGHT THERE** 😡. At least _I_ was recently frustrated by debugging this. Compare that to the gcc trunk output which tells you exactly what is wrong and letting you click to go right to the place to fix it.

```
• 'AlmostPred' is not invocable by 'int', because
• error: 'void AlmostPred::operator()(int) const' is private within this context
• declared private here
:6:10:
6 | void operator()(int) const;
| ^~~~~~~~
```

Clang does a bit better when you use `requires` expressions directly in the function declaration rather than concepts (even though the general advice is to never do that and to always use named concepts instead). With `void g(auto p) requires(requires(int i) {p(i);}){}` the error ends with `because 'p(i)' would be invalid: 'operator()' is a private member of 'AlmostPred'`. This could be improved further by including a reference to the declaration of the private member and possibly even a fixit to add `public:` to the top of the class (probably only if there are no protection markers in the class and it is just using the default).

Either way, the message about the function being private should be shown when attempting to use a concept. Really any concept failure should include the root cause of the failure, even if it skips a few steps between the named concept and the root cause by default for brevity.

[clang trunk godbolt with both `f` and `g`](https://godbolt.org/z/nWex86ods)
[clang trunk with libc++ (no better)](https://godbolt.org/z/Eaabc7P5h)
[gcc trunk godbolt](https://godbolt.org/z/E8nq3d9x6)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.