Skip to content

decltype of template parameters in requires-expression parameter types [GH #462] - #463

Open
daveedvdv-nvidia wants to merge 1 commit into
mainfrom
fix/462
Open

daveedvdv-nvidia wants to merge 1 commit into
mainfrom
fix/462

Conversation

@daveedvdv-nvidia

@daveedvdv-nvidia daveedvdv-nvidia commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #462.

The parameter declarations of a requires-expression are parsed before the requirements, and unlike the requirements, they were not treated as being in a template deduction context. So the information needed to substitute decltype applied to a template parameter in a parameter type wasn't recorded, and the substituted parameter got an error type. Any requirement that used the parameter in an operation was then considered unsatisfied:

struct NoConst { int operator()() { return 0; } };
template <auto F>
constexpr bool b = requires(decltype(F) f) { f(); };
static_assert(b<NoConst{}>);  // Previously failed.

This only worked in a concept definition, whose parameter scope inherits the flag from the enclosing template declaration. function_declarator now sets that flag on the prototype scope of a requires-expression's parameters in a template-dependent context.

A second problem showed up in member templates of a class template (e.g., template <auto F> struct S { template <int I> static constexpr bool m() { return requires(decltype(F) f) { f(); }; } };). When S<NoConst{}> is instantiated, F is still a template parameter of class type. Rescanning the reference stripped the implicit lvalue node that marks it as an id-expression, so when m<1> was instantiated, decltype(F) gave const NoConst & (the type of the template parameter object) instead of NoConst. make_rescan_operand_full now rebuilds that lvalue node and restores the id-expression details, as is already done for template parameter objects (#422).

Summary by CodeRabbit

  • Bug Fixes
    • Corrected C++20 decltype results for parameters in requires-expressions, including class-type non-type template parameters. Requirements using these types now evaluate correctly across template contexts.
  • Tests
    • Added regression coverage for callable and non-callable parameters, different declarator forms, and requires-expressions in function, class, and concept contexts.

@daveedvdv-nvidia
daveedvdv-nvidia requested a review from a team November 3, 2026 00:33
@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between cc40804 and 946defd.

Files selected for processing: 8
  • src/declarator.c
  • src/exprutil.c
  • src/pending_changes/gh-462-requires-expr-param-decltype.txt
  • tests/tests/regressions/.gh-462.rto/default.1.1.txt
  • tests/tests/regressions/.gh-462.rto/default.2.1.txt
  • tests/tests/regressions/.gh-462.rto/default.3.1.txt
  • tests/tests/regressions/.gh-462.rto/default.4.1.txt
  • tests/tests/regressions/gh-462.sft.cpp

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

The compiler now marks requires-expression parameter scopes as being in template deduction context and preserves lvalue category during relevant template-expression rescanning. C++20 regression cases and a release note cover the reported decltype substitution behavior.

Changes: Requires-expression parameter decltype

Layer / File(s) Summary
Template deduction context
src/declarator.c
When requires-expression parameters occur in a template-dependent context, the prototype scope is marked as being in template deduction context.
Operand rescanning and regression coverage
src/exprutil.c, tests/tests/regressions/gh-462.sft.cpp, tests/tests/regressions/.gh-462.rto/*, src/pending_changes/gh-462-requires-expr-param-decltype.txt
Rescanning preserves lvalue category and identifier details for the affected template-parameter expressions. Regression tests cover parameter types and contexts; the release note describes the reported cases.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Possibly related issues

Possibly related PRs

  • edgcpp/compiler#422: It changes rescanning for class-type non-type template parameters, sharing the rescan path modified in this PR.

Suggested labels: bug

Suggested reviewers: wchilders-nvidia, darkarc

Merge Risk: Minimal · up to 946de

The change targets requires-expression decltype handling. No concrete merge-blocking risk was identified.

Pre-merge checks: Passed 4
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies the main change: handling decltype for template parameters in requires-expression parameter types. The GH #462 reference is relevant.
Linked Issues check Passed Issue #462 requires unparenthesized decltype(F) for a class-type non-type template parameter to produce the declared non-const type in a requires-expression parameter, so f() is valid. `src/declar…
Out of Scope Changes check Passed The changes stay within issue #462. The source changes implement requires-expression substitution and template-parameter rescanning. The release note documents the fix. The added regression fixture an…
Full details: Linked Issues check

Explanation

Issue #462 requires unparenthesized decltype(F) for a class-type non-type template parameter to produce the declared non-const type in a requires-expression parameter, so f() is valid. src/declarator.c records template deduction context for requires-expression parameter scopes. src/exprutil.c preserves the lvalue and id-expression information during rescanning. tests/tests/regressions/gh-462.sft.cpp verifies callable behavior, exact type, parenthesized behavior, references, pointers, function templates, class members, out-of-class members, and concepts. The regression commands cover C++20 and the listed compiler modes.

Full details: Out of Scope Changes check

Explanation

The changes stay within issue #462. The source changes implement requires-expression substitution and template-parameter rescanning. The release note documents the fix. The added regression fixture and four test configurations verify the reported behavior and related cases. No unrelated product behavior or unrelated public entity changes are present.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.

@codecov

codecov Bot commented Nov 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/exprutil.c 80.00% 0 Missing and 2 partials ⚠️
src/declarator.c 50.00% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@nv-cmeerw nv-cmeerw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

decltype of a class-type NTTP used as a requires-expression parameter

2 participants