summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2020-09-27 01:53:27 +0200
committerGitHub <noreply@github.com>2020-09-27 01:53:27 +0200
commitaa35c527fd4257d0eddfbd7837e87d6c2d1e75bb (patch)
tree1fcdeeee4cede423a0c7ba97fb563c8a738ac638
parentRollup merge of #77209 - jyn514:fix-docs, r=petrochenkov (diff)
parentRemove all unstable feature support in the `missing_const_for_fn` lint (diff)
downloadrust-aa35c527fd4257d0eddfbd7837e87d6c2d1e75bb.tar.gz
rust-aa35c527fd4257d0eddfbd7837e87d6c2d1e75bb.tar.bz2
rust-aa35c527fd4257d0eddfbd7837e87d6c2d1e75bb.tar.xz
Rollup merge of #77231 - oli-obk:clippy_const_fn, r=Manishearth
Move helper function for `missing_const_for_fn` out of rustc to clippy cc @rust-lang/clippy @ecstatic-morse #76618 r? @Manishearth I also removed all support for suggesting a function could be `const fn` when that would require feature gates to actually work. This means we'll now have to maintain this ourselves in clippy, but that's how most lints work anyway, so...
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs (renamed from compiler/rustc_mir/src/transform/qualify_min_const_fn.rs)130
5 files changed, 32 insertions, 103 deletions
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index a622de9..850cafc 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -36,7 +36,6 @@ pub mod match_branches;
36pub mod no_landing_pads; 36pub mod no_landing_pads;
37pub mod nrvo; 37pub mod nrvo;
38pub mod promote_consts; 38pub mod promote_consts;
39pub mod qualify_min_const_fn;
40pub mod remove_noop_landing_pads; 39pub mod remove_noop_landing_pads;
41pub mod remove_unneeded_drops; 40pub mod remove_unneeded_drops;
42pub mod required_consts; 41pub mod required_consts;
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 58112ac..c3ff34e 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -6,6 +6,7 @@
6#![feature(concat_idents)] 6#![feature(concat_idents)]
7#![feature(crate_visibility_modifier)] 7#![feature(crate_visibility_modifier)]
8#![feature(drain_filter)] 8#![feature(drain_filter)]
9#![feature(in_band_lifetimes)]
9#![feature(or_patterns)] 10#![feature(or_patterns)]
10#![feature(rustc_private)] 11#![feature(rustc_private)]
11#![feature(stmt_expr_attributes)] 12#![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 1ad184d..e5f7cc5 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind;
4use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId}; 4use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
5use rustc_lint::{LateContext, LateLintPass}; 5use rustc_lint::{LateContext, LateLintPass};
6use rustc_middle::lint::in_external_macro; 6use rustc_middle::lint::in_external_macro;
7use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; 7use crate::utils::qualify_min_const_fn::is_min_const_fn;
8use rustc_session::{declare_lint_pass, declare_tool_lint}; 8use rustc_session::{declare_lint_pass, declare_tool_lint};
9use rustc_span::Span; 9use rustc_span::Span;
10use rustc_typeck::hir_ty_to_ty; 10use rustc_typeck::hir_ty_to_ty;
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index ea52741..96d9905 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -20,6 +20,7 @@ pub mod paths;
20pub mod ptr; 20pub mod ptr;
21pub mod sugg; 21pub mod sugg;
22pub mod usage; 22pub mod usage;
23pub mod qualify_min_const_fn;
23 24
24pub use self::attrs::*; 25pub use self::attrs::*;
25pub use self::diagnostics::*; 26pub use self::diagnostics::*;
diff --git a/compiler/rustc_mir/src/transform/qualify_min_const_fn.rs b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
index f15a7f7..6809b1f 100644
--- a/compiler/rustc_mir/src/transform/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
3use rustc_middle::mir::*; 3use rustc_middle::mir::*;
4use rustc_middle::ty::subst::GenericArgKind; 4use rustc_middle::ty::subst::GenericArgKind;
5use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; 5use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
6use rustc_span::symbol::{sym, Symbol}; 6use rustc_span::symbol::{sym};
7use rustc_span::Span; 7use rustc_span::Span;
8use rustc_target::spec::abi::Abi::RustIntrinsic; 8use rustc_target::spec::abi::Abi::RustIntrinsic;
9use std::borrow::Cow; 9use std::borrow::Cow;
@@ -11,14 +11,6 @@ use std::borrow::Cow;
11type McfResult = Result<(), (Span, Cow<'static, str>)>; 11type McfResult = Result<(), (Span, Cow<'static, str>)>;
12 12
13pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -> McfResult { 13pub 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 crate::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
22 let mut current = def_id; 14 let mut current = def_id;
23 loop { 15 loop {
24 let predicates = tcx.predicates_of(current); 16 let predicates = tcx.predicates_of(current);
@@ -32,27 +24,20 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
32 | ty::PredicateAtom::ConstEquate(..) 24 | ty::PredicateAtom::ConstEquate(..)
33 | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue, 25 | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
34 ty::PredicateAtom::ObjectSafe(_) => { 26 ty::PredicateAtom::ObjectSafe(_) => {
35 bug!("object safe predicate on function: {:#?}", predicate) 27 panic!("object safe predicate on function: {:#?}", predicate)
36 } 28 }
37 ty::PredicateAtom::ClosureKind(..) => { 29 ty::PredicateAtom::ClosureKind(..) => {
38 bug!("closure kind predicate on function: {:#?}", predicate) 30 panic!("closure kind predicate on function: {:#?}", predicate)
39 } 31 }
40 ty::PredicateAtom::Subtype(_) => { 32 ty::PredicateAtom::Subtype(_) => {
41 bug!("subtype predicate on function: {:#?}", predicate) 33 panic!("subtype predicate on function: {:#?}", predicate)
42 } 34 }
43 ty::PredicateAtom::Trait(pred, constness) => { 35 ty::PredicateAtom::Trait(pred, _) => {
44 if Some(pred.def_id()) == tcx.lang_items().sized_trait() { 36 if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
45 continue; 37 continue;
46 } 38 }
47 match pred.self_ty().kind() { 39 match pred.self_ty().kind() {
48 ty::Param(ref p) => { 40 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
56 let generics = tcx.generics_of(current); 41 let generics = tcx.generics_of(current);
57 let def = generics.type_param(p, tcx); 42 let def = generics.type_param(p, tcx);
58 let span = tcx.def_span(def.def_id); 43 let span = tcx.def_span(def.def_id);
@@ -77,18 +62,17 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
77 } 62 }
78 63
79 for local in &body.local_decls { 64 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)?;
81 } 66 }
82 // impl trait is gone in MIR, so check the return type manually 67 // impl trait is gone in MIR, so check the return type manually
83 check_ty( 68 check_ty(
84 tcx, 69 tcx,
85 tcx.fn_sig(def_id).output().skip_binder(), 70 tcx.fn_sig(def_id).output().skip_binder(),
86 body.local_decls.iter().next().unwrap().source_info.span, 71 body.local_decls.iter().next().unwrap().source_info.span,
87 def_id,
88 )?; 72 )?;
89 73
90 for bb in body.basic_blocks() { 74 for bb in body.basic_blocks() {
91 check_terminator(tcx, body, def_id, bb.terminator())?; 75 check_terminator(tcx, body, bb.terminator())?;
92 for stmt in &bb.statements { 76 for stmt in &bb.statements {
93 check_statement(tcx, body, def_id, stmt)?; 77 check_statement(tcx, body, def_id, stmt)?;
94 } 78 }
@@ -96,7 +80,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
96 Ok(()) 80 Ok(())
97} 81}
98 82
99fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult { 83fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
100 for arg in ty.walk() { 84 for arg in ty.walk() {
101 let ty = match arg.unpack() { 85 let ty = match arg.unpack() {
102 GenericArgKind::Type(ty) => ty, 86 GenericArgKind::Type(ty) => ty,
@@ -108,15 +92,11 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> Mc
108 92
109 match ty.kind() { 93 match ty.kind() {
110 ty::Ref(_, _, hir::Mutability::Mut) => { 94 ty::Ref(_, _, hir::Mutability::Mut) => {
111 if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) {
112 return Err((span, "mutable references in const fn are unstable".into())); 95 return Err((span, "mutable references in const fn are unstable".into()));
113 }
114 } 96 }
115 ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())), 97 ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
116 ty::FnPtr(..) => { 98 ty::FnPtr(..) => {
117 if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
118 return Err((span, "function pointers in const fn are unstable".into())); 99 return Err((span, "function pointers in const fn are unstable".into()));
119 }
120 } 100 }
121 ty::Dynamic(preds, _) => { 101 ty::Dynamic(preds, _) => {
122 for pred in preds.iter() { 102 for pred in preds.iter() {
@@ -161,12 +141,12 @@ fn check_rvalue(
161 Err((span, "cannot access thread local storage in const fn".into())) 141 Err((span, "cannot access thread local storage in const fn".into()))
162 } 142 }
163 Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { 143 Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
164 check_operand(tcx, operand, span, def_id, body) 144 check_operand(tcx, operand, span, body)
165 } 145 }
166 Rvalue::Len(place) 146 Rvalue::Len(place)
167 | Rvalue::Discriminant(place) 147 | Rvalue::Discriminant(place)
168 | Rvalue::Ref(_, _, place) 148 | 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),
170 Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { 150 Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
171 use rustc_middle::ty::cast::CastTy; 151 use rustc_middle::ty::cast::CastTy;
172 let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast"); 152 let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast");
@@ -175,14 +155,14 @@ fn check_rvalue(
175 (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => { 155 (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
176 Err((span, "casting pointers to ints is unstable in const fn".into())) 156 Err((span, "casting pointers to ints is unstable in const fn".into()))
177 } 157 }
178 _ => check_operand(tcx, operand, span, def_id, body), 158 _ => check_operand(tcx, operand, span, body),
179 } 159 }
180 } 160 }
181 Rvalue::Cast( 161 Rvalue::Cast(
182 CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), 162 CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
183 operand, 163 operand,
184 _, 164 _,
185 ) => check_operand(tcx, operand, span, def_id, body), 165 ) => check_operand(tcx, operand, span, body),
186 Rvalue::Cast( 166 Rvalue::Cast(
187 CastKind::Pointer( 167 CastKind::Pointer(
188 PointerCast::UnsafeFnPointer 168 PointerCast::UnsafeFnPointer
@@ -204,7 +184,7 @@ fn check_rvalue(
204 }; 184 };
205 let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id)); 185 let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
206 if let ty::Slice(_) | ty::Str = unsized_ty.kind() { 186 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)?;
208 // Casting/coercing things to slices is fine. 188 // Casting/coercing things to slices is fine.
209 Ok(()) 189 Ok(())
210 } else { 190 } else {
@@ -214,8 +194,8 @@ fn check_rvalue(
214 } 194 }
215 // binops are fine on integers 195 // binops are fine on integers
216 Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { 196 Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
217 check_operand(tcx, lhs, span, def_id, body)?; 197 check_operand(tcx, lhs, span, body)?;
218 check_operand(tcx, rhs, span, def_id, body)?; 198 check_operand(tcx, rhs, span, body)?;
219 let ty = lhs.ty(body, tcx); 199 let ty = lhs.ty(body, tcx);
220 if ty.is_integral() || ty.is_bool() || ty.is_char() { 200 if ty.is_integral() || ty.is_bool() || ty.is_char() {
221 Ok(()) 201 Ok(())
@@ -230,14 +210,14 @@ fn check_rvalue(
230 Rvalue::UnaryOp(_, operand) => { 210 Rvalue::UnaryOp(_, operand) => {
231 let ty = operand.ty(body, tcx); 211 let ty = operand.ty(body, tcx);
232 if ty.is_integral() || ty.is_bool() { 212 if ty.is_integral() || ty.is_bool() {
233 check_operand(tcx, operand, span, def_id, body) 213 check_operand(tcx, operand, span, body)
234 } else { 214 } else {
235 Err((span, "only int and `bool` operations are stable in const fn".into())) 215 Err((span, "only int and `bool` operations are stable in const fn".into()))
236 } 216 }
237 } 217 }
238 Rvalue::Aggregate(_, operands) => { 218 Rvalue::Aggregate(_, operands) => {
239 for operand in operands { 219 for operand in operands {
240 check_operand(tcx, operand, span, def_id, body)?; 220 check_operand(tcx, operand, span, body)?;
241 } 221 }
242 Ok(()) 222 Ok(())
243 } 223 }
@@ -253,15 +233,15 @@ fn check_statement(
253 let span = statement.source_info.span; 233 let span = statement.source_info.span;
254 match &statement.kind { 234 match &statement.kind {
255 StatementKind::Assign(box (place, rval)) => { 235 StatementKind::Assign(box (place, rval)) => {
256 check_place(tcx, *place, span, def_id, body)?; 236 check_place(tcx, *place, span, body)?;
257 check_rvalue(tcx, body, def_id, rval, span) 237 check_rvalue(tcx, body, def_id, rval, span)
258 } 238 }
259 239
260 StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, def_id, body), 240 StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, body),
261 241
262 // just an assignment 242 // just an assignment
263 StatementKind::SetDiscriminant { place, .. } => { 243 StatementKind::SetDiscriminant { place, .. } => {
264 check_place(tcx, **place, span, def_id, body) 244 check_place(tcx, **place, span, body)
265 } 245 }
266 246
267 StatementKind::LlvmInlineAsm { .. } => { 247 StatementKind::LlvmInlineAsm { .. } => {
@@ -282,11 +262,10 @@ fn check_operand(
282 tcx: TyCtxt<'tcx>, 262 tcx: TyCtxt<'tcx>,
283 operand: &Operand<'tcx>, 263 operand: &Operand<'tcx>,
284 span: Span, 264 span: Span,
285 def_id: DefId,
286 body: &Body<'tcx>, 265 body: &Body<'tcx>,
287) -> McfResult { 266) -> McfResult {
288 match operand { 267 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),
290 Operand::Constant(c) => match c.check_static_ptr(tcx) { 269 Operand::Constant(c) => match c.check_static_ptr(tcx) {
291 Some(_) => Err((span, "cannot access `static` items in const fn".into())), 270 Some(_) => Err((span, "cannot access `static` items in const fn".into())),
292 None => Ok(()), 271 None => Ok(()),
@@ -298,7 +277,6 @@ fn check_place(
298 tcx: TyCtxt<'tcx>, 277 tcx: TyCtxt<'tcx>,
299 place: Place<'tcx>, 278 place: Place<'tcx>,
300 span: Span, 279 span: Span,
301 def_id: DefId,
302 body: &Body<'tcx>, 280 body: &Body<'tcx>,
303) -> McfResult { 281) -> McfResult {
304 let mut cursor = place.projection.as_ref(); 282 let mut cursor = place.projection.as_ref();
@@ -310,9 +288,7 @@ fn check_place(
310 if let Some(def) = base_ty.ty_adt_def() { 288 if let Some(def) = base_ty.ty_adt_def() {
311 // No union field accesses in `const fn` 289 // No union field accesses in `const fn`
312 if def.is_union() { 290 if def.is_union() {
313 if !feature_allowed(tcx, def_id, sym::const_fn_union) {
314 return Err((span, "accessing union fields is unstable".into())); 291 return Err((span, "accessing union fields is unstable".into()));
315 }
316 } 292 }
317 } 293 }
318 } 294 }
@@ -327,48 +303,9 @@ fn check_place(
327 Ok(()) 303 Ok(())
328} 304}
329 305
330/// Returns `true` if the given feature gate is allowed within the function with the given `DefId`.
331fn 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 super::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`.
350pub 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 super::check_consts::allow_internal_unstable(tcx, def_id, feature_gate)
366}
367
368fn check_terminator( 306fn check_terminator(
369 tcx: TyCtxt<'tcx>, 307 tcx: TyCtxt<'tcx>,
370 body: &'a Body<'tcx>, 308 body: &'a Body<'tcx>,
371 def_id: DefId,
372 terminator: &Terminator<'tcx>, 309 terminator: &Terminator<'tcx>,
373) -> McfResult { 310) -> McfResult {
374 let span = terminator.source_info.span; 311 let span = terminator.source_info.span;
@@ -380,14 +317,14 @@ fn check_terminator(
380 | TerminatorKind::Resume 317 | TerminatorKind::Resume
381 | TerminatorKind::Unreachable => Ok(()), 318 | TerminatorKind::Unreachable => Ok(()),
382 319
383 TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, def_id, body), 320 TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body),
384 TerminatorKind::DropAndReplace { place, value, .. } => { 321 TerminatorKind::DropAndReplace { place, value, .. } => {
385 check_place(tcx, *place, span, def_id, body)?; 322 check_place(tcx, *place, span, body)?;
386 check_operand(tcx, value, span, def_id, body) 323 check_operand(tcx, value, span, body)
387 } 324 }
388 325
389 TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => { 326 TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => {
390 check_operand(tcx, discr, span, def_id, body) 327 check_operand(tcx, discr, span, body)
391 } 328 }
392 329
393 TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())), 330 TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
@@ -405,15 +342,7 @@ fn check_terminator(
405 } => { 342 } => {
406 let fn_ty = func.ty(body, tcx); 343 let fn_ty = func.ty(body, tcx);
407 if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() { 344 if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() {
408 // Allow unstable const if we opt in by using #[allow_internal_unstable] 345 if !rustc_mir::const_eval::is_min_const_fn(tcx, fn_def_id)
409 // on function or macro declaration.
410 if !crate::const_eval::is_min_const_fn(tcx, fn_def_id)
411 && !crate::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)
417 { 346 {
418 return Err(( 347 return Err((
419 span, 348 span,
@@ -432,7 +361,6 @@ fn check_terminator(
432 // transmutes in const fn before we add more hacks to this. 361 // transmutes in const fn before we add more hacks to this.
433 if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic 362 if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic
434 && tcx.item_name(fn_def_id) == sym::transmute 363 && tcx.item_name(fn_def_id) == sym::transmute
435 && !feature_allowed(tcx, def_id, sym::const_fn_transmute)
436 { 364 {
437 return Err(( 365 return Err((
438 span, 366 span,
@@ -440,10 +368,10 @@ fn check_terminator(
440 )); 368 ));
441 } 369 }
442 370
443 check_operand(tcx, func, span, fn_def_id, body)?; 371 check_operand(tcx, func, span, body)?;
444 372
445 for arg in args { 373 for arg in args {
446 check_operand(tcx, arg, span, fn_def_id, body)?; 374 check_operand(tcx, arg, span, body)?;
447 } 375 }
448 Ok(()) 376 Ok(())
449 } else { 377 } else {
@@ -452,7 +380,7 @@ fn check_terminator(
452 } 380 }
453 381
454 TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => { 382 TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => {
455 check_operand(tcx, cond, span, def_id, body) 383 check_operand(tcx, cond, span, body)
456 } 384 }
457 385
458 TerminatorKind::InlineAsm { .. } => { 386 TerminatorKind::InlineAsm { .. } => {