]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/transform/qualify_min_const_fn.rs
introduce PredicateAtom
[rust.git] / src / librustc_mir / transform / qualify_min_const_fn.rs
index 7041e2db27e3269be4805c3fad1fe0d467d082e5..de7d7f27186f2b4f59a772db0dd7b3fcc7ad096f 100644 (file)
@@ -6,6 +6,7 @@
 use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use rustc_target::spec::abi::Abi::RustIntrinsic;
 use std::borrow::Cow;
 
 type McfResult = Result<(), (Span, Cow<'static, str>)>;
@@ -23,27 +24,27 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
     loop {
         let predicates = tcx.predicates_of(current);
         for (predicate, _) in predicates.predicates {
-            match predicate.kind() {
-                ty::PredicateKind::RegionOutlives(_)
-                | ty::PredicateKind::TypeOutlives(_)
-                | ty::PredicateKind::WellFormed(_)
-                | ty::PredicateKind::Projection(_)
-                | ty::PredicateKind::ConstEvaluatable(..)
-                | ty::PredicateKind::ConstEquate(..) => continue,
-                ty::PredicateKind::ObjectSafe(_) => {
+            match predicate.skip_binders() {
+                ty::PredicateAtom::RegionOutlives(_)
+                | ty::PredicateAtom::TypeOutlives(_)
+                | ty::PredicateAtom::WellFormed(_)
+                | ty::PredicateAtom::Projection(_)
+                | ty::PredicateAtom::ConstEvaluatable(..)
+                | ty::PredicateAtom::ConstEquate(..) => continue,
+                ty::PredicateAtom::ObjectSafe(_) => {
                     bug!("object safe predicate on function: {:#?}", predicate)
                 }
-                ty::PredicateKind::ClosureKind(..) => {
+                ty::PredicateAtom::ClosureKind(..) => {
                     bug!("closure kind predicate on function: {:#?}", predicate)
                 }
-                ty::PredicateKind::Subtype(_) => {
+                ty::PredicateAtom::Subtype(_) => {
                     bug!("subtype predicate on function: {:#?}", predicate)
                 }
-                &ty::PredicateKind::Trait(pred, constness) => {
+                ty::PredicateAtom::Trait(pred, constness) => {
                     if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                         continue;
                     }
-                    match pred.skip_binder().self_ty().kind {
+                    match pred.self_ty().kind {
                         ty::Param(ref p) => {
                             // Allow `T: ?const Trait`
                             if constness == hir::Constness::NotConst
@@ -418,6 +419,20 @@ fn check_terminator(
                     ));
                 }
 
+                // HACK: This is to "unstabilize" the `transmute` intrinsic
+                // within const fns. `transmute` is allowed in all other const contexts.
+                // This won't really scale to more intrinsics or functions. Let's allow const
+                // transmutes in const fn before we add more hacks to this.
+                if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic
+                    && tcx.item_name(fn_def_id) == sym::transmute
+                    && !feature_allowed(tcx, def_id, sym::const_fn_transmute)
+                {
+                    return Err((
+                        span,
+                        "can only call `transmute` from const items, not `const fn`".into(),
+                    ));
+                }
+
                 check_operand(tcx, func, span, fn_def_id, body)?;
 
                 for arg in args {