Enforce stability of const fn in promoteds
This commit is contained in:
parent
d022dd48cc
commit
383a5df58c
src
librustc_mir/transform
librustc_passes
test/ui/const-eval
@ -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,24 @@ 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();
|
||||
if self.mode == Mode::Fn {
|
||||
// We are in a normal function
|
||||
// with a turned off feature gate. We can still call the function
|
||||
// but we can't promote it
|
||||
self.qualif = Qualif::NOT_CONST;
|
||||
debug!("unstable const fn");
|
||||
} else {
|
||||
// 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 {
|
||||
|
@ -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 {
|
||||
|
@ -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`.
|
34
src/test/ui/const-eval/dont_promote_unstable_const_fn.rs
Normal file
34
src/test/ui/const-eval/dont_promote_unstable_const_fn.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
|
||||
}
|
32
src/test/ui/const-eval/dont_promote_unstable_const_fn.stderr
Normal file
32
src/test/ui/const-eval/dont_promote_unstable_const_fn.stderr
Normal file
@ -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`.
|
Loading…
x
Reference in New Issue
Block a user