Open monkeynova opened 2 months ago
With a little more digging, I don't need that level of templating to replicate the regression. The following does it too:
#include <iostream>
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/flags/parse.h"
#include "absl/flags/usage.h"
#include "absl/log/check.h"
#include "absl/log/initialize.h"
#include "absl/strings/str_join.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
template <typename Storage>
class IntegerMod {
public:
IntegerMod() = default;
constexpr IntegerMod(const int64_t& v, int64_t mod)
: mod_(mod), v_(v % mod) {}
bool operator==(const IntegerMod& o) const = default;
#ifdef WORKING_VERSION
// This version allows compilation.
template <typename Containee=IntegerMod>
absl::flat_hash_set<Containee> Sqrt() const {
return {};
}
#else
absl::flat_hash_set<IntegerMod> Sqrt() const {
return {};
}
#endif
template <typename H>
friend H AbslHashValue(H h, const IntegerMod& m) {
return H::combine(std::move(h), m.v_);
}
template <typename Sink>
friend void AbslStringify(Sink& sink, const IntegerMod& m) {
absl::Format(&sink, "(%v MOD %v)", m.v_, m.mod_);
}
friend std::ostream& operator<<(std::ostream& out, const IntegerMod& m) {
return out << absl::StreamFormat("%v", m);
}
private:
int64_t mod_ = 1;
int64_t v_ = 0;
};
TEST(IntegerMod, Hash_Static) {
// absl::flat_hash_set<StaticIntegerMod<...>> encountered template
// instantiation problems (see comment on IntegerMod::Sqrt). This is here
// to ensure that we hit those problems in euler/... and to help replicate
// in a controlled environment.
using ModType = IntegerMod<int64_t>;
absl::flat_hash_set<ModType> set;
set.insert(ModType{5, 37});
set.insert(ModType{7, 37});
EXPECT_EQ(set.size(), 2);
set.insert(ModType{42, 37});
EXPECT_EQ(set.size(), 2) << absl::StrJoin(set, ",", [](std::string* out, ModType m) {
absl::StrAppend(out, m);
});
}
std::vector<char*> InitMain(int argc, char** argv, const std::string& usage) {
absl::SetProgramUsageMessage(usage);
absl::InitializeLog();
return absl::ParseCommandLine(argc, argv);
}
int main(int argc, char** argv) {
std::vector<char*> args = InitMain(
argc, argv,
absl::StrCat("This program runs the collection of gunit tests (default) "
"or benchmarks linked in (if the --benchmark flag is set). "
"No arguments are accepted. Usage:\n", argv[0],
" [--benchmark]"));
CHECK_EQ(args.size(), 1) << absl::StrJoin(args, ",");
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
git bisect with this replication case points me to this commit which feels relevant as it looks like its a partial specialization of the HashEq struct which could have interfered with the ability to resolve the templating for my type
https://github.com/abseil/abseil-cpp/commit/643b48a3b4362a932c0e41afce62deb55adf825b
Describe the issue
I updated from 20240116.2 to 20240722.0 and had a compilation regression of previous code. There was some nontrivial template meta-programming involved, but the part that failed for me was around returning an absl::flat_hash_set from a method in a templated type Foo.
This commit documents my upgrade and the change I had to make, though it's a private repository, so I'm not sure how best to share that with you.
I stripped the problem down to a bare reproduction step that can exist as a super-simple bazel repository which I've included in reproduction steps. Bringing the version back in MODULES.bazel allows compilation. As does setting the #define I've included in the code which documents my current workaround for this regression.
The error messages I see are as follows
Steps to reproduce the problem
bazel test ...
With the following repository
MODULES.bazel
BUILD
im_replicate_test.cc
What version of Abseil are you using?
20240116.2 (works) 20240722.0 (doesn't)
What operating system and version are you using?
macos 14.6.1
What compiler and version are you using?
default with the os. I think that's clang.
clang -v
What build system are you using?
bazel --version -> bazel 7.3.0 (via alas bazelisk=bazel)
Additional context
No response