Skip to content

[libc++][NFC] Add a static assertion to document an assumption in std::hash #114440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 1, 2024

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Oct 31, 2024

The implementation of std::hash for unsigned long makes the (correct) assumption that size_t is at least as large as unsigned long. If that were not the case on a platform, the implementation of std::hash for unsigned long would be absolutely terrible. Add a static assertion to document that assumption.

…::hash

The implementation of std::hash for unsigned long makes the (correct)
assumption that size_t is at least as large as unsigned long. If that
were not the case on a platform, the implementation of std::hash for
unsigned long would be absolutely terrible. Add a static assertion to
document that assumption.
@ldionne ldionne requested a review from a team as a code owner October 31, 2024 18:12
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Oct 31, 2024
@llvmbot
Copy link
Member

llvmbot commented Oct 31, 2024

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

The implementation of std::hash for unsigned long makes the (correct) assumption that size_t is at least as large as unsigned long. If that were not the case on a platform, the implementation of std::hash for unsigned long would be absolutely terrible. Add a static assertion to document that assumption.


Full diff: https://github.com/llvm/llvm-project/pull/114440.diff

1 Files Affected:

  • (modified) libcxx/include/__functional/hash.h (+5-1)
diff --git a/libcxx/include/__functional/hash.h b/libcxx/include/__functional/hash.h
index f7b89f759b5f5c..87009dfa62ef59 100644
--- a/libcxx/include/__functional/hash.h
+++ b/libcxx/include/__functional/hash.h
@@ -406,7 +406,11 @@ struct _LIBCPP_TEMPLATE_VIS hash<long> : public __unary_function<long, size_t> {
 
 template <>
 struct _LIBCPP_TEMPLATE_VIS hash<unsigned long> : public __unary_function<unsigned long, size_t> {
-  _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned long __v) const _NOEXCEPT { return static_cast<size_t>(__v); }
+  _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned long __v) const _NOEXCEPT {
+    static_assert(sizeof(size_t) >= sizeof(unsigned long),
+                  "This would be a terrible hash function on a platform where size_t is smaller than unsigned long");
+    return static_cast<size_t>(__v);
+  }
 };
 
 template <>

@ldionne ldionne merged commit d301b59 into llvm:main Nov 1, 2024
63 of 65 checks passed
@ldionne ldionne deleted the review/hash-add-static-assert branch November 1, 2024 16:58
smallp-o-p pushed a commit to smallp-o-p/llvm-project that referenced this pull request Nov 3, 2024
…::hash (llvm#114440)

The implementation of std::hash for unsigned long makes the (correct)
assumption that size_t is at least as large as unsigned long. If that
were not the case on a platform, the implementation of std::hash for
unsigned long would be absolutely terrible. Add a static assertion to
document that assumption.
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
…::hash (llvm#114440)

The implementation of std::hash for unsigned long makes the (correct)
assumption that size_t is at least as large as unsigned long. If that
were not the case on a platform, the implementation of std::hash for
unsigned long would be absolutely terrible. Add a static assertion to
document that assumption.
@s-barannikov
Copy link
Contributor

I happen to have such a target (32-bit size_t, 64-bit long). What should I do to resolve the static assertion failure?
I guess 16-bit targets will also suffer, where size_t is usually unsigned int (that is, 16-bit), but long can't be less than 32 bits.

@philnik777
Copy link
Contributor

@s-barannikov What platform do you have? If possible it'd be great to get official support for that platform and implement a good hashing algorithm for that case. I don't think we'll break any 16 bit platforms, since we don't have a general hashing algorithm for them either.

@s-barannikov
Copy link
Contributor

s-barannikov commented Nov 25, 2024

The platform has 32-bit bytes, it is not currently possible to upstream it. I understand that static_assert is better than untested code, so I don't insist on any changes upstream. I'm merely asking for advice on how I could fix it downstream.
Would it be correct to implement this specialization the same way as for double?

@philnik777
Copy link
Contributor

Yeah, I think you should be able to use __scalar_hash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants