1
Fork 0

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:
bors 2020-09-10 05:54:26 +00:00
commit 88197214b8
22 changed files with 427 additions and 116 deletions

View file

@ -21,7 +21,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let Expr { ty, temp_lifetime: _, span, kind } = expr;
match kind {
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| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,

View file

@ -76,6 +76,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
local_decl.local_info =
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)

View file

@ -247,6 +247,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false),
user_ty: None,
const_id: None,
},
hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
@ -306,6 +307,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
ExprKind::Literal {
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true),
user_ty: None,
const_id: None,
}
} else {
ExprKind::Unary { op: UnOp::Neg, arg: arg.to_ref() }
@ -447,6 +449,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
kind: ExprKind::Literal {
literal: ty::Const::zero_sized(cx.tcx, ty),
user_ty,
const_id: None,
},
}
.to_ref(),
@ -473,6 +476,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
kind: ExprKind::Literal {
literal: ty::Const::zero_sized(cx.tcx, ty),
user_ty: None,
const_id: None,
},
}
.to_ref(),
@ -585,7 +589,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
temp_lifetime,
ty: var_ty,
span: expr.span,
kind: ExprKind::Literal { literal, user_ty: None },
kind: ExprKind::Literal { literal, user_ty: None, const_id: None },
}
.to_ref()
};
@ -714,7 +718,11 @@ fn method_callee<'a, 'tcx>(
temp_lifetime,
ty,
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 {
literal: ty::Const::zero_sized(cx.tcx, cx.typeck_results().node_type(expr.hir_id)),
user_ty,
const_id: None,
}
}
@ -794,6 +803,7 @@ fn convert_path_expr<'a, 'tcx>(
.tcx
.mk_const(ty::Const { val, ty: cx.typeck_results().node_type(expr.hir_id) }),
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),
}),
user_ty,
const_id: Some(def_id),
}
}

View file

@ -273,6 +273,10 @@ crate enum ExprKind<'tcx> {
Literal {
literal: &'tcx Const<'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`.
///