diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 999e3d89fc7e4..c249dc312f2f7 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -279,7 +279,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { if let Place::Local(index) = *dest { if self.mir.local_kind(index) == LocalKind::Temp && self.temp_promotion_state[index].is_promotable() { - debug!("store to promotable temp {:?}", index); + debug!("store to promotable temp {:?} ({:?})", index, qualif); store(&mut self.local_qualif[index]); } } @@ -969,10 +969,7 @@ This does not pose a problem by itself because they can't be accessed directly." feature: ref feature_name }), .. }) = self.tcx.lookup_stability(def_id) { - - // We are in a const or static initializer, - if self.mode != Mode::Fn && - + if // feature-gate is not enabled, !self.tcx.features() .declared_lib_features @@ -985,14 +982,19 @@ This does not pose a problem by itself because they can't be accessed directly." // this doesn't come from a macro that has #[allow_internal_unstable] !self.span.allows_unstable() { - let mut err = self.tcx.sess.struct_span_err(self.span, - &format!("`{}` is not yet stable as a const fn", - self.tcx.item_path_str(def_id))); - help!(&mut err, - "in Nightly builds, add `#![feature({})]` \ - to the crate attributes to enable", - feature_name); - err.emit(); + self.qualif = Qualif::NOT_CONST; + if self.mode != Mode::Fn { + // inside a constant environment, not having the feature gate is + // an error + let mut err = self.tcx.sess.struct_span_err(self.span, + &format!("`{}` is not yet stable as a const fn", + self.tcx.item_path_str(def_id))); + help!(&mut err, + "in Nightly builds, add `#![feature({})]` \ + to the crate attributes to enable", + feature_name); + err.emit(); + } } } } else { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 2e737a016da77..52ceb3ff5951d 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -38,6 +38,7 @@ use rustc::util::nodemap::{ItemLocalSet, NodeSet}; use rustc::hir; use rustc_data_structures::sync::Lrc; use syntax::ast; +use syntax::attr; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; @@ -119,7 +120,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { !ty.needs_drop(self.tcx, self.param_env) } - fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>) { + fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>, span: Span) { self.promotable &= self.type_has_only_promotable_values(ret_ty); self.promotable &= if let Some(fn_id) = self.tcx.hir.as_local_node_id(def_id) { @@ -129,6 +130,25 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { } else { self.tcx.is_const_fn(def_id) }; + + if let Some(&attr::Stability { + rustc_const_unstable: Some(attr::RustcConstUnstable { + feature: ref feature_name + }), + .. }) = self.tcx.lookup_stability(def_id) { + self.promotable &= + // feature-gate is enabled, + self.tcx.features() + .declared_lib_features + .iter() + .any(|&(ref sym, _)| sym == feature_name) || + + // this comes from a crate with the feature-gate enabled, + !def_id.is_local() || + + // this comes from a macro that has #[allow_internal_unstable] + span.allows_unstable(); + } } } @@ -359,12 +379,12 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => {} Def::Fn(did) => { - v.handle_const_fn_call(did, node_ty) + v.handle_const_fn_call(did, node_ty, e.span) } Def::Method(did) => { match v.tcx.associated_item(did).container { ty::ImplContainer(_) => { - v.handle_const_fn_call(did, node_ty) + v.handle_const_fn_call(did, node_ty, e.span) } ty::TraitContainer(_) => v.promotable = false } @@ -376,7 +396,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) { let def_id = def.def_id(); match v.tcx.associated_item(def_id).container { - ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty), + ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty, e.span), ty::TraitContainer(_) => v.promotable = false } } else { diff --git a/src/test/ui/const-eval/dont_promote_unstable_const_fn.nll.stderr b/src/test/ui/const-eval/dont_promote_unstable_const_fn.nll.stderr new file mode 100644 index 0000000000000..684fa1c997bf1 --- /dev/null +++ b/src/test/ui/const-eval/dont_promote_unstable_const_fn.nll.stderr @@ -0,0 +1,21 @@ +error: `foo` is not yet stable as a const fn + --> $DIR/dont_promote_unstable_const_fn.rs:25:25 + | +LL | const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn + | ^^^^^ + | + = help: in Nightly builds, add `#![feature(foo)]` to the crate attributes to enable + +error[E0597]: borrowed value does not live long enough + --> $DIR/dont_promote_unstable_const_fn.rs:33:26 + | +LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/const-eval/dont_promote_unstable_const_fn.rs b/src/test/ui/const-eval/dont_promote_unstable_const_fn.rs new file mode 100644 index 0000000000000..a590e569947f8 --- /dev/null +++ b/src/test/ui/const-eval/dont_promote_unstable_const_fn.rs @@ -0,0 +1,34 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![unstable(feature = "humans", + reason = "who ever let humans program computers, + we're apparently really bad at it", + issue = "0")] + +#![feature(rustc_const_unstable, const_fn)] +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo")] +const fn foo() -> u32 { 42 } + +fn meh() -> u32 { 42 } + +const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn + +fn a() { + let _: &'static u32 = &foo(); //~ ERROR does not live long enough +} + +fn main() { + let _: &'static u32 = &meh(); //~ ERROR does not live long enough + let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis(); +} diff --git a/src/test/ui/const-eval/dont_promote_unstable_const_fn.stderr b/src/test/ui/const-eval/dont_promote_unstable_const_fn.stderr new file mode 100644 index 0000000000000..7963cbb4e4569 --- /dev/null +++ b/src/test/ui/const-eval/dont_promote_unstable_const_fn.stderr @@ -0,0 +1,32 @@ +error: `foo` is not yet stable as a const fn + --> $DIR/dont_promote_unstable_const_fn.rs:25:25 + | +LL | const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn + | ^^^^^ + | + = help: in Nightly builds, add `#![feature(foo)]` to the crate attributes to enable + +error[E0597]: borrowed value does not live long enough + --> $DIR/dont_promote_unstable_const_fn.rs:28:28 + | +LL | let _: &'static u32 = &foo(); //~ ERROR does not live long enough + | ^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/dont_promote_unstable_const_fn.rs:32:28 + | +LL | let _: &'static u32 = &meh(); //~ ERROR does not live long enough + | ^^^^^ temporary value does not live long enough +LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis(); +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`.