Repository: dtolnay/cxx (language: rust)

Issue:
Consider reference qualification of assignment operators
```diff
-   String &operator=(const String &) noexcept;
+   String &operator=(const String &) & noexcept;

// etc
```

For reasons described in https://wg21.link/N2819.


Discussion / hints:

Fix patch:
diff --git a/include/cxx.h b/include/cxx.h
index 0744f8cb1..654b176bf 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -44,8 +44,8 @@ class String final {
   String(const char *);
   String(const char *, std::size_t);
 
-  String &operator=(const String &) noexcept;
-  String &operator=(String &&) noexcept;
+  String &operator=(const String &) & noexcept;
+  String &operator=(String &&) & noexcept;
 
   explicit operator std::string() const;
 
@@ -97,7 +97,7 @@ class Str final {
   Str(const char *);
   Str(const char *, std::size_t);
 
-  Str &operator=(const Str &) noexcept = default;
+  Str &operator=(const Str &) & noexcept = default;
 
   explicit operator std::string() const;
 
@@ -144,8 +144,8 @@ template <>
 struct copy_assignable_if<false> {
   copy_assignable_if() noexcept = default;
   copy_assignable_if(const copy_assignable_if &) noexcept = default;
-  copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete;
-  copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default;
+  copy_assignable_if &operator=(const copy_assignable_if &) & noexcept = delete;
+  copy_assignable_if &operator=(copy_assignable_if &&) & noexcept = default;
 };
 } // namespace detail
 
@@ -159,8 +159,8 @@ class Slice final
   Slice() noexcept;
   Slice(T *, std::size_t count) noexcept;
 
-  Slice &operator=(const Slice<T> &) noexcept = default;
-  Slice &operator=(Slice<T> &&) noexcept = default;
+  Slice &operator=(const Slice<T> &) & noexcept = default;
+  Slice &operator=(Slice<T> &&) & noexcept = default;
 
   T *data() const noexcept;
   std::size_t size() const noexcept;
@@ -248,7 +248,7 @@ class Box final {
   explicit Box(const T &);
   explicit Box(T &&);
 
-  Box &operator=(Box &&) noexcept;
+  Box &operator=(Box &&) & noexcept;
 
   const T *operator->() const noexcept;
   const T &operator*() const noexcept;
@@ -293,8 +293,8 @@ class Vec final {
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
-  Vec &operator=(Vec &&) noexcept;
-  Vec &operator=(const Vec &);
+  Vec &operator=(Vec &&) & noexcept;
+  Vec &operator=(const Vec &) &;
 
   std::size_t size() const noexcept;
   bool empty() const noexcept;
@@ -371,8 +371,8 @@ class Error final : public std::exception {
   Error(Error &&) noexcept;
   ~Error() noexcept override;
 
-  Error &operator=(const Error &);
-  Error &operator=(Error &&) noexcept;
+  Error &operator=(const Error &) &;
+  Error &operator=(Error &&) & noexcept;
 
   const char *what() const noexcept override;
 
@@ -735,7 +735,7 @@ Box<T>::~Box() noexcept {
 }
 
 template <typename T>
-Box<T> &Box<T>::operator=(Box &&other) noexcept {
+Box<T> &Box<T>::operator=(Box &&other) & noexcept {
   if (this->ptr) {
     this->drop();
   }
@@ -823,7 +823,7 @@ Vec<T>::~Vec() noexcept {
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
+Vec<T> &Vec<T>::operator=(Vec &&other) & noexcept {
   this->drop();
   this->repr = other.repr;
   new (&other) Vec();
@@ -831,7 +831,7 @@ Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(const Vec &other) {
+Vec<T> &Vec<T>::operator=(const Vec &other) & {
   if (this != &other) {
     this->drop();
     new (this) Vec(other);
diff --git a/src/cxx.cc b/src/cxx.cc
index 2e4e0a0bb..0f87bfe9f 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -100,7 +100,7 @@ String::String(const char *s, std::size_t len) {
              len);
 }
 
-String &String::operator=(const String &other) noexcept {
+String &String::operator=(const String &other) & noexcept {
   if (this != &other) {
     cxxbridge1$string$drop(this);
     cxxbridge1$string$clone(this, other);
@@ -108,7 +108,7 @@ String &String::operator=(const String &other) noexcept {
   return *this;
 }
 
-String &String::operator=(String &&other) noexcept {
+String &String::operator=(String &&other) & noexcept {
   cxxbridge1$string$drop(this);
   this->repr = other.repr;
   cxxbridge1$string$new(&other);
@@ -376,7 +376,7 @@ Error::Error(Error &&other) noexcept
 
 Error::~Error() noexcept { delete[] this->msg; }
 
-Error &Error::operator=(const Error &other) {
+Error &Error::operator=(const Error &other) & {
   if (this != &other) {
     std::exception::operator=(other);
     delete[] this->msg;
@@ -389,7 +389,7 @@ Error &Error::operator=(const Error &other) {
   return *this;
 }
 
-Error &Error::operator=(Error &&other) noexcept {
+Error &Error::operator=(Error &&other) & noexcept {
   std::exception::operator=(std::move(other));
   this->msg = other.msg;
   this->len = other.len;


Test patch: