Skip to content

Commit 7072e45

Browse files
committed
Remove all unstable feature support in the missing_const_for_fn lint
1 parent a6fda14 commit 7072e45

File tree

1 file changed

+25
-97
lines changed

1 file changed

+25
-97
lines changed

clippy_lints/src/utils/qualify_min_const_fn.rs

+25-97
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,14 @@ use rustc_hir::def_id::DefId;
33
use rustc_middle::mir::*;
44
use rustc_middle::ty::subst::GenericArgKind;
55
use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
6-
use rustc_span::symbol::{sym, Symbol};
6+
use rustc_span::symbol::{sym};
77
use rustc_span::Span;
88
use rustc_target::spec::abi::Abi::RustIntrinsic;
99
use std::borrow::Cow;
1010

1111
type McfResult = Result<(), (Span, Cow<'static, str>)>;
1212

1313
pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -> McfResult {
14-
// Prevent const trait methods from being annotated as `stable`.
15-
if tcx.features().staged_api {
16-
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
17-
if rustc_mir::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
18-
return Err((body.span, "trait methods cannot be stable const fn".into()));
19-
}
20-
}
21-
2214
let mut current = def_id;
2315
loop {
2416
let predicates = tcx.predicates_of(current);
@@ -40,19 +32,12 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
4032
ty::PredicateAtom::Subtype(_) => {
4133
panic!("subtype predicate on function: {:#?}", predicate)
4234
}
43-
ty::PredicateAtom::Trait(pred, constness) => {
35+
ty::PredicateAtom::Trait(pred, _) => {
4436
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
4537
continue;
4638
}
4739
match pred.self_ty().kind() {
4840
ty::Param(ref p) => {
49-
// Allow `T: ?const Trait`
50-
if constness == hir::Constness::NotConst
51-
&& feature_allowed(tcx, def_id, sym::const_trait_bound_opt_out)
52-
{
53-
continue;
54-
}
55-
5641
let generics = tcx.generics_of(current);
5742
let def = generics.type_param(p, tcx);
5843
let span = tcx.def_span(def.def_id);
@@ -77,26 +62,25 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
7762
}
7863

7964
for local in &body.local_decls {
80-
check_ty(tcx, local.ty, local.source_info.span, def_id)?;
65+
check_ty(tcx, local.ty, local.source_info.span)?;
8166
}
8267
// impl trait is gone in MIR, so check the return type manually
8368
check_ty(
8469
tcx,
8570
tcx.fn_sig(def_id).output().skip_binder(),
8671
body.local_decls.iter().next().unwrap().source_info.span,
87-
def_id,
8872
)?;
8973

9074
for bb in body.basic_blocks() {
91-
check_terminator(tcx, body, def_id, bb.terminator())?;
75+
check_terminator(tcx, body, bb.terminator())?;
9276
for stmt in &bb.statements {
9377
check_statement(tcx, body, def_id, stmt)?;
9478
}
9579
}
9680
Ok(())
9781
}
9882

99-
fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult {
83+
fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
10084
for arg in ty.walk() {
10185
let ty = match arg.unpack() {
10286
GenericArgKind::Type(ty) => ty,
@@ -108,15 +92,11 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> Mc
10892

10993
match ty.kind() {
11094
ty::Ref(_, _, hir::Mutability::Mut) => {
111-
if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) {
11295
return Err((span, "mutable references in const fn are unstable".into()));
113-
}
11496
}
11597
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
11698
ty::FnPtr(..) => {
117-
if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
11899
return Err((span, "function pointers in const fn are unstable".into()));
119-
}
120100
}
121101
ty::Dynamic(preds, _) => {
122102
for pred in preds.iter() {
@@ -161,12 +141,12 @@ fn check_rvalue(
161141
Err((span, "cannot access thread local storage in const fn".into()))
162142
}
163143
Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
164-
check_operand(tcx, operand, span, def_id, body)
144+
check_operand(tcx, operand, span, body)
165145
}
166146
Rvalue::Len(place)
167147
| Rvalue::Discriminant(place)
168148
| Rvalue::Ref(_, _, place)
169-
| Rvalue::AddressOf(_, place) => check_place(tcx, *place, span, def_id, body),
149+
| Rvalue::AddressOf(_, place) => check_place(tcx, *place, span, body),
170150
Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
171151
use rustc_middle::ty::cast::CastTy;
172152
let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast");
@@ -175,14 +155,14 @@ fn check_rvalue(
175155
(CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
176156
Err((span, "casting pointers to ints is unstable in const fn".into()))
177157
}
178-
_ => check_operand(tcx, operand, span, def_id, body),
158+
_ => check_operand(tcx, operand, span, body),
179159
}
180160
}
181161
Rvalue::Cast(
182162
CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
183163
operand,
184164
_,
185-
) => check_operand(tcx, operand, span, def_id, body),
165+
) => check_operand(tcx, operand, span, body),
186166
Rvalue::Cast(
187167
CastKind::Pointer(
188168
PointerCast::UnsafeFnPointer
@@ -204,7 +184,7 @@ fn check_rvalue(
204184
};
205185
let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
206186
if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
207-
check_operand(tcx, op, span, def_id, body)?;
187+
check_operand(tcx, op, span, body)?;
208188
// Casting/coercing things to slices is fine.
209189
Ok(())
210190
} else {
@@ -214,8 +194,8 @@ fn check_rvalue(
214194
}
215195
// binops are fine on integers
216196
Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
217-
check_operand(tcx, lhs, span, def_id, body)?;
218-
check_operand(tcx, rhs, span, def_id, body)?;
197+
check_operand(tcx, lhs, span, body)?;
198+
check_operand(tcx, rhs, span, body)?;
219199
let ty = lhs.ty(body, tcx);
220200
if ty.is_integral() || ty.is_bool() || ty.is_char() {
221201
Ok(())
@@ -230,14 +210,14 @@ fn check_rvalue(
230210
Rvalue::UnaryOp(_, operand) => {
231211
let ty = operand.ty(body, tcx);
232212
if ty.is_integral() || ty.is_bool() {
233-
check_operand(tcx, operand, span, def_id, body)
213+
check_operand(tcx, operand, span, body)
234214
} else {
235215
Err((span, "only int and `bool` operations are stable in const fn".into()))
236216
}
237217
}
238218
Rvalue::Aggregate(_, operands) => {
239219
for operand in operands {
240-
check_operand(tcx, operand, span, def_id, body)?;
220+
check_operand(tcx, operand, span, body)?;
241221
}
242222
Ok(())
243223
}
@@ -253,15 +233,15 @@ fn check_statement(
253233
let span = statement.source_info.span;
254234
match &statement.kind {
255235
StatementKind::Assign(box (place, rval)) => {
256-
check_place(tcx, *place, span, def_id, body)?;
236+
check_place(tcx, *place, span, body)?;
257237
check_rvalue(tcx, body, def_id, rval, span)
258238
}
259239

260-
StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, def_id, body),
240+
StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, body),
261241

262242
// just an assignment
263243
StatementKind::SetDiscriminant { place, .. } => {
264-
check_place(tcx, **place, span, def_id, body)
244+
check_place(tcx, **place, span, body)
265245
}
266246

267247
StatementKind::LlvmInlineAsm { .. } => {
@@ -282,11 +262,10 @@ fn check_operand(
282262
tcx: TyCtxt<'tcx>,
283263
operand: &Operand<'tcx>,
284264
span: Span,
285-
def_id: DefId,
286265
body: &Body<'tcx>,
287266
) -> McfResult {
288267
match operand {
289-
Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, def_id, body),
268+
Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body),
290269
Operand::Constant(c) => match c.check_static_ptr(tcx) {
291270
Some(_) => Err((span, "cannot access `static` items in const fn".into())),
292271
None => Ok(()),
@@ -298,7 +277,6 @@ fn check_place(
298277
tcx: TyCtxt<'tcx>,
299278
place: Place<'tcx>,
300279
span: Span,
301-
def_id: DefId,
302280
body: &Body<'tcx>,
303281
) -> McfResult {
304282
let mut cursor = place.projection.as_ref();
@@ -310,9 +288,7 @@ fn check_place(
310288
if let Some(def) = base_ty.ty_adt_def() {
311289
// No union field accesses in `const fn`
312290
if def.is_union() {
313-
if !feature_allowed(tcx, def_id, sym::const_fn_union) {
314291
return Err((span, "accessing union fields is unstable".into()));
315-
}
316292
}
317293
}
318294
}
@@ -327,48 +303,9 @@ fn check_place(
327303
Ok(())
328304
}
329305

330-
/// Returns `true` if the given feature gate is allowed within the function with the given `DefId`.
331-
fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
332-
// All features require that the corresponding gate be enabled,
333-
// even if the function has `#[allow_internal_unstable(the_gate)]`.
334-
if !tcx.features().enabled(feature_gate) {
335-
return false;
336-
}
337-
338-
// If this crate is not using stability attributes, or this function is not claiming to be a
339-
// stable `const fn`, that is all that is required.
340-
if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
341-
return true;
342-
}
343-
344-
// However, we cannot allow stable `const fn`s to use unstable features without an explicit
345-
// opt-in via `allow_internal_unstable`.
346-
rustc_mir::transform::check_consts::allow_internal_unstable(tcx, def_id, feature_gate)
347-
}
348-
349-
/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`.
350-
pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
351-
// All features require that the corresponding gate be enabled,
352-
// even if the function has `#[allow_internal_unstable(the_gate)]`.
353-
if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) {
354-
return false;
355-
}
356-
357-
// If this crate is not using stability attributes, or this function is not claiming to be a
358-
// stable `const fn`, that is all that is required.
359-
if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
360-
return true;
361-
}
362-
363-
// However, we cannot allow stable `const fn`s to use unstable features without an explicit
364-
// opt-in via `allow_internal_unstable`.
365-
rustc_mir::transform::check_consts::allow_internal_unstable(tcx, def_id, feature_gate)
366-
}
367-
368306
fn check_terminator(
369307
tcx: TyCtxt<'tcx>,
370308
body: &'a Body<'tcx>,
371-
def_id: DefId,
372309
terminator: &Terminator<'tcx>,
373310
) -> McfResult {
374311
let span = terminator.source_info.span;
@@ -380,14 +317,14 @@ fn check_terminator(
380317
| TerminatorKind::Resume
381318
| TerminatorKind::Unreachable => Ok(()),
382319

383-
TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, def_id, body),
320+
TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body),
384321
TerminatorKind::DropAndReplace { place, value, .. } => {
385-
check_place(tcx, *place, span, def_id, body)?;
386-
check_operand(tcx, value, span, def_id, body)
322+
check_place(tcx, *place, span, body)?;
323+
check_operand(tcx, value, span, body)
387324
}
388325

389326
TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => {
390-
check_operand(tcx, discr, span, def_id, body)
327+
check_operand(tcx, discr, span, body)
391328
}
392329

393330
TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
@@ -405,15 +342,7 @@ fn check_terminator(
405342
} => {
406343
let fn_ty = func.ty(body, tcx);
407344
if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() {
408-
// Allow unstable const if we opt in by using #[allow_internal_unstable]
409-
// on function or macro declaration.
410345
if !rustc_mir::const_eval::is_min_const_fn(tcx, fn_def_id)
411-
&& !rustc_mir::const_eval::is_unstable_const_fn(tcx, fn_def_id)
412-
.map(|feature| {
413-
span.allows_unstable(feature)
414-
|| lib_feature_allowed(tcx, def_id, feature)
415-
})
416-
.unwrap_or(false)
417346
{
418347
return Err((
419348
span,
@@ -432,18 +361,17 @@ fn check_terminator(
432361
// transmutes in const fn before we add more hacks to this.
433362
if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic
434363
&& tcx.item_name(fn_def_id) == sym::transmute
435-
&& !feature_allowed(tcx, def_id, sym::const_fn_transmute)
436364
{
437365
return Err((
438366
span,
439367
"can only call `transmute` from const items, not `const fn`".into(),
440368
));
441369
}
442370

443-
check_operand(tcx, func, span, fn_def_id, body)?;
371+
check_operand(tcx, func, span, body)?;
444372

445373
for arg in args {
446-
check_operand(tcx, arg, span, fn_def_id, body)?;
374+
check_operand(tcx, arg, span, body)?;
447375
}
448376
Ok(())
449377
} else {
@@ -452,7 +380,7 @@ fn check_terminator(
452380
}
453381

454382
TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => {
455-
check_operand(tcx, cond, span, def_id, body)
383+
check_operand(tcx, cond, span, body)
456384
}
457385

458386
TerminatorKind::InlineAsm { .. } => {

0 commit comments

Comments
 (0)