diff --git a/compiler/rustc_lint/src/interior_mutable_consts.rs b/compiler/rustc_lint/src/interior_mutable_consts.rs index 8576698dec33e..4c7d2c6af93b1 100644 --- a/compiler/rustc_lint/src/interior_mutable_consts.rs +++ b/compiler/rustc_lint/src/interior_mutable_consts.rs @@ -1,6 +1,7 @@ use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, ItemKind, Node, find_attr}; +use rustc_middle::ty::adjustment::Adjust; use rustc_session::{declare_lint, declare_lint_pass}; use crate::lints::{ConstItemInteriorMutationsDiag, ConstItemInteriorMutationsSuggestionStatic}; @@ -77,6 +78,13 @@ impl<'tcx> LateLintPass<'tcx> for InteriorMutableConsts { if let ExprKind::Path(qpath) = &receiver.kind && let Res::Def(DefKind::Const | DefKind::AssocConst, const_did) = typeck.qpath_res(qpath, receiver.hir_id) + // Don't consider derefs as those can do arbitrary things + // like using thread local (see rust-lang/rust#150157) + && !cx + .typeck_results() + .expr_adjustments(receiver) + .into_iter() + .any(|adj| matches!(adj.kind, Adjust::Deref(_))) // Let's do the attribute check after the other checks for perf reasons && find_attr!( cx.tcx.get_all_attrs(method_did), diff --git a/tests/ui/lint/const-item-interior-mutations-const-deref.rs b/tests/ui/lint/const-item-interior-mutations-const-deref.rs new file mode 100644 index 0000000000000..021e0952da704 --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const-deref.rs @@ -0,0 +1,28 @@ +// Regression test for +// +// We shouldn't lint on user types, including through deref. + +//@ check-pass + +use std::cell::Cell; +use std::ops::Deref; + +// Cut down version of the issue reproducer without the thread local to just a Deref +pub struct LocalKey { + inner: T, +} + +impl Deref for LocalKey { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +const LOCAL_COUNT: LocalKey> = LocalKey { inner: Cell::new(8) }; + +fn main() { + let count = LOCAL_COUNT.get(); + LOCAL_COUNT.set(count); +}