diff --git a/dom/base/EventSource.cpp b/dom/base/EventSource.cpp
index 12f443e7e83cb6ffa66e45ae813d7667d6e15e3b..0d1e9495a01e1509d8f1b37116499211a4c62af8 100644
--- a/dom/base/EventSource.cpp
+++ b/dom/base/EventSource.cpp
@@ -4,14 +4,13 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/EventSource.h"
-
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Components.h"
 #include "mozilla/DataMutex.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/DOMEventTargetHelper.h"
+#include "mozilla/dom/EventSource.h"
 #include "mozilla/dom/EventSourceBinding.h"
 #include "mozilla/dom/MessageEvent.h"
 #include "mozilla/dom/MessageEventBinding.h"
@@ -793,7 +792,7 @@ void EventSourceImpl::ParseSegment(const char* aBuffer, uint32_t aLength) {
     uint32_t result;
     size_t read;
     size_t written;
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         mUnicodeDecoder->DecodeToUTF16(src, dst, false);
     for (auto c : dst.To(written)) {
       nsresult rv = ParseCharacter(c);
diff --git a/dom/encoding/TextDecoder.cpp b/dom/encoding/TextDecoder.cpp
index 699c76b571579f0d3d87eaa73d5b15ed3bea3a1c..2396dacff4f688f0cc39b6c1777e07e017e26612 100644
--- a/dom/encoding/TextDecoder.cpp
+++ b/dom/encoding/TextDecoder.cpp
@@ -9,6 +9,7 @@
 #include "mozilla/Encoding.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "nsContentUtils.h"
+
 #include <stdint.h>
 
 namespace mozilla::dom {
@@ -64,14 +65,14 @@ void TextDecoder::Decode(Span<const uint8_t> aInput, const bool aStream,
   size_t read;
   size_t written;
   if (mFatal) {
-    Tie(result, read, written) =
+    std::tie(result, read, written) =
         mDecoder->DecodeToUTF16WithoutReplacement(aInput, *output, !aStream);
     if (result != kInputEmpty) {
       aRv.ThrowTypeError<MSG_DOM_DECODING_FAILED>();
       return;
     }
   } else {
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         mDecoder->DecodeToUTF16(aInput, *output, !aStream);
   }
   MOZ_ASSERT(result == kInputEmpty);
diff --git a/dom/file/FileReader.cpp b/dom/file/FileReader.cpp
index 027116910de9e1433a4ecae141b97dd4f8cbf907..81ef5d88fe4daf4abef7048de8b63fcbc46dcf21 100644
--- a/dom/file/FileReader.cpp
+++ b/dom/file/FileReader.cpp
@@ -474,7 +474,7 @@ nsresult FileReader::GetAsText(Blob* aBlob, const nsACString& aCharset,
 
   auto data = Span(reinterpret_cast<const uint8_t*>(aFileData), aDataLen);
   nsresult rv;
-  Tie(rv, Ignore) = encoding->Decode(data, aResult);
+  std::tie(rv, std::ignore) = encoding->Decode(data, aResult);
   return NS_FAILED(rv) ? rv : NS_OK;
 }
 
diff --git a/dom/html/HTMLFormSubmission.cpp b/dom/html/HTMLFormSubmission.cpp
index 6d584f8fce564b027f8044afcdd896823b58cfb1..a7141c3cd9a4737fb6eba18d8e6a4c29ac03d23d 100644
--- a/dom/html/HTMLFormSubmission.cpp
+++ b/dom/html/HTMLFormSubmission.cpp
@@ -5,11 +5,9 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "HTMLFormSubmission.h"
-
 #include "HTMLFormElement.h"
 #include "HTMLFormSubmissionConstants.h"
 #include "nsCOMPtr.h"
-#include "mozilla/dom/Document.h"
 #include "nsComponentManagerUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIFormControl.h"
@@ -31,12 +29,15 @@
 #include "nsCExternalHandlerService.h"
 #include "nsContentUtils.h"
 
+#include "mozilla/dom/Document.h"
 #include "mozilla/dom/AncestorIterator.h"
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/RandomNum.h"
 
+#include <tuple>
+
 namespace mozilla::dom {
 
 namespace {
@@ -716,7 +717,7 @@ nsresult EncodingFormSubmission::EncodeVal(const nsAString& aStr,
                                            nsCString& aOut,
                                            EncodeType aEncodeType) {
   nsresult rv;
-  Tie(rv, Ignore) = mEncoding->Encode(aStr, aOut);
+  std::tie(rv, std::ignore) = mEncoding->Encode(aStr, aOut);
   if (NS_FAILED(rv)) {
     return rv;
   }
diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
index c783123365cbe7a5891ca019fbf04871008b9d33..602ff58a2f677b733622d0360acf0b2bc59f654d 100644
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -4,10 +4,9 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "ActorsChild.h"
-
 #include <type_traits>
 
+#include "ActorsChild.h"
 #include "BackgroundChildImpl.h"
 #include "IDBDatabase.h"
 #include "IDBEvents.h"
@@ -901,7 +900,7 @@ nsresult GetFileHandleResult(const RefPtr<IDBFileRequest>& aFileRequest,
   }
 
   nsString tmpString;
-  Tie(rv, Ignore) = encoding->Decode(data, tmpString);
+  std::tie(rv, std::ignore) = encoding->Decode(data, tmpString);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
   }
diff --git a/dom/script/ScriptDecoding.h b/dom/script/ScriptDecoding.h
index f9e317edae61a71428bfefdbc9942dd822864145..f39818537428ca47ec413ef0ed106cf1662d986b 100644
--- a/dom/script/ScriptDecoding.h
+++ b/dom/script/ScriptDecoding.h
@@ -13,9 +13,7 @@
 #include "mozilla/CheckedInt.h"  // mozilla::CheckedInt
 #include "mozilla/Encoding.h"    // mozilla::Decoder
 #include "mozilla/Span.h"        // mozilla::Span
-#include "mozilla/Tuple.h"       // mozilla::Tie
 #include "mozilla/UniquePtr.h"   // mozilla::UniquePtr
-#include "mozilla/Unused.h"      // mozilla::Unused
 
 #include <stddef.h>     // size_t
 #include <stdint.h>     // uint8_t, uint32_t
@@ -44,7 +42,7 @@ struct ScriptDecoding<char16_t> {
     uint32_t result;
     size_t read;
     size_t written;
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         aDecoder->DecodeToUTF16(aSrc, aDest, aEndOfSource);
     MOZ_ASSERT(result == kInputEmpty);
     MOZ_ASSERT(read == aSrc.Length());
@@ -76,7 +74,7 @@ struct ScriptDecoding<Utf8Unit> {
     // twos-complement is mandated, we have to play fast and loose and *hope*
     // interpreting memory storing |uint8_t| as |char| will pick up the desired
     // wrapped-around value.  ¯\_(ツ)_/¯
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         aDecoder->DecodeToUTF8(aSrc, AsWritableBytes(aDest), aEndOfSource);
     MOZ_ASSERT(result == kInputEmpty);
     MOZ_ASSERT(read == aSrc.Length());
diff --git a/dom/script/ScriptLoadHandler.cpp b/dom/script/ScriptLoadHandler.cpp
index d048688bb2651f0035a5192b886c7a960a9ad018..2c256c63196e4cafde9e6558503c89a5b077ebae 100644
--- a/dom/script/ScriptLoadHandler.cpp
+++ b/dom/script/ScriptLoadHandler.cpp
@@ -19,7 +19,6 @@
 #include "mozilla/NotNull.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/StaticPrefs_dom.h"
-#include "mozilla/Tuple.h"
 #include "mozilla/Utf8.h"
 #include "mozilla/Vector.h"
 #include "mozilla/dom/Document.h"
@@ -197,7 +196,7 @@ bool ScriptLoadHandler::TrySetDecoder(nsIIncrementalStreamLoader* aLoader,
 
   // Do BOM detection.
   const Encoding* encoding;
-  Tie(encoding, Ignore) = Encoding::ForBOM(Span(aData, aDataLength));
+  std::tie(encoding, std::ignore) = Encoding::ForBOM(Span(aData, aDataLength));
   if (encoding) {
     mDecoder = encoding->NewDecoderWithBOMRemoval();
     return true;
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
index ba124e732a237d143dd4d69233dafbb81d96cabd..6e82173004ee034721e203184972db49b78dc7e1 100644
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -3724,7 +3724,7 @@ static nsresult ConvertToUnicode(nsIChannel* aChannel, const uint8_t* aData,
   UniquePtr<Decoder> unicodeDecoder;
 
   const Encoding* encoding;
-  Tie(encoding, Ignore) = Encoding::ForBOM(data);
+  std::tie(encoding, std::ignore) = Encoding::ForBOM(data);
   if (encoding) {
     unicodeDecoder = encoding->NewDecoderWithBOMRemoval();
   }
diff --git a/dom/serializers/nsDocumentEncoder.cpp b/dom/serializers/nsDocumentEncoder.cpp
index fe6d57d5c832e5d09ed6fbff7415e6e249317e82..34c6ff4334c96d82ec842db0caa2f1a4d9516269 100644
--- a/dom/serializers/nsDocumentEncoder.cpp
+++ b/dom/serializers/nsDocumentEncoder.cpp
@@ -9,17 +9,14 @@
  * to strings in a gazillion different ways.
  */
 
-#include "nsIDocumentEncoder.h"
-
 #include <utility>
 
 #include "nscore.h"
 #include "nsISupports.h"
-#include "mozilla/dom/Document.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include "nsIContentSerializer.h"
-#include "mozilla/Encoding.h"
+#include "nsIDocumentEncoder.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIOutputStream.h"
 #include "nsRange.h"
@@ -36,15 +33,17 @@
 #include "nsReadableUtils.h"
 #include "nsTArray.h"
 #include "nsIFrame.h"
+#include "nsLayoutUtils.h"
 #include "nsStringBuffer.h"
 #include "mozilla/dom/Comment.h"
+#include "mozilla/dom/Document.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLBRElement.h"
 #include "mozilla/dom/ProcessingInstruction.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/Text.h"
-#include "nsLayoutUtils.h"
+#include "mozilla/Encoding.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/UniquePtr.h"
@@ -125,7 +124,7 @@ nsresult TextStreamer::EncodeAndWrite() {
     size_t read;
     size_t written;
     if (mIsPlainText) {
-      Tie(result, read, written) =
+      std::tie(result, read, written) =
           mUnicodeEncoder->EncodeFromUTF16WithoutReplacement(src, dst, false);
       if (result != kInputEmpty && result != kOutputFull) {
         // There's always room for one byte in the case of
@@ -134,7 +133,7 @@ nsresult TextStreamer::EncodeAndWrite() {
         dst[written++] = '?';
       }
     } else {
-      Tie(result, read, written, Ignore) =
+      std::tie(result, read, written, std::ignore) =
           mUnicodeEncoder->EncodeFromUTF16(src, dst, false);
     }
     src = src.From(read);
diff --git a/dom/serviceworkers/ServiceWorkerEvents.cpp b/dom/serviceworkers/ServiceWorkerEvents.cpp
index 9570bb5bbd3746b94d4fd1f04b47b69520853b28..cb139d660d02a2adb8c397b9e5ce7e8eb2a8dcd2 100644
--- a/dom/serviceworkers/ServiceWorkerEvents.cpp
+++ b/dom/serviceworkers/ServiceWorkerEvents.cpp
@@ -1018,7 +1018,8 @@ nsresult ExtractBytesFromUSVString(const nsAString& aStr,
   uint32_t result;
   size_t read;
   size_t written;
-  Tie(result, read, written) =
+  // Do not use structured binding lest deal with [-Werror=unused-variable]
+  std::tie(result, read, written) =
       encoder->EncodeFromUTF16WithoutReplacement(aStr, aBytes, true);
   MOZ_ASSERT(result == kInputEmpty);
   MOZ_ASSERT(read == aStr.Length());
diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp
index 24d7f1859a9a3cc002d42350221687b754b9b107..3b160fc812f38d96c6d60c773c536fe343aadb86 100644
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -530,7 +530,7 @@ nsresult XMLHttpRequestMainThread::AppendToResponseText(
     uint32_t result;
     size_t read;
     size_t written;
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         mDecoder->DecodeToUTF16(aBuffer, handle.AsSpan().From(len), aLast);
     MOZ_ASSERT(result == kInputEmpty);
     MOZ_ASSERT(read == aBuffer.Length());
diff --git a/extensions/spellcheck/hunspell/glue/hunspell_csutil.cxx b/extensions/spellcheck/hunspell/glue/hunspell_csutil.cxx
index 7a2ef792ff9310e9ebae2aa636a8e4121176ad42..0f5565a12c61790ced4901985a8b86b436504571 100644
--- a/extensions/spellcheck/hunspell/glue/hunspell_csutil.cxx
+++ b/extensions/spellcheck/hunspell/glue/hunspell_csutil.cxx
@@ -72,8 +72,6 @@
 #include "hunspell_csutil.hxx"
 #include "mozilla/Encoding.h"
 #include "mozilla/Span.h"
-#include "mozilla/Tuple.h"
-
 #include "nsUnicharUtils.h"
 
 /* This is a copy of get_current_cs from the hunspell csutil.cxx file.
@@ -116,14 +114,14 @@ struct cs_info* hunspell_get_current_cs(const std::string& es) {
       uint32_t result;
       size_t read;
       size_t written;
-      mozilla::Tie(result, read, written) =
+      std::tie(result, read, written) =
           decoder->DecodeToUTF16WithoutReplacement(src1, dst1, true);
       if (result != mozilla::kInputEmpty || read != 1 || written != 1) {
         break;
       }
 
       uniCased = ToLowerCase(uni[0]);
-      mozilla::Tie(result, read, written) =
+      std::tie(result, read, written) =
           encoder->EncodeFromUTF16WithoutReplacement(src2, dst2, true);
       if (result != mozilla::kInputEmpty || read != 1 || written != 1) {
         break;
@@ -131,7 +129,7 @@ struct cs_info* hunspell_get_current_cs(const std::string& es) {
       lower = destination[0];
 
       uniCased = ToUpperCase(uni[0]);
-      mozilla::Tie(result, read, written) =
+      std::tie(result, read, written) =
           encoder->EncodeFromUTF16WithoutReplacement(src2, dst2, true);
       if (result != mozilla::kInputEmpty || read != 1 || written != 1) {
         break;
diff --git a/extensions/spellcheck/hunspell/glue/mozHunspell.cpp b/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
index 1f98e26f34b0e458c79dd536f89bd60d43efc2e6..2a2e1ac27bc3e1eb61836b65af808cc03307e2c6 100644
--- a/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
@@ -66,7 +66,6 @@
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "mozInlineSpellChecker.h"
-#include <stdlib.h>
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsNetUtil.h"
@@ -74,6 +73,9 @@
 #include "mozilla/Components.h"
 #include "mozilla/Services.h"
 
+#include <stdlib.h>
+#include <tuple>
+
 using mozilla::dom::ContentParent;
 using namespace mozilla;
 
@@ -373,11 +375,9 @@ nsresult mozHunspell::ConvertCharset(const nsAString& aStr, std::string& aDst) {
   auto dst = Span(reinterpret_cast<uint8_t*>(dstPtr), needed.value());
 
   uint32_t result;
-  size_t read;
   size_t written;
-  Tie(result, read, written) =
+  std::tie(result, std::ignore, written) =
       mEncoder->EncodeFromUTF16WithoutReplacement(src, dst, true);
-  Unused << read;
   MOZ_ASSERT(result != kOutputFull);
   if (result != kInputEmpty) {
     return NS_ERROR_UENC_NOMAPPING;
diff --git a/intl/Encoding.h b/intl/Encoding.h
index ee57422e943b131e3eadb4e7e80d47330fc8fcaf..3b5639e431d1d047061c6d695e28ef15638fdf9f 100644
--- a/intl/Encoding.h
+++ b/intl/Encoding.h
@@ -18,9 +18,10 @@
 #include "mozilla/Maybe.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/Span.h"
-#include "mozilla/Tuple.h"
 #include "nsString.h"
 
+#include <tuple>
+
 namespace mozilla {
 class Encoding;
 class Decoder;
@@ -213,15 +214,16 @@ class Encoding final {
    * stream (non-streaming case) or a buffer representing at least the first
    * three bytes of the input stream (streaming case).
    *
-   * Returns `MakeTuple(UTF_8_ENCODING, 3)`, `MakeTuple(UTF_16LE_ENCODING, 2)`
-   * or `MakeTuple(UTF_16BE_ENCODING, 3)` if the argument starts with the
-   * UTF-8, UTF-16LE or UTF-16BE BOM or `MakeTuple(nullptr, 0)` otherwise.
+   * Returns `{UTF_8_ENCODING, 3}`,
+   * `{UTF_16LE_ENCODING, 2}` or
+   * `{UTF_16BE_ENCODING, 3}` if the argument starts with the
+   * UTF-8, UTF-16LE or UTF-16BE BOM or `{nullptr, 0}` otherwise.
    */
-  static inline Tuple<const Encoding*, size_t> ForBOM(
+  static inline std::tuple<const Encoding*, size_t> ForBOM(
       Span<const uint8_t> aBuffer) {
     size_t len = aBuffer.Length();
     const Encoding* encoding = encoding_for_bom(aBuffer.Elements(), &len);
-    return MakeTuple(encoding, len);
+    return {encoding, len};
   }
 
   /**
@@ -308,7 +310,7 @@ class Encoding final {
    * a segment of the input instead of the whole input. Use `NewDecoder()`
    * when decoding segmented input.
    */
-  inline Tuple<nsresult, NotNull<const mozilla::Encoding*>> Decode(
+  inline std::tuple<nsresult, NotNull<const mozilla::Encoding*>> Decode(
       const nsACString& aBytes, nsACString& aOut) const {
     const Encoding* encoding = this;
     const nsACString* bytes = &aBytes;
@@ -320,7 +322,7 @@ class Encoding final {
     } else {
       rv = mozilla_encoding_decode_to_nscstring(&encoding, bytes, out);
     }
-    return MakeTuple(rv, WrapNotNull(encoding));
+    return {rv, WrapNotNull(encoding)};
   }
 
   /**
@@ -344,12 +346,12 @@ class Encoding final {
    * a segment of the input instead of the whole input. Use `NewDecoder()`
    * when decoding segmented input.
    */
-  inline Tuple<nsresult, NotNull<const mozilla::Encoding*>> Decode(
+  inline std::tuple<nsresult, NotNull<const mozilla::Encoding*>> Decode(
       Span<const uint8_t> aBytes, nsAString& aOut) const {
     const Encoding* encoding = this;
     nsresult rv = mozilla_encoding_decode_to_nsstring(
         &encoding, aBytes.Elements(), aBytes.Length(), &aOut);
-    return MakeTuple(rv, WrapNotNull(encoding));
+    return {rv, WrapNotNull(encoding)};
   }
 
   /**
@@ -601,7 +603,7 @@ class Encoding final {
    * a segment of the input instead of the whole input. Use `NewEncoder()`
    * when encoding segmented output.
    */
-  inline Tuple<nsresult, NotNull<const mozilla::Encoding*>> Encode(
+  inline std::tuple<nsresult, NotNull<const mozilla::Encoding*>> Encode(
       const nsACString& aString, nsACString& aOut) const {
     const Encoding* encoding = this;
     const nsACString* string = &aString;
@@ -613,7 +615,7 @@ class Encoding final {
     } else {
       rv = mozilla_encoding_encode_from_nscstring(&encoding, string, out);
     }
-    return MakeTuple(rv, WrapNotNull(encoding));
+    return {rv, WrapNotNull(encoding)};
   }
 
   /**
@@ -637,12 +639,12 @@ class Encoding final {
    * a segment of the input instead of the whole input. Use `NewEncoder()`
    * when encoding segmented output.
    */
-  inline Tuple<nsresult, NotNull<const mozilla::Encoding*>> Encode(
+  inline std::tuple<nsresult, NotNull<const mozilla::Encoding*>> Encode(
       Span<const char16_t> aString, nsACString& aOut) const {
     const Encoding* encoding = this;
     nsresult rv = mozilla_encoding_encode_from_utf16(
         &encoding, aString.Elements(), aString.Length(), &aOut);
-    return MakeTuple(rv, WrapNotNull(encoding));
+    return {rv, WrapNotNull(encoding)};
   }
 
   /**
@@ -944,7 +946,7 @@ class Decoder final {
    * See the documentation of the class for documentation for `Decode*`
    * methods collectively.
    */
-  inline Tuple<uint32_t, size_t, size_t, bool> DecodeToUTF8(
+  inline std::tuple<uint32_t, size_t, size_t, bool> DecodeToUTF8(
       Span<const uint8_t> aSrc, Span<uint8_t> aDst, bool aLast) {
     size_t srcRead = aSrc.Length();
     size_t dstWritten = aDst.Length();
@@ -952,7 +954,7 @@ class Decoder final {
     uint32_t result =
         decoder_decode_to_utf8(this, aSrc.Elements(), &srcRead, aDst.Elements(),
                                &dstWritten, aLast, &hadReplacements);
-    return MakeTuple(result, srcRead, dstWritten, hadReplacements);
+    return {result, srcRead, dstWritten, hadReplacements};
   }
 
   /**
@@ -961,13 +963,13 @@ class Decoder final {
    * See the documentation of the class for documentation for `Decode*`
    * methods collectively.
    */
-  inline Tuple<uint32_t, size_t, size_t> DecodeToUTF8WithoutReplacement(
+  inline std::tuple<uint32_t, size_t, size_t> DecodeToUTF8WithoutReplacement(
       Span<const uint8_t> aSrc, Span<uint8_t> aDst, bool aLast) {
     size_t srcRead = aSrc.Length();
     size_t dstWritten = aDst.Length();
     uint32_t result = decoder_decode_to_utf8_without_replacement(
         this, aSrc.Elements(), &srcRead, aDst.Elements(), &dstWritten, aLast);
-    return MakeTuple(result, srcRead, dstWritten);
+    return {result, srcRead, dstWritten};
   }
 
   /**
@@ -998,7 +1000,7 @@ class Decoder final {
    * See the documentation of the class for documentation for `Decode*`
    * methods collectively.
    */
-  inline Tuple<uint32_t, size_t, size_t, bool> DecodeToUTF16(
+  inline std::tuple<uint32_t, size_t, size_t, bool> DecodeToUTF16(
       Span<const uint8_t> aSrc, Span<char16_t> aDst, bool aLast) {
     size_t srcRead = aSrc.Length();
     size_t dstWritten = aDst.Length();
@@ -1006,7 +1008,7 @@ class Decoder final {
     uint32_t result = decoder_decode_to_utf16(this, aSrc.Elements(), &srcRead,
                                               aDst.Elements(), &dstWritten,
                                               aLast, &hadReplacements);
-    return MakeTuple(result, srcRead, dstWritten, hadReplacements);
+    return {result, srcRead, dstWritten, hadReplacements};
   }
 
   /**
@@ -1015,13 +1017,13 @@ class Decoder final {
    * See the documentation of the class for documentation for `Decode*`
    * methods collectively.
    */
-  inline Tuple<uint32_t, size_t, size_t> DecodeToUTF16WithoutReplacement(
+  inline std::tuple<uint32_t, size_t, size_t> DecodeToUTF16WithoutReplacement(
       Span<const uint8_t> aSrc, Span<char16_t> aDst, bool aLast) {
     size_t srcRead = aSrc.Length();
     size_t dstWritten = aDst.Length();
     uint32_t result = decoder_decode_to_utf16_without_replacement(
         this, aSrc.Elements(), &srcRead, aDst.Elements(), &dstWritten, aLast);
-    return MakeTuple(result, srcRead, dstWritten);
+    return {result, srcRead, dstWritten};
   }
 
   /**
@@ -1239,7 +1241,7 @@ class Encoder final {
    * The input ***MUST*** be valid UTF-8 or bad things happen! Unless
    * absolutely sure, use `Encoding::UTF8ValidUpTo()` to check.
    */
-  inline Tuple<uint32_t, size_t, size_t, bool> EncodeFromUTF8(
+  inline std::tuple<uint32_t, size_t, size_t, bool> EncodeFromUTF8(
       Span<const uint8_t> aSrc, Span<uint8_t> aDst, bool aLast) {
     size_t srcRead = aSrc.Length();
     size_t dstWritten = aDst.Length();
@@ -1247,7 +1249,7 @@ class Encoder final {
     uint32_t result = encoder_encode_from_utf8(this, aSrc.Elements(), &srcRead,
                                                aDst.Elements(), &dstWritten,
                                                aLast, &hadReplacements);
-    return MakeTuple(result, srcRead, dstWritten, hadReplacements);
+    return {result, srcRead, dstWritten, hadReplacements};
   }
 
   /**
@@ -1260,13 +1262,13 @@ class Encoder final {
    * The input ***MUST*** be valid UTF-8 or bad things happen! Unless
    * absolutely sure, use `Encoding::UTF8ValidUpTo()` to check.
    */
-  inline Tuple<uint32_t, size_t, size_t> EncodeFromUTF8WithoutReplacement(
+  inline std::tuple<uint32_t, size_t, size_t> EncodeFromUTF8WithoutReplacement(
       Span<const uint8_t> aSrc, Span<uint8_t> aDst, bool aLast) {
     size_t srcRead = aSrc.Length();
     size_t dstWritten = aDst.Length();
     uint32_t result = encoder_encode_from_utf8_without_replacement(
         this, aSrc.Elements(), &srcRead, aDst.Elements(), &dstWritten, aLast);
-    return MakeTuple(result, srcRead, dstWritten);
+    return {result, srcRead, dstWritten};
   }
 
   /**
@@ -1319,7 +1321,7 @@ class Encoder final {
    * See the documentation of the class for documentation for `Encode*`
    * methods collectively.
    */
-  inline Tuple<uint32_t, size_t, size_t, bool> EncodeFromUTF16(
+  inline std::tuple<uint32_t, size_t, size_t, bool> EncodeFromUTF16(
       Span<const char16_t> aSrc, Span<uint8_t> aDst, bool aLast) {
     size_t srcRead = aSrc.Length();
     size_t dstWritten = aDst.Length();
@@ -1327,7 +1329,7 @@ class Encoder final {
     uint32_t result = encoder_encode_from_utf16(this, aSrc.Elements(), &srcRead,
                                                 aDst.Elements(), &dstWritten,
                                                 aLast, &hadReplacements);
-    return MakeTuple(result, srcRead, dstWritten, hadReplacements);
+    return {result, srcRead, dstWritten, hadReplacements};
   }
 
   /**
@@ -1336,13 +1338,13 @@ class Encoder final {
    * See the documentation of the class for documentation for `Encode*`
    * methods collectively.
    */
-  inline Tuple<uint32_t, size_t, size_t> EncodeFromUTF16WithoutReplacement(
+  inline std::tuple<uint32_t, size_t, size_t> EncodeFromUTF16WithoutReplacement(
       Span<const char16_t> aSrc, Span<uint8_t> aDst, bool aLast) {
     size_t srcRead = aSrc.Length();
     size_t dstWritten = aDst.Length();
     uint32_t result = encoder_encode_from_utf16_without_replacement(
         this, aSrc.Elements(), &srcRead, aDst.Elements(), &dstWritten, aLast);
-    return MakeTuple(result, srcRead, dstWritten);
+    return {result, srcRead, dstWritten};
   }
 
  private:
diff --git a/intl/gtest/TestEncoding.cpp b/intl/gtest/TestEncoding.cpp
index e6be8e56ee0c2f8e468757f32e21689241e2fce9..24ffa243901c08c9851d558f212974d5d6dad165 100644
--- a/intl/gtest/TestEncoding.cpp
+++ b/intl/gtest/TestEncoding.cpp
@@ -28,19 +28,19 @@ ENCODING_TEST(ForBOM) {
   nsAutoCString data("\xEF\xBB\xBF\x61");
   const Encoding* encoding;
   size_t bomLength;
-  Tie(encoding, bomLength) = Encoding::ForBOM(data);
+  std::tie(encoding, bomLength) = Encoding::ForBOM(data);
   ASSERT_EQ(encoding, UTF_8_ENCODING);
   ASSERT_EQ(bomLength, 3U);
   data.AssignLiteral("\xFF\xFE");
-  Tie(encoding, bomLength) = Encoding::ForBOM(data);
+  std::tie(encoding, bomLength) = Encoding::ForBOM(data);
   ASSERT_EQ(encoding, UTF_16LE_ENCODING);
   ASSERT_EQ(bomLength, 2U);
   data.AssignLiteral("\xFE\xFF");
-  Tie(encoding, bomLength) = Encoding::ForBOM(data);
+  std::tie(encoding, bomLength) = Encoding::ForBOM(data);
   ASSERT_EQ(encoding, UTF_16BE_ENCODING);
   ASSERT_EQ(bomLength, 2U);
   data.AssignLiteral("\xEF\xBB");
-  Tie(encoding, bomLength) = Encoding::ForBOM(data);
+  std::tie(encoding, bomLength) = Encoding::ForBOM(data);
   ASSERT_EQ(encoding, nullptr);
   ASSERT_EQ(bomLength, 0U);
 }
diff --git a/intl/uconv/nsConverterInputStream.cpp b/intl/uconv/nsConverterInputStream.cpp
index 7e44f086b0d4e738849f25993807fe1d298d9261..fd2acce1231f4fb71f5122b3f4d9a0fded8e1cef 100644
--- a/intl/uconv/nsConverterInputStream.cpp
+++ b/intl/uconv/nsConverterInputStream.cpp
@@ -7,8 +7,9 @@
 #include "nsIInputStream.h"
 #include "nsReadLine.h"
 #include "nsStreamUtils.h"
+
 #include <algorithm>
-#include "mozilla/Unused.h"
+#include <tuple>
 
 using namespace mozilla;
 
@@ -212,10 +213,10 @@ uint32_t nsConverterInputStream::Fill(nsresult* aErrorCode) {
   // errors are ignored. Always passing false as the last argument to
   // Decode* calls below.
   if (mErrorsAreFatal) {
-    Tie(result, read, written) =
+    std::tie(result, read, written) =
         mConverter->DecodeToUTF16WithoutReplacement(src, dst, false);
   } else {
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         mConverter->DecodeToUTF16(src, dst, false);
   }
   mLeftOverBytes = mByteData.Length() - read;
diff --git a/intl/uconv/nsConverterOutputStream.cpp b/intl/uconv/nsConverterOutputStream.cpp
index 4c7094c4707d7f2e46876be71c6b2f221a462b70..a24adb03777f1fcd079910211e1001542e7122e5 100644
--- a/intl/uconv/nsConverterOutputStream.cpp
+++ b/intl/uconv/nsConverterOutputStream.cpp
@@ -4,13 +4,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsCOMPtr.h"
-
 #include "nsIOutputStream.h"
 #include "nsString.h"
-
 #include "nsConverterOutputStream.h"
 #include "mozilla/Encoding.h"
-#include "mozilla/Unused.h"
 
 using namespace mozilla;
 
@@ -57,7 +54,7 @@ nsConverterOutputStream::Write(uint32_t aCount, const char16_t* aChars,
     uint32_t result;
     size_t read;
     size_t written;
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         mConverter->EncodeFromUTF16(src, dst, false);
     src = src.From(read);
     uint32_t streamWritten;
@@ -93,9 +90,8 @@ nsConverterOutputStream::Flush() {
   auto dst = Span(buffer);
   Span<char16_t> src(nullptr);
   uint32_t result;
-  size_t read;
   size_t written;
-  Tie(result, read, written, Ignore) =
+  std::tie(result, std::ignore, written, std::ignore) =
       mConverter->EncodeFromUTF16(src, dst, true);
   MOZ_ASSERT(result == kInputEmpty);
   uint32_t streamWritten;
diff --git a/intl/uconv/nsScriptableUConv.cpp b/intl/uconv/nsScriptableUConv.cpp
index d8162f9a3c0cbc57b9c2143397bf8e0269a4abe0..8a9638f2ce5f428ccebfc593f13d632f0dcd2016 100644
--- a/intl/uconv/nsScriptableUConv.cpp
+++ b/intl/uconv/nsScriptableUConv.cpp
@@ -10,6 +10,8 @@
 #include "nsIStringStream.h"
 #include "nsComponentManagerUtils.h"
 
+#include <tuple>
+
 using namespace mozilla;
 
 /* Implementation file */
@@ -47,10 +49,7 @@ nsScriptableUnicodeConverter::ConvertFromUnicode(const nsAString& aSrc,
   auto dst = AsWritableBytes(*dstChars);
   size_t totalWritten = 0;
   for (;;) {
-    uint32_t result;
-    size_t read;
-    size_t written;
-    Tie(result, read, written) =
+    auto [result, read, written] =
         mEncoder->EncodeFromUTF16WithoutReplacement(src, dst, false);
     if (result != kInputEmpty && result != kOutputFull) {
       MOZ_RELEASE_ASSERT(written < dst.Length(),
@@ -94,7 +93,7 @@ nsScriptableUnicodeConverter::Finish(nsACString& _retval) {
   uint32_t result;
   size_t read;
   size_t written;
-  Tie(result, read, written, Ignore) =
+  std::tie(result, read, written, std::ignore) =
       mEncoder->EncodeFromUTF16(src, dst, true);
   MOZ_ASSERT(!read);
   MOZ_ASSERT(result == kInputEmpty);
@@ -132,13 +131,13 @@ nsScriptableUnicodeConverter::ConvertToUnicode(const nsACString& aSrc,
   // If callers want control over the behavior, they should switch to
   // TextDecoder.
   if (mDecoder->Encoding() == UTF_8_ENCODING) {
-    Tie(result, read, written) =
+    std::tie(result, read, written) =
         mDecoder->DecodeToUTF16WithoutReplacement(src, *dst, false);
     if (result != kInputEmpty) {
       return NS_ERROR_UDEC_ILLEGALINPUT;
     }
   } else {
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         mDecoder->DecodeToUTF16(src, *dst, false);
   }
   MOZ_ASSERT(result == kInputEmpty);
@@ -170,10 +169,7 @@ nsScriptableUnicodeConverter::ConvertToByteArray(const nsAString& aString,
   auto dst = Span(data, needed.value());
   size_t totalWritten = 0;
   for (;;) {
-    uint32_t result;
-    size_t read;
-    size_t written;
-    Tie(result, read, written) =
+    auto [result, read, written] =
         mEncoder->EncodeFromUTF16WithoutReplacement(src, dst, true);
     if (result != kInputEmpty && result != kOutputFull) {
       // There's always room for one byte in the case of
diff --git a/intl/uconv/nsTextToSubURI.cpp b/intl/uconv/nsTextToSubURI.cpp
index 897b338ed6fda4b42acc057869d1c8664915ee7b..5913800461629a3df8b7837321f214cbcff5c85f 100644
--- a/intl/uconv/nsTextToSubURI.cpp
+++ b/intl/uconv/nsTextToSubURI.cpp
@@ -29,7 +29,7 @@ nsTextToSubURI::ConvertAndEscape(const nsACString& aCharset,
   }
   nsresult rv;
   nsAutoCString intermediate;
-  Tie(rv, Ignore) = encoding->Encode(aText, intermediate);
+  std::tie(rv, std::ignore) = encoding->Encode(aText, intermediate);
   if (NS_FAILED(rv)) {
     aOut.Truncate();
     return rv;
diff --git a/layout/style/StreamLoader.cpp b/layout/style/StreamLoader.cpp
index 93a65dfb96a0e19b185cfb7d2df86d7c1a6e33bc..625ce581ac6814587d83a92353aa6919bf08ae73 100644
--- a/layout/style/StreamLoader.cpp
+++ b/layout/style/StreamLoader.cpp
@@ -150,9 +150,7 @@ void StreamLoader::HandleBOM() {
   MOZ_ASSERT(mEncodingFromBOM.isNothing());
   MOZ_ASSERT(mBytes.IsEmpty());
 
-  const Encoding* encoding;
-  size_t bomLength;
-  Tie(encoding, bomLength) = Encoding::ForBOM(mBOMBytes);
+  auto [encoding, bomLength] = Encoding::ForBOM(mBOMBytes);
   mEncodingFromBOM.emplace(encoding);  // Null means no BOM.
 
   // BOMs are three bytes at most, but may be fewer. Copy over anything
diff --git a/netwerk/base/nsStandardURL.cpp b/netwerk/base/nsStandardURL.cpp
index 1fdbd9ca75c756ffe3fd46557087bb15f911e88b..2d5340745e696025d7a80b7b7f7c81cb37d66e64 100644
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -143,10 +143,7 @@ int32_t nsStandardURL::nsSegmentEncoder::EncodeSegmentCount(
 
       size_t totalRead = 0;
       for (;;) {
-        uint32_t encoderResult;
-        size_t read;
-        size_t written;
-        Tie(encoderResult, read, written) =
+        auto [encoderResult, read, written] =
             encoder->EncodeFromUTF8WithoutReplacement(
                 AsBytes(span.From(totalRead)), AsWritableBytes(buffer), true);
         totalRead += read;
diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp
index 47010180e3f82eb509cfc498f1eed9cab9c1f32e..3f0216c621981b76d63c6ae826e0e5b65a81e5b4 100644
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -1047,11 +1047,7 @@ nsresult nsHtml5StreamParser::WriteStreamBytes(
   auto src = aFromSegment;
   for (;;) {
     auto dst = mLastBuffer->TailAsSpan(READ_BUFFER_SIZE);
-    uint32_t result;
-    size_t read;
-    size_t written;
-    bool hadErrors;
-    Tie(result, read, written, hadErrors) =
+    auto [result, read, written, hadErrors] =
         mUnicodeDecoder->DecodeToUTF16(src, dst, false);
     if (!mDecodingLocalFileWithoutTokenizing) {
       OnNewContent(dst.To(written));
@@ -1377,7 +1373,8 @@ void nsHtml5StreamParser::DoStopRequest() {
     size_t read;
     size_t written;
     bool hadErrors;
-    Tie(result, read, written, hadErrors) =
+    // Do not use structured binding lest deal with [-Werror=unused-variable]
+    std::tie(result, read, written, hadErrors) =
         mUnicodeDecoder->DecodeToUTF16(src, dst, true);
     if (!mDecodingLocalFileWithoutTokenizing) {
       OnNewContent(dst.To(written));
diff --git a/parser/htmlparser/nsParser.cpp b/parser/htmlparser/nsParser.cpp
index db5dd988b6ee9b075cc481e951d2483ce8669355..566bb4ff00fc5318be3f94da67b610c485931d0a 100644
--- a/parser/htmlparser/nsParser.cpp
+++ b/parser/htmlparser/nsParser.cpp
@@ -25,15 +25,15 @@
 #include "nsHTMLTokenizer.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsMimeTypes.h"
-#include "mozilla/CondVar.h"
-#include "mozilla/Mutex.h"
 #include "nsCharsetSource.h"
 #include "nsThreadUtils.h"
 #include "nsIHTMLContentSink.h"
 
 #include "mozilla/BinarySearch.h"
+#include "mozilla/CondVar.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/Encoding.h"
+#include "mozilla/Mutex.h"
 
 using namespace mozilla;
 
@@ -1215,7 +1215,7 @@ static nsresult ParserWriteFunc(nsIInputStream* in, void* closure,
     // This code was bogus when I found it. It expects the BOM or the XML
     // declaration to be entirely in the first network buffer. -- hsivonen
     const Encoding* encoding;
-    Tie(encoding, Ignore) = Encoding::ForBOM(Span(buf, count));
+    std::tie(encoding, std::ignore) = Encoding::ForBOM(Span(buf, count));
     if (encoding) {
       // The decoder will swallow the BOM. The UTF-16 will re-sniff for
       // endianness. The value of preferred is now "UTF-8", "UTF-16LE"
diff --git a/parser/htmlparser/nsScanner.cpp b/parser/htmlparser/nsScanner.cpp
index 7095ef9392caef2c127490eda85e95f4e7803626..51913c87742dc79c0d0674ef31981b8000ab16ae 100644
--- a/parser/htmlparser/nsScanner.cpp
+++ b/parser/htmlparser/nsScanner.cpp
@@ -227,7 +227,8 @@ nsresult nsScanner::Append(const char* aBuffer, uint32_t aLen) {
     uint32_t result;
     size_t read;
     size_t written;
-    Tie(result, read, written) =
+    // Do not use structured binding lest deal with [-Werror=unused-variable]
+    std::tie(result, read, written) =
         mUnicodeDecoder->DecodeToUTF16WithoutReplacement(
             AsBytes(Span(aBuffer, aLen)), Span(unichars, needed.value()),
             false);  // Retain bug about failure to handle EOF
diff --git a/toolkit/components/osfile/NativeOSFileInternals.cpp b/toolkit/components/osfile/NativeOSFileInternals.cpp
index 62597e967323156aaf4063127109d42b35c2e90a..98bd780796548dfb0786e650bbac74e8feba2725 100644
--- a/toolkit/components/osfile/NativeOSFileInternals.cpp
+++ b/toolkit/components/osfile/NativeOSFileInternals.cpp
@@ -847,7 +847,7 @@ class DoReadToStringEvent final : public AbstractReadEvent {
     uint32_t result;
     size_t read;
     size_t written;
-    Tie(result, read, written, Ignore) =
+    std::tie(result, read, written, std::ignore) =
         mDecoder->DecodeToUTF16(src, *resultSpan, false);
     MOZ_ASSERT(result == kInputEmpty);
     MOZ_ASSERT(read == src.Length());
diff --git a/widget/gtk/nsClipboard.cpp b/widget/gtk/nsClipboard.cpp
index ed15e549de1984711737dfcfdbc6994f2953b723..868e394fd6ae71b4eef81ae1fba94699ed887fc1 100644
--- a/widget/gtk/nsClipboard.cpp
+++ b/widget/gtk/nsClipboard.cpp
@@ -919,7 +919,7 @@ bool ConvertHTMLtoUCS2(const char* data, int32_t dataLength, nsCString& charset,
     uint32_t result;
     size_t read;
     size_t written;
-    Tie(result, read, written, Ignore) = decoder->DecodeToUTF16(
+    std::tie(result, read, written, std::ignore) = decoder->DecodeToUTF16(
         AsBytes(dataSpan), Span(*unicodeData, needed.value()), true);
     MOZ_ASSERT(result == kInputEmpty);
     MOZ_ASSERT(read == size_t(dataSpan.Length()));