Skip to content

Diagnostic for constraint satisfication failure can provide irrelevant information #54678

Closed
@brevzin

Description

@brevzin

Here's an example:

template<class>
concept True = true;

template<class>
concept False = false;

template<class>
concept Irrelevant = false;

template<class T> void foo(T t) requires (True<T> || Irrelevant<T>) && False<T> { }
template<class T> void bar(T t) requires (Irrelevant<T> || True<T>) && False<T> { }

int main() {
    foo(42);
    bar(42L);
}

The calls to foo(42) and bar(42L) should (and do) fail, because neither int nor long satisfy False.

clang currently emits this error for foo(42)

<source>:14:5: error: no matching function for call to 'foo'
    foo(42);
    ^~~
<source>:10:24: note: candidate template ignored: constraints not satisfied [with T = int]
template<class T> void foo(T t) requires (True<T> || Irrelevant<T>) && False<T> { }
                       ^
<source>:10:72: note: because 'int' does not satisfy 'False'
template<class T> void foo(T t) requires (True<T> || Irrelevant<T>) && False<T> { }
                                                                       ^
<source>:5:17: note: because 'false' evaluated to false
concept False = false;
                ^

Which is good.

But it emits this error for bar(42L):

<source>:15:5: error: no matching function for call to 'bar'
    bar(42L);
    ^~~
<source>:11:24: note: candidate template ignored: constraints not satisfied [with T = long]
template<class T> void bar(T t) requires (Irrelevant<T> || True<T>) && False<T> { }
                       ^
<source>:11:43: note: because 'long' does not satisfy 'Irrelevant'
template<class T> void bar(T t) requires (Irrelevant<T> || True<T>) && False<T> { }
                                          ^
<source>:8:22: note: because 'false' evaluated to false
concept Irrelevant = false;
                     ^
<source>:11:72: note: and 'long' does not satisfy 'False'
template<class T> void bar(T t) requires (Irrelevant<T> || True<T>) && False<T> { }
                                                                       ^
<source>:5:17: note: because 'false' evaluated to false
concept False = false;
                ^

This notes both that long does not satisfy False but also that long does not satisfy Irrelevant. But Irrelevant is irrelevant - that part of the disjunction holds (because long satisfies True), so that is not the reason this fails. It's just an irrelevant diagnostic to the user -- which clang (correctly) doesn't provide in the foo case.

Metadata

Metadata

Assignees

Labels

clang:diagnosticsNew/improved warning or error message in Clang, but not in clang-tidy or static analyzer

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions