Skip to content

Commit caad063

Browse files
committed
Auto merge of #12713 - J-ZhengLi:issue8864, r=y21
make sure the msrv for `const_raw_ptr_deref` is met when linting [`missing_const_for_fn`] fixes: #8864 --- changelog: make sure the msrv for `const_ptr_deref` is met when linting [`missing_const_for_fn`]
2 parents e669d97 + 1b7fc5f commit caad063

File tree

5 files changed

+121
-36
lines changed

5 files changed

+121
-36
lines changed

clippy_config/src/msrvs.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ msrv_aliases! {
2626
1,63,0 { CLONE_INTO }
2727
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
2828
1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST }
29-
1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
29+
1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF }
30+
1,56,0 { CONST_FN_UNION }
3031
1,55,0 { SEEK_REWIND }
3132
1,54,0 { INTO_KEYS }
3233
1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }

clippy_utils/src/qualify_min_const_fn.rs

+45-33
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// of terminologies might not be relevant in the context of Clippy. Note that its behavior might
44
// differ from the time of `rustc` even if the name stays the same.
55

6-
use clippy_config::msrvs::Msrv;
6+
use clippy_config::msrvs::{self, Msrv};
77
use hir::LangItem;
88
use rustc_attr::StableSince;
99
use rustc_const_eval::transform::check_consts::ConstCx;
@@ -42,7 +42,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
4242
for bb in &*body.basic_blocks {
4343
check_terminator(tcx, body, bb.terminator(), msrv)?;
4444
for stmt in &bb.statements {
45-
check_statement(tcx, body, def_id, stmt)?;
45+
check_statement(tcx, body, def_id, stmt, msrv)?;
4646
}
4747
}
4848
Ok(())
@@ -102,13 +102,14 @@ fn check_rvalue<'tcx>(
102102
def_id: DefId,
103103
rvalue: &Rvalue<'tcx>,
104104
span: Span,
105+
msrv: &Msrv,
105106
) -> McfResult {
106107
match rvalue {
107108
Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())),
108109
Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
109-
check_place(tcx, *place, span, body)
110+
check_place(tcx, *place, span, body, msrv)
110111
},
111-
Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body),
112+
Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, msrv),
112113
Rvalue::Repeat(operand, _)
113114
| Rvalue::Use(operand)
114115
| Rvalue::Cast(
@@ -122,7 +123,7 @@ fn check_rvalue<'tcx>(
122123
| CastKind::PointerCoercion(PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer),
123124
operand,
124125
_,
125-
) => check_operand(tcx, operand, span, body),
126+
) => check_operand(tcx, operand, span, body, msrv),
126127
Rvalue::Cast(
127128
CastKind::PointerCoercion(
128129
PointerCoercion::UnsafeFnPointer
@@ -141,7 +142,7 @@ fn check_rvalue<'tcx>(
141142
};
142143
let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
143144
if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
144-
check_operand(tcx, op, span, body)?;
145+
check_operand(tcx, op, span, body, msrv)?;
145146
// Casting/coercing things to slices is fine.
146147
Ok(())
147148
} else {
@@ -162,8 +163,8 @@ fn check_rvalue<'tcx>(
162163
)),
163164
// binops are fine on integers
164165
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
165-
check_operand(tcx, lhs, span, body)?;
166-
check_operand(tcx, rhs, span, body)?;
166+
check_operand(tcx, lhs, span, body, msrv)?;
167+
check_operand(tcx, rhs, span, body, msrv)?;
167168
let ty = lhs.ty(body, tcx);
168169
if ty.is_integral() || ty.is_bool() || ty.is_char() {
169170
Ok(())
@@ -179,14 +180,14 @@ fn check_rvalue<'tcx>(
179180
Rvalue::UnaryOp(_, operand) => {
180181
let ty = operand.ty(body, tcx);
181182
if ty.is_integral() || ty.is_bool() {
182-
check_operand(tcx, operand, span, body)
183+
check_operand(tcx, operand, span, body, msrv)
183184
} else {
184185
Err((span, "only int and `bool` operations are stable in const fn".into()))
185186
}
186187
},
187188
Rvalue::Aggregate(_, operands) => {
188189
for operand in operands {
189-
check_operand(tcx, operand, span, body)?;
190+
check_operand(tcx, operand, span, body, msrv)?;
190191
}
191192
Ok(())
192193
},
@@ -198,28 +199,29 @@ fn check_statement<'tcx>(
198199
body: &Body<'tcx>,
199200
def_id: DefId,
200201
statement: &Statement<'tcx>,
202+
msrv: &Msrv,
201203
) -> McfResult {
202204
let span = statement.source_info.span;
203205
match &statement.kind {
204206
StatementKind::Assign(box (place, rval)) => {
205-
check_place(tcx, *place, span, body)?;
206-
check_rvalue(tcx, body, def_id, rval, span)
207+
check_place(tcx, *place, span, body, msrv)?;
208+
check_rvalue(tcx, body, def_id, rval, span, msrv)
207209
},
208210

209-
StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body),
211+
StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body, msrv),
210212
// just an assignment
211213
StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => {
212-
check_place(tcx, **place, span, body)
214+
check_place(tcx, **place, span, body, msrv)
213215
},
214216

215-
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body),
217+
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body, msrv),
216218

217219
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
218220
rustc_middle::mir::CopyNonOverlapping { dst, src, count },
219221
)) => {
220-
check_operand(tcx, dst, span, body)?;
221-
check_operand(tcx, src, span, body)?;
222-
check_operand(tcx, count, span, body)
222+
check_operand(tcx, dst, span, body, msrv)?;
223+
check_operand(tcx, src, span, body, msrv)?;
224+
check_operand(tcx, count, span, body, msrv)
223225
},
224226
// These are all NOPs
225227
StatementKind::StorageLive(_)
@@ -233,7 +235,13 @@ fn check_statement<'tcx>(
233235
}
234236
}
235237

236-
fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
238+
fn check_operand<'tcx>(
239+
tcx: TyCtxt<'tcx>,
240+
operand: &Operand<'tcx>,
241+
span: Span,
242+
body: &Body<'tcx>,
243+
msrv: &Msrv,
244+
) -> McfResult {
237245
match operand {
238246
Operand::Move(place) => {
239247
if !place.projection.as_ref().is_empty()
@@ -245,33 +253,37 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b
245253
));
246254
}
247255

248-
check_place(tcx, *place, span, body)
256+
check_place(tcx, *place, span, body, msrv)
249257
},
250-
Operand::Copy(place) => check_place(tcx, *place, span, body),
258+
Operand::Copy(place) => check_place(tcx, *place, span, body, msrv),
251259
Operand::Constant(c) => match c.check_static_ptr(tcx) {
252260
Some(_) => Err((span, "cannot access `static` items in const fn".into())),
253261
None => Ok(()),
254262
},
255263
}
256264
}
257265

258-
fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
266+
fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>, msrv: &Msrv) -> McfResult {
259267
for (base, elem) in place.as_ref().iter_projections() {
260268
match elem {
261269
ProjectionElem::Field(..) => {
262-
let base_ty = base.ty(body, tcx).ty;
263-
if let Some(def) = base_ty.ty_adt_def() {
264-
// No union field accesses in `const fn`
265-
if def.is_union() {
266-
return Err((span, "accessing union fields is unstable".into()));
267-
}
270+
if base.ty(body, tcx).ty.is_union() && !msrv.meets(msrvs::CONST_FN_UNION) {
271+
return Err((span, "accessing union fields is unstable".into()));
268272
}
269273
},
274+
ProjectionElem::Deref => match base.ty(body, tcx).ty.kind() {
275+
ty::RawPtr(_, hir::Mutability::Mut) => {
276+
return Err((span, "dereferencing raw mut pointer in const fn is unstable".into()));
277+
},
278+
ty::RawPtr(_, hir::Mutability::Not) if !msrv.meets(msrvs::CONST_RAW_PTR_DEREF) => {
279+
return Err((span, "dereferencing raw const pointer in const fn is unstable".into()));
280+
},
281+
_ => (),
282+
},
270283
ProjectionElem::ConstantIndex { .. }
271284
| ProjectionElem::OpaqueCast(..)
272285
| ProjectionElem::Downcast(..)
273286
| ProjectionElem::Subslice { .. }
274-
| ProjectionElem::Deref
275287
| ProjectionElem::Subtype(_)
276288
| ProjectionElem::Index(_) => {},
277289
}
@@ -304,7 +316,7 @@ fn check_terminator<'tcx>(
304316
}
305317
Ok(())
306318
},
307-
TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
319+
TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body, msrv),
308320
TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => {
309321
Err((span, "const fn coroutines are unstable".into()))
310322
},
@@ -341,10 +353,10 @@ fn check_terminator<'tcx>(
341353
));
342354
}
343355

344-
check_operand(tcx, func, span, body)?;
356+
check_operand(tcx, func, span, body, msrv)?;
345357

346358
for arg in args {
347-
check_operand(tcx, &arg.node, span, body)?;
359+
check_operand(tcx, &arg.node, span, body, msrv)?;
348360
}
349361
Ok(())
350362
} else {
@@ -357,7 +369,7 @@ fn check_terminator<'tcx>(
357369
msg: _,
358370
target: _,
359371
unwind: _,
360-
} => check_operand(tcx, cond, span, body),
372+
} => check_operand(tcx, cond, span, body, msrv),
361373
TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
362374
}
363375
}

tests/ui/missing_const_for_fn/cant_be_const.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,23 @@ union U {
161161
f: u32,
162162
}
163163

164-
// Do not lint because accessing union fields from const functions is unstable
164+
// Do not lint because accessing union fields from const functions is unstable in 1.55
165+
#[clippy::msrv = "1.55"]
165166
fn h(u: U) -> u32 {
166167
unsafe { u.f }
167168
}
169+
170+
mod msrv {
171+
struct Foo(*const u8, *mut u8);
172+
173+
impl Foo {
174+
#[clippy::msrv = "1.57"]
175+
fn deref_ptr_cannot_be_const(self) -> usize {
176+
unsafe { *self.0 as usize }
177+
}
178+
#[clippy::msrv = "1.58"]
179+
fn deref_mut_ptr_cannot_be_const(self) -> usize {
180+
unsafe { *self.1 as usize }
181+
}
182+
}
183+
}

tests/ui/missing_const_for_fn/could_be_const.rs

+28
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,31 @@ impl const Drop for D {
113113
// Lint this, since it can be dropped in const contexts
114114
// FIXME(effects)
115115
fn d(this: D) {}
116+
117+
mod msrv {
118+
struct Foo(*const u8, &'static u8);
119+
120+
impl Foo {
121+
#[clippy::msrv = "1.58"]
122+
fn deref_ptr_can_be_const(self) -> usize {
123+
//~^ ERROR: this could be a `const fn`
124+
unsafe { *self.0 as usize }
125+
}
126+
127+
fn deref_copied_val(self) -> usize {
128+
//~^ ERROR: this could be a `const fn`
129+
*self.1 as usize
130+
}
131+
}
132+
133+
union Bar {
134+
val: u8,
135+
}
136+
137+
#[clippy::msrv = "1.56"]
138+
fn union_access_can_be_const() {
139+
//~^ ERROR: this could be a `const fn`
140+
let bar = Bar { val: 1 };
141+
let _ = unsafe { bar.val };
142+
}
143+
}

tests/ui/missing_const_for_fn/could_be_const.stderr

+29-1
Original file line numberDiff line numberDiff line change
@@ -102,5 +102,33 @@ LL | | 46
102102
LL | | }
103103
| |_^
104104

105-
error: aborting due to 11 previous errors
105+
error: this could be a `const fn`
106+
--> tests/ui/missing_const_for_fn/could_be_const.rs:122:9
107+
|
108+
LL | / fn deref_ptr_can_be_const(self) -> usize {
109+
LL | |
110+
LL | | unsafe { *self.0 as usize }
111+
LL | | }
112+
| |_________^
113+
114+
error: this could be a `const fn`
115+
--> tests/ui/missing_const_for_fn/could_be_const.rs:127:9
116+
|
117+
LL | / fn deref_copied_val(self) -> usize {
118+
LL | |
119+
LL | | *self.1 as usize
120+
LL | | }
121+
| |_________^
122+
123+
error: this could be a `const fn`
124+
--> tests/ui/missing_const_for_fn/could_be_const.rs:138:5
125+
|
126+
LL | / fn union_access_can_be_const() {
127+
LL | |
128+
LL | | let bar = Bar { val: 1 };
129+
LL | | let _ = unsafe { bar.val };
130+
LL | | }
131+
| |_____^
132+
133+
error: aborting due to 14 previous errors
106134

0 commit comments

Comments
 (0)