about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGary Guo <gary@garyguo.net>2020-06-26 23:33:35 +0100
committerGary Guo <gary@garyguo.net>2020-06-27 00:53:18 +0100
commit779b05d16a38fec347a874210e2ae54579a8f5c1 (patch)
tree4f8d6719b6c4bedbeba4a7e0d1ff5b59e1db3b64
parentfc239e82fe1ef91632dfa858487d89141aaab7a7 (diff)
downloadrust-779b05d16a38fec347a874210e2ae54579a8f5c1.tar.gz
rust-779b05d16a38fec347a874210e2ae54579a8f5c1.zip
Fix ICE for lib features
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs4
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs25
2 files changed, 25 insertions, 4 deletions
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 80257260f01..bd9d33e67f8 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -550,9 +550,9 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                 } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) {
                     // Exempt unstable const fns inside of macros or functions with
                     // `#[allow_internal_unstable]`.
-                    use crate::transform::qualify_min_const_fn::feature_allowed;
+                    use crate::transform::qualify_min_const_fn::lib_feature_allowed;
                     if !self.span.allows_unstable(feature)
-                        && !feature_allowed(self.tcx, self.def_id, feature)
+                        && !lib_feature_allowed(self.tcx, self.def_id, feature)
                     {
                         self.check_op(ops::FnCallUnstable(def_id, feature));
                     }
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 6f252ad4ed5..7c54acf2163 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -315,7 +315,7 @@ fn check_place(
 }
 
 /// Returns `true` if the given feature gate is allowed within the function with the given `DefId`.
-pub fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
+fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
     // All features require that the corresponding gate be enabled,
     // even if the function has `#[allow_internal_unstable(the_gate)]`.
     if !tcx.features().enabled(feature_gate) {
@@ -334,6 +334,26 @@ pub fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -
         .map_or(false, |mut features| features.any(|name| name == feature_gate))
 }
 
+/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`.
+pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
+    // All features require that the corresponding gate be enabled,
+    // even if the function has `#[allow_internal_unstable(the_gate)]`.
+    if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) {
+        return false;
+    }
+
+    // If this crate is not using stability attributes, or this function is not claiming to be a
+    // stable `const fn`, that is all that is required.
+    if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
+        return true;
+    }
+
+    // However, we cannot allow stable `const fn`s to use unstable features without an explicit
+    // opt-in via `allow_internal_unstable`.
+    attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic())
+        .map_or(false, |mut features| features.any(|name| name == feature_gate))
+}
+
 fn check_terminator(
     tcx: TyCtxt<'tcx>,
     body: &'a Body<'tcx>,
@@ -383,7 +403,8 @@ fn check_terminator(
                 if !crate::const_eval::is_min_const_fn(tcx, fn_def_id)
                     && !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id)
                         .map(|feature| {
-                            span.allows_unstable(feature) || feature_allowed(tcx, def_id, feature)
+                            span.allows_unstable(feature)
+                                || lib_feature_allowed(tcx, def_id, feature)
                         })
                         .unwrap_or(false)
                 {