about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-09 14:50:14 +0000
committerbors <bors@rust-lang.org>2024-01-09 14:50:14 +0000
commit5876c8cdfd3df742c334d6447d44d760c77103b6 (patch)
treeb2437656721ba0a5f4068566975525a9bab87974 /src
parentbe00c5a9b89161b7f45ba80340f709e8e41122f9 (diff)
parentf41d7739880e72743a74722ae6fcc1be9f7b4e5c (diff)
downloadrust-5876c8cdfd3df742c334d6447d44d760c77103b6.tar.gz
rust-5876c8cdfd3df742c334d6447d44d760c77103b6.zip
Auto merge of #119767 - GuillaumeGomez:rollup-fbp26yb, r=GuillaumeGomez
Rollup of 9 pull requests

Successful merges:

 - #117556 (Disallow reference to `static mut` and adding `static_mut_ref` lint)
 - #118748 (std: getrandom simplification for freebsd.)
 - #119282 (Rework and improve the unstable documentation of check-cfg)
 - #119527 (don't reexport atomic::ordering via rustc_data_structures, use std import)
 - #119668 (Simplify implementation of MIR promotion)
 - #119699 (Merge dead bb pruning and unreachable bb deduplication.)
 - #119723 (Remove `-Zdont-buffer-diagnostics`.)
 - #119756 (rustdoc-search: reuse individual types in function signatures)
 - #119758 (GNU/Hurd: unconditionally use inline stack probes)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/compiler-flags/check-cfg.md224
-rw-r--r--src/librustdoc/html/static/js/search.js111
-rw-r--r--src/tools/lint-docs/src/groups.rs1
-rw-r--r--src/tools/miri/tests/fail/tls/tls_static_dealloc.rs2
-rw-r--r--src/tools/miri/tests/pass/static_mut.rs3
-rw-r--r--src/tools/miri/tests/pass/tls/tls_static.rs2
6 files changed, 222 insertions, 121 deletions
diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
index 8ab6e83d99e..e8fc2fe986e 100644
--- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md
+++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
@@ -4,18 +4,16 @@ The tracking issue for this feature is: [#82450](https://github.com/rust-lang/ru
 
 ------------------------
 
-This feature allows you to enable complete or partial checking of configuration.
+This feature enables checking of conditional configuration.
 
 `rustc` accepts the `--check-cfg` option, which specifies whether to check conditions and how to
-check them. The `--check-cfg` option takes a value, called the _check cfg specification_. The
-check cfg specification is parsed using the Rust metadata syntax, just as the `--cfg` option is.
+check them. The `--check-cfg` option takes a value, called the _check cfg specification_.
+This specification has one form:
 
-`--check-cfg` option take one form:
+1. `--check-cfg cfg(...)` mark a configuration and it's expected values as expected.
 
-1. `--check-cfg cfg(...)` enables checking the values within list-valued conditions.
-
-NOTE: No implicit expectation is added when using `--cfg` for both forms. Users are expected to
-pass all expected names and values using `cfg(...)`.
+*No implicit expectation is added when using `--cfg`. Users are expected to
+pass all expected names and values using the _check cfg specification_.*
 
 ## The `cfg(...)` form
 
@@ -23,7 +21,7 @@ The `cfg(...)` form enables checking the values within list-valued conditions. I
 basic form:
 
 ```bash
-rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
+rustc --check-cfg 'cfg(name, values("value1", "value2", ... "valueN"))'
 ```
 
 where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
@@ -31,162 +29,186 @@ string. `name` specifies the name of the condition, such as `feature` or `my_cfg
 
 When the `cfg(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
 attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
-and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the
-list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs`
-lint diagnostic. The default diagnostic level for this lint is `Warn`.
+attribute and `cfg!(name = "value")` macro call. It will check that the `"value"` specified is
+present in the list of expected values. If `"value"` is not in it, then `rustc` will report an
+`unexpected_cfgs` lint diagnostic. The default diagnostic level for this lint is `Warn`.
 
-The command line `--cfg` arguments are currently *NOT* checked but may very well be checked in
-the future.
+*The command line `--cfg` arguments are currently *NOT* checked but may very well be checked in
+the future.*
 
-To enable checking of values, but to provide an empty set of expected values, use these forms:
+To enable checking of values, but to provide an *none*/empty set of expected values
+(ie. expect `#[cfg(name)]`), use these forms:
 
 ```bash
-rustc --check-cfg 'cfg(name1, ..., nameN)'
-rustc --check-cfg 'cfg(name1, ..., nameN, values())'
+rustc --check-cfg 'cfg(name)'
+rustc --check-cfg 'cfg(name, values())'
 ```
 
 To enable checking of name but not values (i.e. unknown expected values), use this form:
 
 ```bash
-rustc --check-cfg 'cfg(name1, ..., nameN, values(any()))'
+rustc --check-cfg 'cfg(name, values(any()))'
+```
+
+To avoid repeating the same set of values, use this form:
+
+```bash
+rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
 ```
 
 The `--check-cfg cfg(...)` option can be repeated, both for the same condition name and for
 different names. If it is repeated for the same condition name, then the sets of values for that
-condition are merged together (presedence is given to `any()`).
+condition are merged together (precedence is given to `values(any())`).
 
 ## Well known names and values
 
 `rustc` has a internal list of well known names and their corresponding values.
 Those well known names and values follows the same stability as what they refer to.
 
-Well known values checking is always enabled as long as a `--check-cfg` argument is present.
+Well known names and values checking is always enabled as long as at least one
+`--check-cfg` argument is present.
+
+As of `2024-01-09T`, the list of known names is as follows:
+
+<!--- See CheckCfg::fill_well_known in compiler/rustc_session/src/config.rs -->
+
+ - `debug_assertions`
+ - `doc`
+ - `doctest`
+ - `miri`
+ - `overflow_checks`
+ - `panic`
+ - `proc_macro`
+ - `relocation_model`
+ - `sanitize`
+ - `sanitizer_cfi_generalize_pointers`
+ - `sanitizer_cfi_normalize_integers`
+ - `target_abi`
+ - `target_arch`
+ - `target_endian`
+ - `target_env`
+ - `target_family`
+ - `target_feature`
+ - `target_has_atomic`
+ - `target_has_atomic_equal_alignment`
+ - `target_has_atomic_load_store`
+ - `target_os`
+ - `target_pointer_width`
+ - `target_thread_local`
+ - `target_vendor`
+ - `test`
+ - `unix`
+ - `windows`
+
+Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())`
+as argument to `--check-cfg`.
 
-Well known names checking is always enable as long as a `--check-cfg` argument is present
-**unless** any `cfg(any())` argument is passed.
+## Examples
 
-To disable checking of well known names, use this form:
+### Equivalence table
 
-```bash
-rustc --check-cfg 'cfg(any())'
-```
+This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument.
 
-NOTE: If one want to enable values and names checking without having any cfg to declare, one
-can use an empty `cfg()` argument.
+| `--cfg`                       | `--check-cfg`                                              |
+|-----------------------------|----------------------------------------------------------|
+| *nothing*                     | *nothing* or `--check-cfg=cfg()` (to enable the checking)  |
+| `--cfg foo`                   | `--check-cfg=cfg(foo) or --check-cfg=cfg(foo, values())`   |
+| `--cfg foo=""`                | `--check-cfg=cfg(foo, values(""))`                         |
+| `--cfg foo="bar"`             | `--check-cfg=cfg(foo, values("bar"))`                      |
+| `--cfg foo="1" --cfg foo="2"` | `--check-cfg=cfg(foo, values("1", "2"))`                   |
+| `--cfg foo="1" --cfg bar="2"` | `--check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2"))` |
+| `--cfg foo --cfg foo="bar"`   | `--check-cfg=cfg(foo) --check-cfg=cfg(foo, values("bar"))` |
 
-## Examples
+NOTE: There is (currently) no way to express that a condition name is expected but no (!= none)
+values are expected. Passing an empty `values()` means *(none)* in the sense of `#[cfg(foo)]`
+with no value. Users are expected to NOT pass a `--check-cfg` with that condition name.
+
+### Example: Cargo-like `feature` example
 
 Consider this command line:
 
 ```bash
 rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \
-      --cfg 'feature="lion"' -Z unstable-options \
-      example.rs
+      --cfg 'feature="lion"' -Z unstable-options example.rs
 ```
 
 This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
-feature is enabled, while the `zebra` feature is disabled. Exhaustive checking of names and
-values are enabled by default. Consider compiling this code:
+feature is enabled, while the `zebra` feature is disabled.
+Given the `--check-cfg` arguments, exhaustive checking of names and
+values are enabled.
 
+`example.rs`:
 ```rust
-// This is expected, and tame_lion() will be compiled
-#[cfg(feature = "lion")]
+#[cfg(feature = "lion")]     // This condition is expected, as "lion" is an expected value of `feature`
 fn tame_lion(lion: Lion) {}
 
-// This is expected, and ride_zebra() will NOT be compiled.
-#[cfg(feature = "zebra")]
-fn ride_zebra(zebra: Zebra) {}
+#[cfg(feature = "zebra")]    // This condition is expected, as "zebra" is an expected value of `feature`
+                             // but the condition will still evaluate to false
+                             // since only --cfg feature="lion" was passed
+fn ride_zebra(z: Zebra) {}
 
-// This is UNEXPECTED, and will cause a compiler warning (by default).
-#[cfg(feature = "platypus")]
+#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT an expected value of
+                             // `feature` and will cause a compiler warning (by default).
 fn poke_platypus() {}
 
-// This is UNEXPECTED, because 'feechure' is not a known condition name,
-// and will cause a compiler warning (by default).
-#[cfg(feechure = "lion")]
+#[cfg(feechure = "lion")]    // This condition is UNEXPECTED, as 'feechure' is NOT a expected condition
+                             // name, no `cfg(feechure, ...)` was passed in `--check-cfg`
 fn tame_lion() {}
 
-// This is UNEXPECTED, because 'windows' is a well known condition name,
-// and because 'windows' doesn't take any values,
-// and will cause a compiler warning (by default).
-#[cfg(windows = "unix")]
+#[cfg(windows = "unix")]     // This condition is UNEXPECTED, as while 'windows' is a well known
+                             // condition name, it doens't expect any values
 fn tame_windows() {}
 ```
 
-### Example: Checking condition names, but not values
+### Example: Multiple names and values
 
 ```bash
-# This turns on checking for condition names, but not values, such as 'feature' values.
-rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
-      --cfg has_feathers -Z unstable-options
+rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
+      --check-cfg 'cfg(feature, values("zapping", "lasers"))' \
+      --cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
 ```
 
 ```rust
-#[cfg(is_embedded)]         // This is expected as "is_embedded" was provided in cfg()
-fn do_embedded() {}         // and because names exhaustiveness was not disabled
-
-#[cfg(has_feathers)]        // This is expected as "has_feathers" was provided in cfg()
-fn do_features() {}         // and because names exhaustiveness was not disabled
+#[cfg(is_embedded)]         // This condition is expected, as 'is_embedded' was provided in --check-cfg
+fn do_embedded() {}         // and doesn't take any value
 
-#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in cfg()
-                                 // and because no value checking was enable for "has_feathers"
-                                 // no warning is emitted for the value "zapping"
-fn do_zapping() {}
+#[cfg(has_feathers)]        // This condition is expected, as 'has_feathers' was provided in --check-cfg
+fn do_features() {}         // and doesn't take any value
 
-#[cfg(has_mumble_frotz)]    // This is UNEXPECTED because names checking is enable and
-                            // "has_mumble_frotz" was not provided in cfg()
+#[cfg(has_mumble_frotz)]    // This condition is UNEXPECTED, as 'has_mumble_frotz' was NEVER provided
+                            // in any --check-cfg arguments
 fn do_mumble_frotz() {}
-```
-
-### Example: Checking feature values, but not condition names
 
-```bash
-# This turns on checking for feature values, but not for condition names.
-rustc --check-cfg 'cfg(feature, values("zapping", "lasers"))' \
-      --check-cfg 'cfg(any())' \
-      --cfg 'feature="zapping"' -Z unstable-options
-```
-
-```rust
-#[cfg(is_embedded)]         // This is doesn't raise a warning, because names checking was
-                            // disabled by 'cfg(any())'
-fn do_embedded() {}
-
-#[cfg(has_feathers)]        // Same as above, 'cfg(any())' was provided so no name
-                            // checking is performed
-fn do_features() {}
-
-#[cfg(feature = "lasers")]  // This is expected, "lasers" is in the cfg(feature) list
+#[cfg(feature = "lasers")]  // This condition is expected, as "lasers" is an expected value of `feature`
 fn shoot_lasers() {}
 
-#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the
-                            // cfg(feature) list
+#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT an expected value of
+                            // `feature`
 fn write_shakespeare() {}
 ```
 
-### Example: Checking both condition names and feature values
+### Example: Condition names without values
 
 ```bash
-# This turns on checking for feature values and for condition names.
-rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
-      --check-cfg 'cfg(feature, values("zapping", "lasers"))' \
-      --cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
+rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
+      --cfg has_feathers -Z unstable-options
 ```
 
 ```rust
-#[cfg(is_embedded)]         // This is expected because "is_embedded" was provided in cfg()
-fn do_embedded() {}         // and doesn't take any value
-
-#[cfg(has_feathers)]        // This is expected because "has_feathers" was provided in cfg()
-fn do_features() {}         // and deosn't take any value
+#[cfg(is_embedded)]      // This condition is expected, as 'is_embedded' was provided in --check-cfg
+                         // as condition name
+fn do_embedded() {}
 
-#[cfg(has_mumble_frotz)]    // This is UNEXPECTED, because "has_mumble_frotz" was never provided
-fn do_mumble_frotz() {}
+#[cfg(has_feathers)]     // This condition is expected, as "has_feathers" was provided in --check-cfg
+                         // as condition name
+fn do_features() {}
 
-#[cfg(feature = "lasers")]  // This is expected, "lasers" is in the cfg(feature) list
-fn shoot_lasers() {}
+#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers" was provided in
+                                 // and because *any* values is expected for 'has_feathers' no
+                                 // warning is emitted for the value "zapping"
+fn do_zapping() {}
 
-#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in
-                            // the cfg(feature) list
-fn write_shakespeare() {}
+#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was not provided
+                         // in any --check-cfg arguments
+fn do_mumble_frotz() {}
 ```
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index a5e2bc1c7af..7995a33f09f 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -2717,10 +2717,34 @@ ${item.displayPath}<span class="${type}">${name}</span>\
      * @return {Array<FunctionSearchType>}
      */
     function buildItemSearchTypeAll(types, lowercasePaths) {
-        return types.map(type => buildItemSearchType(type, lowercasePaths));
+        return types.length > 0 ?
+            types.map(type => buildItemSearchType(type, lowercasePaths)) :
+            EMPTY_GENERICS_ARRAY;
     }
 
     /**
+     * Empty, immutable map used in item search types with no bindings.
+     *
+     * @type {Map<number, Array<FunctionType>>}
+     */
+    const EMPTY_BINDINGS_MAP = new Map();
+
+    /**
+     * Empty, immutable map used in item search types with no bindings.
+     *
+     * @type {Array<FunctionType>}
+     */
+    const EMPTY_GENERICS_ARRAY = [];
+
+    /**
+     * Object pool for function types with no bindings or generics.
+     * This is reset after loading the index.
+     *
+     * @type {Map<number|null, FunctionType>}
+     */
+    let TYPES_POOL = new Map();
+
+    /**
      * Converts a single type.
      *
      * @param {RawFunctionType} type
@@ -2732,15 +2756,15 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         let pathIndex, generics, bindings;
         if (typeof type === "number") {
             pathIndex = type;
-            generics = [];
-            bindings = new Map();
+            generics = EMPTY_GENERICS_ARRAY;
+            bindings = EMPTY_BINDINGS_MAP;
         } else {
             pathIndex = type[PATH_INDEX_DATA];
             generics = buildItemSearchTypeAll(
                 type[GENERICS_DATA],
                 lowercasePaths
             );
-            if (type.length > BINDINGS_DATA) {
+            if (type.length > BINDINGS_DATA && type[BINDINGS_DATA].length > 0) {
                 bindings = new Map(type[BINDINGS_DATA].map(binding => {
                     const [assocType, constraints] = binding;
                     // Associated type constructors are represented sloppily in rustdoc's
@@ -2759,38 +2783,83 @@ ${item.displayPath}<span class="${type}">${name}</span>\
                     ];
                 }));
             } else {
-                bindings = new Map();
+                bindings = EMPTY_BINDINGS_MAP;
             }
         }
+        /**
+         * @type {FunctionType}
+         */
+        let result;
         if (pathIndex < 0) {
             // types less than 0 are generic parameters
             // the actual names of generic parameters aren't stored, since they aren't API
-            return {
+            result = {
                 id: pathIndex,
                 ty: TY_GENERIC,
                 path: null,
                 generics,
                 bindings,
             };
-        }
-        if (pathIndex === 0) {
+        } else if (pathIndex === 0) {
             // `0` is used as a sentinel because it's fewer bytes than `null`
-            return {
+            result = {
                 id: null,
                 ty: null,
                 path: null,
                 generics,
                 bindings,
             };
+        } else {
+            const item = lowercasePaths[pathIndex - 1];
+            result = {
+                id: buildTypeMapIndex(item.name, isAssocType),
+                ty: item.ty,
+                path: item.path,
+                generics,
+                bindings,
+            };
         }
-        const item = lowercasePaths[pathIndex - 1];
-        return {
-            id: buildTypeMapIndex(item.name, isAssocType),
-            ty: item.ty,
-            path: item.path,
-            generics,
-            bindings,
-        };
+        const cr = TYPES_POOL.get(result.id);
+        if (cr) {
+            // Shallow equality check. Since this function is used
+            // to construct every type object, this should be mostly
+            // equivalent to a deep equality check, except if there's
+            // a conflict, we don't keep the old one around, so it's
+            // not a fully precise implementation of hashcons.
+            if (cr.generics.length === result.generics.length &&
+                cr.generics !== result.generics &&
+                cr.generics.every((x, i) => result.generics[i] === x)
+            ) {
+                result.generics = cr.generics;
+            }
+            if (cr.bindings.size === result.bindings.size && cr.bindings !== result.bindings) {
+                let ok = true;
+                for (const [k, v] of cr.bindings.entries()) {
+                    const v2 = result.bindings.get(v);
+                    if (!v2) {
+                        ok = false;
+                        break;
+                    }
+                    if (v !== v2 && v.length === v2.length && v.every((x, i) => v2[i] === x)) {
+                        result.bindings.set(k, v);
+                    } else if (v !== v2) {
+                        ok = false;
+                        break;
+                    }
+                }
+                if (ok) {
+                    result.bindings = cr.bindings;
+                }
+            }
+            if (cr.ty === result.ty && cr.path === result.path
+                && cr.bindings === result.bindings && cr.generics === result.generics
+                && cr.ty === result.ty
+            ) {
+                return cr;
+            }
+        }
+        TYPES_POOL.set(result.id, result);
+        return result;
     }
 
     /**
@@ -2801,7 +2870,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
      * object-based encoding so that the actual search code is more readable and easier to debug.
      *
      * The raw function search type format is generated using serde in
-     * librustdoc/html/render/mod.rs: impl Serialize for IndexItemFunctionType
+     * librustdoc/html/render/mod.rs: IndexItemFunctionType::write_to_string
      *
      * @param {{
      *  string: string,
@@ -2970,8 +3039,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         const fb = {
             id: null,
             ty: 0,
-            generics: [],
-            bindings: new Map(),
+            generics: EMPTY_GENERICS_ARRAY,
+            bindings: EMPTY_BINDINGS_MAP,
         };
         for (const [k, v] of type.bindings.entries()) {
             fb.id = k;
@@ -3199,6 +3268,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
             }
             currentIndex += itemTypes.length;
         }
+        // Drop the (rather large) hash table used for reusing function items
+        TYPES_POOL = new Map();
     }
 
     /**
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index 5be8ef7996b..c5cd30ccc34 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -15,6 +15,7 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
     ("future-incompatible", "Lints that detect code that has future-compatibility problems"),
     ("rust-2018-compatibility", "Lints used to transition code from the 2015 edition to 2018"),
     ("rust-2021-compatibility", "Lints used to transition code from the 2018 edition to 2021"),
+    ("rust-2024-compatibility", "Lints used to transition code from the 2021 edition to 2024"),
 ];
 
 type LintGroups = BTreeMap<String, BTreeSet<String>>;
diff --git a/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs b/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs
index d5e6d37226a..762a8d85314 100644
--- a/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs
+++ b/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs
@@ -1,6 +1,8 @@
 //! Ensure that thread-local statics get deallocated when the thread dies.
 
 #![feature(thread_local)]
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#![allow(static_mut_ref)]
 
 #[thread_local]
 static mut TLS: u8 = 0;
diff --git a/src/tools/miri/tests/pass/static_mut.rs b/src/tools/miri/tests/pass/static_mut.rs
index 218b02525bd..c1e58b70adb 100644
--- a/src/tools/miri/tests/pass/static_mut.rs
+++ b/src/tools/miri/tests/pass/static_mut.rs
@@ -1,4 +1,7 @@
 static mut FOO: i32 = 42;
+
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#[allow(static_mut_ref)]
 static BAR: Foo = Foo(unsafe { &FOO as *const _ });
 
 #[allow(dead_code)]
diff --git a/src/tools/miri/tests/pass/tls/tls_static.rs b/src/tools/miri/tests/pass/tls/tls_static.rs
index fc4c8a283dd..9be00af47aa 100644
--- a/src/tools/miri/tests/pass/tls/tls_static.rs
+++ b/src/tools/miri/tests/pass/tls/tls_static.rs
@@ -8,6 +8,8 @@
 //! test, we also check that thread-locals act as per-thread statics.
 
 #![feature(thread_local)]
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#![allow(static_mut_ref)]
 
 use std::thread;