[PATCH] D113319: [clang-format] Improve require and concept handling
Björn Schäpers via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 3 16:19:38 PST 2021
HazardyKnusperkeks marked 4 inline comments as done.
HazardyKnusperkeks added inline comments.
================
Comment at: clang/docs/ClangFormatStyleOptions.rst:3464-3483
+ * ``RCPS_TwoLines`` (in configuration: ``TwoLines``)
+ The clause always gets its own line, and the content of the clause go
+ into the next line with some indentation.
+
+ .. code-block:: c++
+
+ template<typename T>
----------------
Quuxplusone wrote:
> This option strikes me as actively harmful; I think you should remove it from the PR completely. Nobody does this today and nobody should do it in the future either.
I will never use it, so I have no strong opinion in that, because it was really easy to add. I will let others decide if we want to offer it.
================
Comment at: clang/include/clang/Format/Format.h:3130-3136
+ /// \brief The position of the ``requires`` clause for class templates.
+ /// \version 14
+ RequiresClausePositionStyle RequiresClausePositionForClasses;
+
+ /// \brief The position of the ``requires`` clause for function templates.
+ /// \version 14
+ RequiresClausePositionStyle RequiresClausePositionForFunctions;
----------------
Quuxplusone wrote:
> What about for variable templates? What about for alias templates? What about for deduction guides?
> It makes sense to me to have //one// option for this. It doesn't make sense to have 2, 3, or 4. Having 5 feels insane. So, I think you should just have one option that applies consistently to all `requires`-clauses everywhere in the code.
That makes sense, in my defense I thought about it and came to the conclusion there would be no need for requires on variable templates, and the others I did not think of.
Why I have chosen to options is maybe someone wants
```template <typename T>
requires ...
class ...```
But also
```template <typename T>
void foo(T) requires ... {
```
What's your opinion on that?
================
Comment at: clang/unittests/Format/FormatTest.cpp:22288-22291
+ verifyFormat("template <typename T>\n"
+ "concept C = ((false || foo()) && C2<T>) || "
+ "(std::trait<T>::value && Baz) ||\n "
+ " sizeof(T) >= 6;");
----------------
Quuxplusone wrote:
> Nit: I was initially very confused by the formatting here, until I realized that lines 22289 and 22290 are two lines //physically// but represent one single line in the //test case//. Strongly recommend eliminating the gratuitous line break.
I'm not really happy wit the two solutions which come to my mind:
Using a Style with a lower column limit, or using // clang format off.
================
Comment at: clang/unittests/Format/FormatTest.cpp:22374-22378
+ "template <typename T>\n"
+ "concept C = decltype([]() { return std::true_type{}; }())::value &&\n"
+ " requires(T t) {\n"
+ " t.bar();\n"
+ "} && sizeof(T) <= 8;");
----------------
Quuxplusone wrote:
> This looks wrong. Current:
> ```
> template <typename T>\n"
> concept C = decltype([]() { return std::true_type{}; }())::value &&
> requires(T t) {
> t.bar();
> } && sizeof(T) <= 8;
> ```
> but should be:
> ```
> template <typename T>\n"
> concept C = decltype([]() { return std::true_type{}; }())::value &&
> requires(T t) {
> t.bar();
> } && sizeof(T) <= 8;
> ```
> (assuming that all the relevant indent-widths are set to `2`).
For me personally it should look
```template <typename T>\n"
concept C = decltype([]() { return std::true_type{}; }())::value &&
requires(T t) {
t.bar();
} && sizeof(T) <= 8;```
I have not taken any action to manipulate the position, this is what dropped out of clang-format naturally. And I think the requires should start below the decltype the same as all other conditions would. If the body should be indented is open for discussion.
================
Comment at: clang/unittests/Format/FormatTest.cpp:22597
+ verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+ "requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+ "struct constant;",
----------------
Quuxplusone wrote:
> Currently:
> ```
> template <std::semiregular F, std::semiregular... Args>
> requires(std::invocable<F, std::invoke_result_t<Args>...>)
> struct constant;
> ```
> Should be:
> ```
> template <std::semiregular F, std::semiregular... Args>
> requires (std::invocable<F, std::invoke_result_t<Args>...>)
> struct constant;
> ```
> (notice the extra single space). Add a TODO comment and ship it anyway?
Take a look at D113369 which will most likely land simultaneously with this change, but currently needs to be updated.
================
Comment at: clang/unittests/Format/FormatTest.cpp:22643
verifyFormat("template <typename T>\n"
- "concept Context = Traits<typename T::traits_type> or\n"
- " Interface<typename T::interface_type> or\n"
- " Request<typename T::request_type> or\n"
- " Response<typename T::response_type> or\n"
- " ContextExtension<typename T::extension_type> or\n"
- " ::std::is_copy_constructable<T> or "
- "::std::is_move_constructable<T> or\n"
- " requires (T c) {\n"
- " { c.response; } -> Response;\n"
- "} or requires (T c) {\n"
- " { c.request; } -> Request;\n"
- "}\n",
+ "requires requires(T t) {\n"
+ " typename T::Bar;\n"
----------------
Quuxplusone wrote:
> Data point: libc++ has a mix of `requires (T t) { }` and `requires(T t) { }`. Am I correct that clang-format is not yet smart enough to have a meaningful opinion about this particular whitespace?
> I would bet that two years ago I was doing `requires(T t) { }`, but these days `requires (T t) { }` is much more natural to me.
See above.
================
Comment at: clang/unittests/Format/FormatTest.cpp:23268-23270
+ return;
+ FormatStyle Style = getLLVMStyle();
+ Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
----------------
Quuxplusone wrote:
> (1) That `return` on line 23268 is sneaky. 😛
> (2) LLVM style should certainly set `IndentRequires=true`, so this test shouldn't pass without some modification to line 23273.
This test case will be gone, after I'm done. I just keep it to look for some variants I might have missed in writing new tests.
About `IndentRequires` I have strong opinion, other than changing what is released feels a bit wrong. (Since as far as I can see LLVM Style does not mention requires at all.)
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D113319/new/
https://reviews.llvm.org/D113319
More information about the cfe-commits
mailing list