Auto merge of #75573 - Aaron1011:feature/const-mutation-lint, r=oli-obk
Add CONST_ITEM_MUTATION lint Fixes #74053 Fixes #55721 This PR adds a new lint `CONST_ITEM_MUTATION`. Given an item `const FOO: SomeType = ..`, this lint fires on: * Attempting to write directly to a field (`FOO.field = some_val`) or array entry (`FOO.array_field[0] = val`) * Taking a mutable reference to the `const` item (`&mut FOO`), including through an autoderef `FOO.some_mut_self_method()` The lint message explains that since each use of a constant creates a new temporary, the original `const` item will not be modified.
This commit is contained in:
commit
88197214b8
22 changed files with 427 additions and 116 deletions
|
@ -922,6 +922,8 @@ pub enum LocalInfo<'tcx> {
|
||||||
User(ClearCrossCrate<BindingForm<'tcx>>),
|
User(ClearCrossCrate<BindingForm<'tcx>>),
|
||||||
/// A temporary created that references the static with the given `DefId`.
|
/// A temporary created that references the static with the given `DefId`.
|
||||||
StaticRef { def_id: DefId, is_thread_local: bool },
|
StaticRef { def_id: DefId, is_thread_local: bool },
|
||||||
|
/// A temporary created that references the const with the given `DefId`
|
||||||
|
ConstRef { def_id: DefId },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> LocalDecl<'tcx> {
|
impl<'tcx> LocalDecl<'tcx> {
|
||||||
|
|
|
@ -804,68 +804,51 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
debug!("move_spans: target_temp = {:?}", target_temp);
|
debug!("move_spans: target_temp = {:?}", target_temp);
|
||||||
|
|
||||||
if let Some(Terminator {
|
if let Some(Terminator {
|
||||||
kind: TerminatorKind::Call { func, args, fn_span, from_hir_call, .. },
|
kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
|
||||||
..
|
|
||||||
}) = &self.body[location.block].terminator
|
}) = &self.body[location.block].terminator
|
||||||
{
|
{
|
||||||
let mut method_did = None;
|
let method_did = if let Some(method_did) =
|
||||||
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
|
crate::util::find_self_call(self.infcx.tcx, &self.body, target_temp, location.block)
|
||||||
if let ty::FnDef(def_id, _) = *ty.kind() {
|
{
|
||||||
debug!("move_spans: fn = {:?}", def_id);
|
method_did
|
||||||
if let Some(ty::AssocItem { fn_has_self_parameter, .. }) =
|
} else {
|
||||||
self.infcx.tcx.opt_associated_item(def_id)
|
return normal_ret;
|
||||||
{
|
};
|
||||||
if *fn_has_self_parameter {
|
|
||||||
method_did = Some(def_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
let method_did = if let Some(did) = method_did { did } else { return normal_ret };
|
|
||||||
|
|
||||||
if let [Operand::Move(self_place), ..] = **args {
|
let parent = tcx.parent(method_did);
|
||||||
if self_place.as_local() == Some(target_temp) {
|
let is_fn_once = parent == tcx.lang_items().fn_once_trait();
|
||||||
let parent = tcx.parent(method_did);
|
let is_operator = !from_hir_call
|
||||||
let is_fn_once = parent == tcx.lang_items().fn_once_trait();
|
&& parent.map_or(false, |p| tcx.lang_items().group(LangItemGroup::Op).contains(&p));
|
||||||
let is_operator = !from_hir_call
|
let fn_call_span = *fn_span;
|
||||||
&& parent.map_or(false, |p| {
|
|
||||||
tcx.lang_items().group(LangItemGroup::Op).contains(&p)
|
|
||||||
});
|
|
||||||
let fn_call_span = *fn_span;
|
|
||||||
|
|
||||||
let self_arg = tcx.fn_arg_names(method_did)[0];
|
let self_arg = tcx.fn_arg_names(method_did)[0];
|
||||||
|
|
||||||
let kind = if is_fn_once {
|
let kind = if is_fn_once {
|
||||||
FnSelfUseKind::FnOnceCall
|
FnSelfUseKind::FnOnceCall
|
||||||
} else if is_operator {
|
} else if is_operator {
|
||||||
FnSelfUseKind::Operator { self_arg }
|
FnSelfUseKind::Operator { self_arg }
|
||||||
} else {
|
} else {
|
||||||
debug!(
|
debug!("move_spans: method_did={:?}, fn_call_span={:?}", method_did, fn_call_span);
|
||||||
"move_spans: method_did={:?}, fn_call_span={:?}",
|
let implicit_into_iter = matches!(
|
||||||
method_did, fn_call_span
|
fn_call_span.desugaring_kind(),
|
||||||
);
|
Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
|
||||||
let implicit_into_iter = matches!(
|
);
|
||||||
fn_call_span.desugaring_kind(),
|
FnSelfUseKind::Normal { self_arg, implicit_into_iter }
|
||||||
Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
|
};
|
||||||
);
|
|
||||||
FnSelfUseKind::Normal { self_arg, implicit_into_iter }
|
|
||||||
};
|
|
||||||
|
|
||||||
return FnSelfUse {
|
return FnSelfUse {
|
||||||
var_span: stmt.source_info.span,
|
var_span: stmt.source_info.span,
|
||||||
fn_call_span,
|
fn_call_span,
|
||||||
fn_span: self
|
fn_span: self
|
||||||
.infcx
|
.infcx
|
||||||
.tcx
|
.tcx
|
||||||
.sess
|
.sess
|
||||||
.source_map()
|
.source_map()
|
||||||
.guess_head_span(self.infcx.tcx.def_span(method_did)),
|
.guess_head_span(self.infcx.tcx.def_span(method_did)),
|
||||||
kind,
|
kind,
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
normal_ret
|
normal_ret
|
||||||
}
|
}
|
||||||
|
|
114
compiler/rustc_mir/src/transform/check_const_item_mutation.rs
Normal file
114
compiler/rustc_mir/src/transform/check_const_item_mutation.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
use rustc_errors::DiagnosticBuilder;
|
||||||
|
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||||
|
use rustc_middle::mir::visit::Visitor;
|
||||||
|
use rustc_middle::mir::*;
|
||||||
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
use rustc_session::lint::builtin::CONST_ITEM_MUTATION;
|
||||||
|
use rustc_span::def_id::DefId;
|
||||||
|
|
||||||
|
use crate::transform::{MirPass, MirSource};
|
||||||
|
|
||||||
|
pub struct CheckConstItemMutation;
|
||||||
|
|
||||||
|
impl<'tcx> MirPass<'tcx> for CheckConstItemMutation {
|
||||||
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
||||||
|
let mut checker = ConstMutationChecker { body, tcx, target_local: None };
|
||||||
|
checker.visit_body(&body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConstMutationChecker<'a, 'tcx> {
|
||||||
|
body: &'a Body<'tcx>,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
target_local: Option<Local>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> {
|
||||||
|
fn is_const_item(&self, local: Local) -> Option<DefId> {
|
||||||
|
if let Some(box LocalInfo::ConstRef { def_id }) = self.body.local_decls[local].local_info {
|
||||||
|
Some(def_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn lint_const_item_usage(
|
||||||
|
&self,
|
||||||
|
const_item: DefId,
|
||||||
|
location: Location,
|
||||||
|
decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b>) -> DiagnosticBuilder<'b>,
|
||||||
|
) {
|
||||||
|
let source_info = self.body.source_info(location);
|
||||||
|
let lint_root = self.body.source_scopes[source_info.scope]
|
||||||
|
.local_data
|
||||||
|
.as_ref()
|
||||||
|
.assert_crate_local()
|
||||||
|
.lint_root;
|
||||||
|
|
||||||
|
self.tcx.struct_span_lint_hir(CONST_ITEM_MUTATION, lint_root, source_info.span, |lint| {
|
||||||
|
decorate(lint)
|
||||||
|
.span_note(self.tcx.def_span(const_item), "`const` item defined here")
|
||||||
|
.emit()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Visitor<'tcx> for ConstMutationChecker<'a, 'tcx> {
|
||||||
|
fn visit_statement(&mut self, stmt: &Statement<'tcx>, loc: Location) {
|
||||||
|
if let StatementKind::Assign(box (lhs, _)) = &stmt.kind {
|
||||||
|
// Check for assignment to fields of a constant
|
||||||
|
// Assigning directly to a constant (e.g. `FOO = true;`) is a hard error,
|
||||||
|
// so emitting a lint would be redundant.
|
||||||
|
if !lhs.projection.is_empty() {
|
||||||
|
if let Some(def_id) = self.is_const_item(lhs.local) {
|
||||||
|
self.lint_const_item_usage(def_id, loc, |lint| {
|
||||||
|
let mut lint = lint.build("attempting to modify a `const` item");
|
||||||
|
lint.note("each usage of a `const` item creates a new temporary - the original `const` item will not be modified");
|
||||||
|
lint
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We are looking for MIR of the form:
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// _1 = const FOO;
|
||||||
|
// _2 = &mut _1;
|
||||||
|
// method_call(_2, ..)
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Record our current LHS, so that we can detect this
|
||||||
|
// pattern in `visit_rvalue`
|
||||||
|
self.target_local = lhs.as_local();
|
||||||
|
}
|
||||||
|
self.super_statement(stmt, loc);
|
||||||
|
self.target_local = None;
|
||||||
|
}
|
||||||
|
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, loc: Location) {
|
||||||
|
if let Rvalue::Ref(_, BorrowKind::Mut { .. }, place) = rvalue {
|
||||||
|
let local = place.local;
|
||||||
|
if let Some(def_id) = self.is_const_item(local) {
|
||||||
|
// If this Rvalue is being used as the right-hand side of a
|
||||||
|
// `StatementKind::Assign`, see if it ends up getting used as
|
||||||
|
// the `self` parameter of a method call (as the terminator of our current
|
||||||
|
// BasicBlock). If so, we emit a more specific lint.
|
||||||
|
let method_did = self.target_local.and_then(|target_local| {
|
||||||
|
crate::util::find_self_call(self.tcx, &self.body, target_local, loc.block)
|
||||||
|
});
|
||||||
|
let lint_loc =
|
||||||
|
if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc };
|
||||||
|
self.lint_const_item_usage(def_id, lint_loc, |lint| {
|
||||||
|
let mut lint = lint.build("taking a mutable reference to a `const` item");
|
||||||
|
lint
|
||||||
|
.note("each usage of a `const` item creates a new temporary")
|
||||||
|
.note("the mutable reference will refer to this temporary, not the original `const` item");
|
||||||
|
|
||||||
|
if let Some(method_did) = method_did {
|
||||||
|
lint.span_note(self.tcx.def_span(method_did), "mutable reference created due to call to this method");
|
||||||
|
}
|
||||||
|
|
||||||
|
lint
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.super_rvalue(rvalue, loc);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ use std::borrow::Cow;
|
||||||
pub mod add_call_guards;
|
pub mod add_call_guards;
|
||||||
pub mod add_moves_for_packed_drops;
|
pub mod add_moves_for_packed_drops;
|
||||||
pub mod add_retag;
|
pub mod add_retag;
|
||||||
|
pub mod check_const_item_mutation;
|
||||||
pub mod check_consts;
|
pub mod check_consts;
|
||||||
pub mod check_packed_ref;
|
pub mod check_packed_ref;
|
||||||
pub mod check_unsafety;
|
pub mod check_unsafety;
|
||||||
|
@ -307,6 +308,7 @@ fn mir_const<'tcx>(
|
||||||
&[&[
|
&[&[
|
||||||
// MIR-level lints.
|
// MIR-level lints.
|
||||||
&check_packed_ref::CheckPackedRef,
|
&check_packed_ref::CheckPackedRef,
|
||||||
|
&check_const_item_mutation::CheckConstItemMutation,
|
||||||
// What we need to do constant evaluation.
|
// What we need to do constant evaluation.
|
||||||
&simplify::SimplifyCfg::new("initial"),
|
&simplify::SimplifyCfg::new("initial"),
|
||||||
&rustc_peek::SanityCheck,
|
&rustc_peek::SanityCheck,
|
||||||
|
|
35
compiler/rustc_mir/src/util/find_self_call.rs
Normal file
35
compiler/rustc_mir/src/util/find_self_call.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
use rustc_middle::mir::*;
|
||||||
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
|
use rustc_span::def_id::DefId;
|
||||||
|
|
||||||
|
/// Checks if the specified `local` is used as the `self` prameter of a method call
|
||||||
|
/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
|
||||||
|
/// returned.
|
||||||
|
pub fn find_self_call(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
body: &Body<'_>,
|
||||||
|
local: Local,
|
||||||
|
block: BasicBlock,
|
||||||
|
) -> Option<DefId> {
|
||||||
|
debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator);
|
||||||
|
if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
|
||||||
|
&body[block].terminator
|
||||||
|
{
|
||||||
|
debug!("find_self_call: func={:?}", func);
|
||||||
|
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
|
||||||
|
if let ty::FnDef(def_id, _) = *ty.kind() {
|
||||||
|
if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
|
||||||
|
tcx.opt_associated_item(def_id)
|
||||||
|
{
|
||||||
|
debug!("find_self_call: args={:?}", args);
|
||||||
|
if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args {
|
||||||
|
if self_place.as_local() == Some(local) {
|
||||||
|
return Some(def_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
|
@ -7,12 +7,14 @@ pub mod storage;
|
||||||
|
|
||||||
mod alignment;
|
mod alignment;
|
||||||
pub mod collect_writes;
|
pub mod collect_writes;
|
||||||
|
mod find_self_call;
|
||||||
mod graphviz;
|
mod graphviz;
|
||||||
pub(crate) mod pretty;
|
pub(crate) mod pretty;
|
||||||
pub(crate) mod spanview;
|
pub(crate) mod spanview;
|
||||||
|
|
||||||
pub use self::aggregate::expand_aggregate;
|
pub use self::aggregate::expand_aggregate;
|
||||||
pub use self::alignment::is_disaligned;
|
pub use self::alignment::is_disaligned;
|
||||||
|
pub use self::find_self_call::find_self_call;
|
||||||
pub use self::graphviz::write_node_label as write_graphviz_node_label;
|
pub use self::graphviz::write_node_label as write_graphviz_node_label;
|
||||||
pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz};
|
pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz};
|
||||||
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
|
pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
|
||||||
|
|
|
@ -21,7 +21,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let Expr { ty, temp_lifetime: _, span, kind } = expr;
|
let Expr { ty, temp_lifetime: _, span, kind } = expr;
|
||||||
match kind {
|
match kind {
|
||||||
ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
|
ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
|
||||||
ExprKind::Literal { literal, user_ty } => {
|
ExprKind::Literal { literal, user_ty, const_id: _ } => {
|
||||||
let user_ty = user_ty.map(|user_ty| {
|
let user_ty = user_ty.map(|user_ty| {
|
||||||
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -76,6 +76,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
local_decl.local_info =
|
local_decl.local_info =
|
||||||
Some(box LocalInfo::StaticRef { def_id, is_thread_local: true });
|
Some(box LocalInfo::StaticRef { def_id, is_thread_local: true });
|
||||||
}
|
}
|
||||||
|
ExprKind::Literal { const_id: Some(def_id), .. } => {
|
||||||
|
local_decl.local_info = Some(box LocalInfo::ConstRef { def_id });
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
this.local_decls.push(local_decl)
|
this.local_decls.push(local_decl)
|
||||||
|
|
|
@ -247,6 +247,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
||||||
hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
|
hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
|
||||||
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false),
|
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false),
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
|
const_id: None,
|
||||||
},
|
},
|
||||||
|
|
||||||
hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
|
hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
|
||||||
|
@ -306,6 +307,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
||||||
ExprKind::Literal {
|
ExprKind::Literal {
|
||||||
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true),
|
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true),
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
|
const_id: None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ExprKind::Unary { op: UnOp::Neg, arg: arg.to_ref() }
|
ExprKind::Unary { op: UnOp::Neg, arg: arg.to_ref() }
|
||||||
|
@ -447,6 +449,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
||||||
kind: ExprKind::Literal {
|
kind: ExprKind::Literal {
|
||||||
literal: ty::Const::zero_sized(cx.tcx, ty),
|
literal: ty::Const::zero_sized(cx.tcx, ty),
|
||||||
user_ty,
|
user_ty,
|
||||||
|
const_id: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.to_ref(),
|
.to_ref(),
|
||||||
|
@ -473,6 +476,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
||||||
kind: ExprKind::Literal {
|
kind: ExprKind::Literal {
|
||||||
literal: ty::Const::zero_sized(cx.tcx, ty),
|
literal: ty::Const::zero_sized(cx.tcx, ty),
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
|
const_id: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.to_ref(),
|
.to_ref(),
|
||||||
|
@ -585,7 +589,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
kind: ExprKind::Literal { literal, user_ty: None },
|
kind: ExprKind::Literal { literal, user_ty: None, const_id: None },
|
||||||
}
|
}
|
||||||
.to_ref()
|
.to_ref()
|
||||||
};
|
};
|
||||||
|
@ -714,7 +718,11 @@ fn method_callee<'a, 'tcx>(
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty,
|
ty,
|
||||||
span,
|
span,
|
||||||
kind: ExprKind::Literal { literal: ty::Const::zero_sized(cx.tcx(), ty), user_ty },
|
kind: ExprKind::Literal {
|
||||||
|
literal: ty::Const::zero_sized(cx.tcx(), ty),
|
||||||
|
user_ty,
|
||||||
|
const_id: None,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,6 +785,7 @@ fn convert_path_expr<'a, 'tcx>(
|
||||||
ExprKind::Literal {
|
ExprKind::Literal {
|
||||||
literal: ty::Const::zero_sized(cx.tcx, cx.typeck_results().node_type(expr.hir_id)),
|
literal: ty::Const::zero_sized(cx.tcx, cx.typeck_results().node_type(expr.hir_id)),
|
||||||
user_ty,
|
user_ty,
|
||||||
|
const_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,6 +803,7 @@ fn convert_path_expr<'a, 'tcx>(
|
||||||
.tcx
|
.tcx
|
||||||
.mk_const(ty::Const { val, ty: cx.typeck_results().node_type(expr.hir_id) }),
|
.mk_const(ty::Const { val, ty: cx.typeck_results().node_type(expr.hir_id) }),
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
|
const_id: Some(def_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,6 +820,7 @@ fn convert_path_expr<'a, 'tcx>(
|
||||||
ty: cx.typeck_results().node_type(expr.hir_id),
|
ty: cx.typeck_results().node_type(expr.hir_id),
|
||||||
}),
|
}),
|
||||||
user_ty,
|
user_ty,
|
||||||
|
const_id: Some(def_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -273,6 +273,10 @@ crate enum ExprKind<'tcx> {
|
||||||
Literal {
|
Literal {
|
||||||
literal: &'tcx Const<'tcx>,
|
literal: &'tcx Const<'tcx>,
|
||||||
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
|
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
|
||||||
|
/// The `DefId` of the `const` item this literal
|
||||||
|
/// was produced from, if this is not a user-written
|
||||||
|
/// literal value.
|
||||||
|
const_id: Option<DefId>,
|
||||||
},
|
},
|
||||||
/// A literal containing the address of a `static`.
|
/// A literal containing the address of a `static`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -232,6 +232,12 @@ declare_lint! {
|
||||||
"detects unaligned references to fields of packed structs",
|
"detects unaligned references to fields of packed structs",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
pub CONST_ITEM_MUTATION,
|
||||||
|
Warn,
|
||||||
|
"detects attempts to mutate a `const` item",
|
||||||
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
pub SAFE_PACKED_BORROWS,
|
pub SAFE_PACKED_BORROWS,
|
||||||
Warn,
|
Warn,
|
||||||
|
@ -582,6 +588,7 @@ declare_lint_pass! {
|
||||||
CONST_ERR,
|
CONST_ERR,
|
||||||
RENAMED_AND_REMOVED_LINTS,
|
RENAMED_AND_REMOVED_LINTS,
|
||||||
UNALIGNED_REFERENCES,
|
UNALIGNED_REFERENCES,
|
||||||
|
CONST_ITEM_MUTATION,
|
||||||
SAFE_PACKED_BORROWS,
|
SAFE_PACKED_BORROWS,
|
||||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||||
LATE_BOUND_LIFETIME_ARGUMENTS,
|
LATE_BOUND_LIFETIME_ARGUMENTS,
|
||||||
|
|
|
@ -3,9 +3,11 @@ const C: i32 = 2;
|
||||||
static mut M: i32 = 3;
|
static mut M: i32 = 3;
|
||||||
|
|
||||||
const CR: &'static mut i32 = &mut C; //~ ERROR E0764
|
const CR: &'static mut i32 = &mut C; //~ ERROR E0764
|
||||||
|
//~| WARN taking a mutable
|
||||||
static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0764
|
static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0764
|
||||||
//~| ERROR E0019
|
//~| ERROR E0019
|
||||||
//~| ERROR cannot borrow
|
//~| ERROR cannot borrow
|
||||||
static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764
|
static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764
|
||||||
|
//~| WARN taking a mutable
|
||||||
static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0764
|
static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0764
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
warning: taking a mutable reference to a `const` item
|
||||||
|
--> $DIR/E0017.rs:5:30
|
||||||
|
|
|
||||||
|
LL | const CR: &'static mut i32 = &mut C;
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(const_item_mutation)]` on by default
|
||||||
|
= note: each usage of a `const` item creates a new temporary
|
||||||
|
= note: the mutable reference will refer to this temporary, not the original `const` item
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/E0017.rs:2:1
|
||||||
|
|
|
||||||
|
LL | const C: i32 = 2;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0764]: mutable references are not allowed in constants
|
error[E0764]: mutable references are not allowed in constants
|
||||||
--> $DIR/E0017.rs:5:30
|
--> $DIR/E0017.rs:5:30
|
||||||
|
|
|
|
||||||
|
@ -5,7 +20,7 @@ LL | const CR: &'static mut i32 = &mut C;
|
||||||
| ^^^^^^ `&mut` is only allowed in `const fn`
|
| ^^^^^^ `&mut` is only allowed in `const fn`
|
||||||
|
|
||||||
error[E0019]: static contains unimplemented expression type
|
error[E0019]: static contains unimplemented expression type
|
||||||
--> $DIR/E0017.rs:6:39
|
--> $DIR/E0017.rs:7:39
|
||||||
|
|
|
|
||||||
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -13,30 +28,44 @@ LL | static STATIC_REF: &'static mut i32 = &mut X;
|
||||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0764]: mutable references are not allowed in statics
|
error[E0764]: mutable references are not allowed in statics
|
||||||
--> $DIR/E0017.rs:6:39
|
--> $DIR/E0017.rs:7:39
|
||||||
|
|
|
|
||||||
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
||||||
| ^^^^^^ `&mut` is only allowed in `const fn`
|
| ^^^^^^ `&mut` is only allowed in `const fn`
|
||||||
|
|
||||||
error[E0596]: cannot borrow immutable static item `X` as mutable
|
error[E0596]: cannot borrow immutable static item `X` as mutable
|
||||||
--> $DIR/E0017.rs:6:39
|
--> $DIR/E0017.rs:7:39
|
||||||
|
|
|
|
||||||
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
||||||
| ^^^^^^ cannot borrow as mutable
|
| ^^^^^^ cannot borrow as mutable
|
||||||
|
|
||||||
|
warning: taking a mutable reference to a `const` item
|
||||||
|
--> $DIR/E0017.rs:10:38
|
||||||
|
|
|
||||||
|
LL | static CONST_REF: &'static mut i32 = &mut C;
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: each usage of a `const` item creates a new temporary
|
||||||
|
= note: the mutable reference will refer to this temporary, not the original `const` item
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/E0017.rs:2:1
|
||||||
|
|
|
||||||
|
LL | const C: i32 = 2;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0764]: mutable references are not allowed in statics
|
error[E0764]: mutable references are not allowed in statics
|
||||||
--> $DIR/E0017.rs:9:38
|
--> $DIR/E0017.rs:10:38
|
||||||
|
|
|
|
||||||
LL | static CONST_REF: &'static mut i32 = &mut C;
|
LL | static CONST_REF: &'static mut i32 = &mut C;
|
||||||
| ^^^^^^ `&mut` is only allowed in `const fn`
|
| ^^^^^^ `&mut` is only allowed in `const fn`
|
||||||
|
|
||||||
error[E0764]: mutable references are not allowed in statics
|
error[E0764]: mutable references are not allowed in statics
|
||||||
--> $DIR/E0017.rs:10:52
|
--> $DIR/E0017.rs:12:52
|
||||||
|
|
|
|
||||||
LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
|
LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
|
||||||
| ^^^^^^ `&mut` is only allowed in `const fn`
|
| ^^^^^^ `&mut` is only allowed in `const fn`
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 6 previous errors; 2 warnings emitted
|
||||||
|
|
||||||
Some errors have detailed explanations: E0019, E0596, E0764.
|
Some errors have detailed explanations: E0019, E0596, E0764.
|
||||||
For more information about an error, try `rustc --explain E0019`.
|
For more information about an error, try `rustc --explain E0019`.
|
||||||
|
|
|
@ -2,9 +2,11 @@ static X: i32 = 1;
|
||||||
const C: i32 = 2;
|
const C: i32 = 2;
|
||||||
|
|
||||||
const CR: &'static mut i32 = &mut C; //~ ERROR E0764
|
const CR: &'static mut i32 = &mut C; //~ ERROR E0764
|
||||||
|
//~| WARN taking a mutable
|
||||||
static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0019
|
static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0019
|
||||||
//~| ERROR cannot borrow
|
//~| ERROR cannot borrow
|
||||||
//~| ERROR E0764
|
//~| ERROR E0764
|
||||||
static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764
|
static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764
|
||||||
|
//~| WARN taking a mutable
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
warning: taking a mutable reference to a `const` item
|
||||||
|
--> $DIR/E0388.rs:4:30
|
||||||
|
|
|
||||||
|
LL | const CR: &'static mut i32 = &mut C;
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(const_item_mutation)]` on by default
|
||||||
|
= note: each usage of a `const` item creates a new temporary
|
||||||
|
= note: the mutable reference will refer to this temporary, not the original `const` item
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/E0388.rs:2:1
|
||||||
|
|
|
||||||
|
LL | const C: i32 = 2;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0764]: mutable references are not allowed in constants
|
error[E0764]: mutable references are not allowed in constants
|
||||||
--> $DIR/E0388.rs:4:30
|
--> $DIR/E0388.rs:4:30
|
||||||
|
|
|
|
||||||
|
@ -5,7 +20,7 @@ LL | const CR: &'static mut i32 = &mut C;
|
||||||
| ^^^^^^ `&mut` is only allowed in `const fn`
|
| ^^^^^^ `&mut` is only allowed in `const fn`
|
||||||
|
|
||||||
error[E0019]: static contains unimplemented expression type
|
error[E0019]: static contains unimplemented expression type
|
||||||
--> $DIR/E0388.rs:5:39
|
--> $DIR/E0388.rs:6:39
|
||||||
|
|
|
|
||||||
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -13,24 +28,38 @@ LL | static STATIC_REF: &'static mut i32 = &mut X;
|
||||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0764]: mutable references are not allowed in statics
|
error[E0764]: mutable references are not allowed in statics
|
||||||
--> $DIR/E0388.rs:5:39
|
--> $DIR/E0388.rs:6:39
|
||||||
|
|
|
|
||||||
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
||||||
| ^^^^^^ `&mut` is only allowed in `const fn`
|
| ^^^^^^ `&mut` is only allowed in `const fn`
|
||||||
|
|
||||||
error[E0596]: cannot borrow immutable static item `X` as mutable
|
error[E0596]: cannot borrow immutable static item `X` as mutable
|
||||||
--> $DIR/E0388.rs:5:39
|
--> $DIR/E0388.rs:6:39
|
||||||
|
|
|
|
||||||
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
|
||||||
| ^^^^^^ cannot borrow as mutable
|
| ^^^^^^ cannot borrow as mutable
|
||||||
|
|
||||||
|
warning: taking a mutable reference to a `const` item
|
||||||
|
--> $DIR/E0388.rs:9:38
|
||||||
|
|
|
||||||
|
LL | static CONST_REF: &'static mut i32 = &mut C;
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: each usage of a `const` item creates a new temporary
|
||||||
|
= note: the mutable reference will refer to this temporary, not the original `const` item
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/E0388.rs:2:1
|
||||||
|
|
|
||||||
|
LL | const C: i32 = 2;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0764]: mutable references are not allowed in statics
|
error[E0764]: mutable references are not allowed in statics
|
||||||
--> $DIR/E0388.rs:8:38
|
--> $DIR/E0388.rs:9:38
|
||||||
|
|
|
|
||||||
LL | static CONST_REF: &'static mut i32 = &mut C;
|
LL | static CONST_REF: &'static mut i32 = &mut C;
|
||||||
| ^^^^^^ `&mut` is only allowed in `const fn`
|
| ^^^^^^ `&mut` is only allowed in `const fn`
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors; 2 warnings emitted
|
||||||
|
|
||||||
Some errors have detailed explanations: E0019, E0596, E0764.
|
Some errors have detailed explanations: E0019, E0596, E0764.
|
||||||
For more information about an error, try `rustc --explain E0019`.
|
For more information about an error, try `rustc --explain E0019`.
|
||||||
|
|
21
src/test/ui/lint/lint-const-item-mutation.rs
Normal file
21
src/test/ui/lint/lint-const-item-mutation.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
struct MyStruct {
|
||||||
|
field: bool,
|
||||||
|
inner_array: [char; 1],
|
||||||
|
}
|
||||||
|
impl MyStruct {
|
||||||
|
fn use_mut(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ARRAY: [u8; 1] = [25];
|
||||||
|
const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'] };
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
ARRAY[0] = 5; //~ WARN attempting to modify
|
||||||
|
MY_STRUCT.field = false; //~ WARN attempting to modify
|
||||||
|
MY_STRUCT.inner_array[0] = 'b'; //~ WARN attempting to modify
|
||||||
|
MY_STRUCT.use_mut(); //~ WARN taking
|
||||||
|
&mut MY_STRUCT; //~ WARN taking
|
||||||
|
(&mut MY_STRUCT).use_mut(); //~ WARN taking
|
||||||
|
}
|
89
src/test/ui/lint/lint-const-item-mutation.stderr
Normal file
89
src/test/ui/lint/lint-const-item-mutation.stderr
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
warning: attempting to modify a `const` item
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:15:5
|
||||||
|
|
|
||||||
|
LL | ARRAY[0] = 5;
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(const_item_mutation)]` on by default
|
||||||
|
= note: each usage of a `const` item creates a new temporary - the original `const` item will not be modified
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:11:1
|
||||||
|
|
|
||||||
|
LL | const ARRAY: [u8; 1] = [25];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: attempting to modify a `const` item
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:16:5
|
||||||
|
|
|
||||||
|
LL | MY_STRUCT.field = false;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: each usage of a `const` item creates a new temporary - the original `const` item will not be modified
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:12:1
|
||||||
|
|
|
||||||
|
LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'] };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: attempting to modify a `const` item
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:17:5
|
||||||
|
|
|
||||||
|
LL | MY_STRUCT.inner_array[0] = 'b';
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: each usage of a `const` item creates a new temporary - the original `const` item will not be modified
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:12:1
|
||||||
|
|
|
||||||
|
LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'] };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: taking a mutable reference to a `const` item
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:18:5
|
||||||
|
|
|
||||||
|
LL | MY_STRUCT.use_mut();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: each usage of a `const` item creates a new temporary
|
||||||
|
= note: the mutable reference will refer to this temporary, not the original `const` item
|
||||||
|
note: mutable reference created due to call to this method
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:8:5
|
||||||
|
|
|
||||||
|
LL | fn use_mut(&mut self) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:12:1
|
||||||
|
|
|
||||||
|
LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'] };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: taking a mutable reference to a `const` item
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:19:5
|
||||||
|
|
|
||||||
|
LL | &mut MY_STRUCT;
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: each usage of a `const` item creates a new temporary
|
||||||
|
= note: the mutable reference will refer to this temporary, not the original `const` item
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:12:1
|
||||||
|
|
|
||||||
|
LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'] };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: taking a mutable reference to a `const` item
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:20:5
|
||||||
|
|
|
||||||
|
LL | (&mut MY_STRUCT).use_mut();
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: each usage of a `const` item creates a new temporary
|
||||||
|
= note: the mutable reference will refer to this temporary, not the original `const` item
|
||||||
|
note: `const` item defined here
|
||||||
|
--> $DIR/lint-const-item-mutation.rs:12:1
|
||||||
|
|
|
||||||
|
LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'] };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: 6 warnings emitted
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::utils::{is_adjusted, span_lint};
|
use crate::utils::{is_adjusted, span_lint};
|
||||||
use rustc_hir::def::{DefKind, Res};
|
|
||||||
use rustc_hir::{Expr, ExprKind};
|
use rustc_hir::{Expr, ExprKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
@ -22,10 +21,9 @@ declare_clippy_lint! {
|
||||||
"assignments to temporaries"
|
"assignments to temporaries"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_temporary(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
fn is_temporary(_cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
ExprKind::Struct(..) | ExprKind::Tup(..) => true,
|
ExprKind::Struct(..) | ExprKind::Tup(..) => true,
|
||||||
ExprKind::Path(qpath) => matches!(cx.qpath_res(qpath, expr.hir_id), Res::Def(DefKind::Const, ..)),
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#![warn(clippy::borrow_interior_mutable_const)]
|
#![warn(clippy::borrow_interior_mutable_const)]
|
||||||
#![allow(clippy::declare_interior_mutable_const, clippy::ref_in_deref)]
|
#![allow(clippy::declare_interior_mutable_const, clippy::ref_in_deref)]
|
||||||
|
#![allow(const_item_mutation)]
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::{Cell, UnsafeCell};
|
use std::cell::{Cell, UnsafeCell};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:65:5
|
--> $DIR/borrow_interior_mutable_const.rs:66:5
|
||||||
|
|
|
|
||||||
LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
|
LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -8,7 +8,7 @@ LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:66:16
|
--> $DIR/borrow_interior_mutable_const.rs:67:16
|
||||||
|
|
|
|
||||||
LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
|
LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -16,7 +16,7 @@ LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:69:22
|
--> $DIR/borrow_interior_mutable_const.rs:70:22
|
||||||
|
|
|
|
||||||
LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
|
LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -24,7 +24,7 @@ LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:70:25
|
--> $DIR/borrow_interior_mutable_const.rs:71:25
|
||||||
|
|
|
|
||||||
LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
|
LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -32,7 +32,7 @@ LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:71:27
|
--> $DIR/borrow_interior_mutable_const.rs:72:27
|
||||||
|
|
|
|
||||||
LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
|
LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -40,7 +40,7 @@ LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:72:26
|
--> $DIR/borrow_interior_mutable_const.rs:73:26
|
||||||
|
|
|
|
||||||
LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
|
LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -48,7 +48,7 @@ LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:83:14
|
--> $DIR/borrow_interior_mutable_const.rs:84:14
|
||||||
|
|
|
|
||||||
LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
|
LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -56,7 +56,7 @@ LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:84:14
|
--> $DIR/borrow_interior_mutable_const.rs:85:14
|
||||||
|
|
|
|
||||||
LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
|
LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -64,7 +64,7 @@ LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:85:19
|
--> $DIR/borrow_interior_mutable_const.rs:86:19
|
||||||
|
|
|
|
||||||
LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
|
LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -72,7 +72,7 @@ LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:86:14
|
--> $DIR/borrow_interior_mutable_const.rs:87:14
|
||||||
|
|
|
|
||||||
LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
|
LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -80,7 +80,7 @@ LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:87:13
|
--> $DIR/borrow_interior_mutable_const.rs:88:13
|
||||||
|
|
|
|
||||||
LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
|
LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -88,7 +88,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:93:13
|
--> $DIR/borrow_interior_mutable_const.rs:94:13
|
||||||
|
|
|
|
||||||
LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
|
LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -96,7 +96,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:98:5
|
--> $DIR/borrow_interior_mutable_const.rs:99:5
|
||||||
|
|
|
|
||||||
LL | CELL.set(2); //~ ERROR interior mutability
|
LL | CELL.set(2); //~ ERROR interior mutability
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
@ -104,7 +104,7 @@ LL | CELL.set(2); //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:99:16
|
--> $DIR/borrow_interior_mutable_const.rs:100:16
|
||||||
|
|
|
|
||||||
LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
|
LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
@ -112,7 +112,7 @@ LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:112:5
|
--> $DIR/borrow_interior_mutable_const.rs:113:5
|
||||||
|
|
|
|
||||||
LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
|
LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -120,7 +120,7 @@ LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
|
||||||
= help: assign this const to a local or static variable, and use the variable here
|
= help: assign this const to a local or static variable, and use the variable here
|
||||||
|
|
||||||
error: a `const` item with interior mutability should not be borrowed
|
error: a `const` item with interior mutability should not be borrowed
|
||||||
--> $DIR/borrow_interior_mutable_const.rs:113:16
|
--> $DIR/borrow_interior_mutable_const.rs:114:16
|
||||||
|
|
|
|
||||||
LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
|
LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![warn(clippy::temporary_assignment)]
|
#![warn(clippy::temporary_assignment)]
|
||||||
|
#![allow(const_item_mutation)]
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: assignment to temporary
|
error: assignment to temporary
|
||||||
--> $DIR/temporary_assignment.rs:47:5
|
--> $DIR/temporary_assignment.rs:48:5
|
||||||
|
|
|
|
||||||
LL | Struct { field: 0 }.field = 1;
|
LL | Struct { field: 0 }.field = 1;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -7,7 +7,7 @@ LL | Struct { field: 0 }.field = 1;
|
||||||
= note: `-D clippy::temporary-assignment` implied by `-D warnings`
|
= note: `-D clippy::temporary-assignment` implied by `-D warnings`
|
||||||
|
|
||||||
error: assignment to temporary
|
error: assignment to temporary
|
||||||
--> $DIR/temporary_assignment.rs:48:5
|
--> $DIR/temporary_assignment.rs:49:5
|
||||||
|
|
|
|
||||||
LL | / MultiStruct {
|
LL | / MultiStruct {
|
||||||
LL | | structure: Struct { field: 0 },
|
LL | | structure: Struct { field: 0 },
|
||||||
|
@ -17,40 +17,16 @@ LL | | .field = 1;
|
||||||
| |______________^
|
| |______________^
|
||||||
|
|
||||||
error: assignment to temporary
|
error: assignment to temporary
|
||||||
--> $DIR/temporary_assignment.rs:53:5
|
--> $DIR/temporary_assignment.rs:54:5
|
||||||
|
|
|
|
||||||
LL | ArrayStruct { array: [0] }.array[0] = 1;
|
LL | ArrayStruct { array: [0] }.array[0] = 1;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: assignment to temporary
|
error: assignment to temporary
|
||||||
--> $DIR/temporary_assignment.rs:54:5
|
--> $DIR/temporary_assignment.rs:55:5
|
||||||
|
|
|
|
||||||
LL | (0, 0).0 = 1;
|
LL | (0, 0).0 = 1;
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: assignment to temporary
|
error: aborting due to 4 previous errors
|
||||||
--> $DIR/temporary_assignment.rs:56:5
|
|
||||||
|
|
|
||||||
LL | A.0 = 2;
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
error: assignment to temporary
|
|
||||||
--> $DIR/temporary_assignment.rs:57:5
|
|
||||||
|
|
|
||||||
LL | B.field = 2;
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: assignment to temporary
|
|
||||||
--> $DIR/temporary_assignment.rs:58:5
|
|
||||||
|
|
|
||||||
LL | C.structure.field = 2;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: assignment to temporary
|
|
||||||
--> $DIR/temporary_assignment.rs:59:5
|
|
||||||
|
|
|
||||||
LL | D.array[0] = 2;
|
|
||||||
| ^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue