https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126050

            Bug ID: 126050
           Summary: [contracts] Premature type evaluation loop on
                    operator<=> using auto return deduction with a
                    dependent contract precondition
           Product: gcc
           Version: 16.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: zuhaitz.zechhub at gmail dot com
  Target Milestone: ---
              Host: x86_64-redhat-linux
            Target: x86_64-redhat-linux
             Build: x86_64-redhat-linux

Created attachment 64902
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=64902&action=edit
Preprocessed source.

Placing a C++26 pre() precondition attribute on a three-way comparison operator
(operator<=>) utilizing auto return type deduction causes an infinite type
system pipeline loop if the contract predicate depends on a comparison operator
(such as <). The compiler attempts to resolve the dependent comparison using
the spaceship operator before it has evaluated the function body's return
statement, creating a premature utilization error of an undeduced placeholder.

EXACT GCC VERSION:
gcc version 16.1.1 20260515 (Red Hat 16.1.1-2) (GCC)

SYSTEM TYPE / TARGET:
Target: x86_64-redhat-linux

COMPLETE COMMAND LINE TRIGGERING THE BUG:
g++ -std=c++26 -fcontracts -save-temps bug_spaceship_deduction_loop.cpp

COMPILER OUTPUT:
bug_spaceship_deduction_loop.cpp: In member function ‘auto
CustomNumber::operator<=>(const CustomNumber&) const’:
bug_spaceship_deduction_loop.cpp:8:23: error: use of ‘auto
CustomNumber::operator<=>(const CustomNumber&) const’ before deduction of
‘auto’
    8 |          pre((*this) < other || other.val > 0)
      |                       ^~~~~

MINIMAL STANDALONE TESTCASE (bug_spaceship_deduction_loop.cpp):
#include <contracts>
#include <compare>

struct CustomNumber {
    int val;

    auto operator<=>(const CustomNumber& other) const
        pre((*this) < other || other.val > 0)
    {
        return val <=> other.val;
    }
};

int main() {
    CustomNumber a{-5}, b{-10};
    auto res = (a <=> b);
}

Reply via email to