about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection
diff options
context:
space:
mode:
authorBastian Kauschke <bastian_kauschke@hotmail.de>2020-09-01 16:17:41 +0200
committerBastian Kauschke <bastian_kauschke@hotmail.de>2020-09-08 16:39:12 +0200
commit1dd00e60b92cba4a84da0946ef63346e12ebd3d2 (patch)
treeeb476e5d9a05eb2f0ee35b566933c442a2753276 /compiler/rustc_trait_selection
parent78046448638c8db12db51b8f7bbbe29860d79c4e (diff)
downloadrust-1dd00e60b92cba4a84da0946ef63346e12ebd3d2.tar.gz
rust-1dd00e60b92cba4a84da0946ef63346e12ebd3d2.zip
add tracking issue, fix rebase
Diffstat (limited to 'compiler/rustc_trait_selection')
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
new file mode 100644
index 00000000000..013cd71ea30
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -0,0 +1,61 @@
+use rustc_hir::def::DefKind;
+use rustc_infer::infer::InferCtxt;
+use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::{self, TypeFoldable};
+use rustc_session::lint;
+use rustc_span::def_id::DefId;
+use rustc_span::Span;
+
+pub fn is_const_evaluatable<'cx, 'tcx>(
+    infcx: &InferCtxt<'cx, 'tcx>,
+    def: ty::WithOptConstParam<DefId>,
+    substs: SubstsRef<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    span: Span,
+) -> Result<(), ErrorHandled> {
+    let future_compat_lint = || {
+        if let Some(local_def_id) = def.did.as_local() {
+            infcx.tcx.struct_span_lint_hir(
+                lint::builtin::CONST_EVALUATABLE_UNCHECKED,
+                infcx.tcx.hir().local_def_id_to_hir_id(local_def_id),
+                span,
+                |err| {
+                    err.build("cannot use constants which depend on generic parameters in types")
+                        .emit();
+                },
+            );
+        }
+    };
+
+    // FIXME: We should only try to evaluate a given constant here if it is fully concrete
+    // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
+    //
+    // We previously did not check this, so we only emit a future compat warning if
+    // const evaluation succeeds and the given constant is still polymorphic for now
+    // and hopefully soon change this to an error.
+    //
+    // See #74595 for more details about this.
+    let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span));
+
+    let def_kind = infcx.tcx.def_kind(def.did);
+    match def_kind {
+        DefKind::AnonConst => {
+            let mir_body = if let Some(def) = def.as_const_arg() {
+                infcx.tcx.optimized_mir_of_const_arg(def)
+            } else {
+                infcx.tcx.optimized_mir(def.did)
+            };
+            if mir_body.is_polymorphic && concrete.is_ok() {
+                future_compat_lint();
+            }
+        }
+        _ => {
+            if substs.has_param_types_or_consts() && concrete.is_ok() {
+                future_compat_lint();
+            }
+        }
+    }
+
+    concrete.map(drop)
+}