Closed
Description
I believe this code should not produce the static assertion failure:
//--- lambda.h
#pragma once
inline auto cmp = [](auto l, auto r) {
return l < r;
};
//--- A.cppm
module;
#include "lambda.h"
export module A;
export auto c1 = cmp;
export using ::cmp;
//--- B.cppm
module;
#include "lambda.h"
export module B;
export auto c2 = cmp;
export using ::cmp;
//--- use.cppm
module;
export module use;
import A;
import B;
static_assert(__is_same(decltype(c1), decltype(c2))); // should succeed.
auto x = cmp; // cmp must not be ambiguous,
// Build with:
// clang++ -std=c++20 --precompile -o A.pcm A.cppm
// clang++ -std=c++20 --precompile -o B.pcm B.cppm
// clang++ -std=c++20 -fprebuilt-module-path=. use.cppm
As the lambda meets all requirements specified in basic.def.odr and cmp
is declared inline. I.e. this should be no different from explicit class declaration from lambda.
However, the static assertion currently fails and the use of 'cmp' produces an "ambiguous reference" error.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Done
Milestone
Relationships
Development
No branches or pull requests
Activity
llvmbot commentedon Aug 18, 2022
@llvm/issue-subscribers-clang-frontend
llvmbot commentedon Aug 18, 2022
@llvm/issue-subscribers-c-20
llvmbot commentedon Aug 18, 2022
@llvm/issue-subscribers-clang-modules
[-]Merging of lambda types [/-][+][C++20] [Modules] Merging of lambda types [/+]ChuanqiXu9 commentedon Aug 19, 2022
Confirmed. First I hesitated since I know each lambda has a unique closure type. But later I found https://eel.is/c++draft/basic.def.odr#14.4:
And https://eel.is/c++draft/basic.def.odr#14.6
So static_assert shouldn't fail.
Also I think the
inline
part may be redundant, no matter it is inline or not, the declaration is attached to global module fragment.aaronmondal commentedon Sep 29, 2022
I believe this is implicitly causing
libcxx
to fail when we include anything that makes use of__compare/synth_three_way.h
in GMFs and the locations of the headers differ during compilation and precompilation. For instance if we include<compare>
several times in the interface and/or implementation GMFs, we get something like this:This patch seems to fix the issue, but I'm not sure what the implications of removing this lambda may be:
@mumbleskates Could you explain why this lambda is neccessary?
Apart from having to add a template deduction guide for
back_insert_iterator
this is the only blocker I found so far for usinglibcxx
freely in global module fragments.I initially tried only changing (in Line 29)
inline constexpr
tostatic inline constexpr
, but then theusing __synth_three_way_result
-line raises this buggy error message which I think was already reported in some other module-related issue:mumbleskates commentedon Sep 29, 2022
@aaronmondal the lambda is transcribed pretty much verbatim from the draft standard. It was written here, and there was some discussion about whether or not to make it a lambda (cc @ldionne). we're supposed to have ODR protection with
_LIBCPP_HIDE_FROM_ABI
though i'm not familiar with the different situations that may be arising here.it looks like arthur made the change e0e7bd1 in march this year updating the
__synth_three_way_result
definition to use the explicit namespace, which may have been good to have in there originally but also should have used_VSTD
. it does not look like this commit went through review, and he's gone now.@aaronmondal if you make only the latter change, to
__synth_three_way_result
to use_VSTD::
, does that alone fix it?aaronmondal commentedon Sep 29, 2022
@mumbleskates Thanks for taking a look at this!
Ah ok found it: https://eel.is/c++draft/expos.only.func#conceptref:three_way_comparable_with
Only changing this still raises the
redeclaration of '__synth_three_way' with a different type
error.I think this is a bug with modules, not with
libcxx
. However, if the simpler non-lambda variant satisfies all tests (haven't checked yet), I think it may actually desirable to use that variant. From the linked discussion it seems to me that the lambda was more or less an arbitrary choice for the sake of sticking close to what the exposition in the standard looks like. I think the original argument had something to do with not having to use_VSTD
, but since_VSTD
should be used now anyways the non-lambda variant seems a lot easier to comprehend to me.Fixing the lambda resolution in modules seems very hard in comparison to changing 3 lines in
libcxx
. I checked the cppcoreguidelines for stylistic reasons on why one may want to use a lambda here but couldn't find any.So for the sake of readability and module compatibility (even if technically just a workaround) I think it would be nice to change this.
I'll send the patch for review 😊
19 remaining items