Skip to content

Commit 0746522

Browse files
committed
Auto merge of #50909 - oli-obk:unstable_const_fn_promotion, r=eddyb
Enforce stability of const fn in promoteds r? @eddyb fixes #50901 what's going on here? Why do we have two promoted computation algorithms?
2 parents a41dd6f + a11f785 commit 0746522

File tree

5 files changed

+126
-17
lines changed

5 files changed

+126
-17
lines changed

Diff for: src/librustc_mir/transform/qualify_consts.rs

+15-13
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
279279
if let Place::Local(index) = *dest {
280280
if self.mir.local_kind(index) == LocalKind::Temp
281281
&& self.temp_promotion_state[index].is_promotable() {
282-
debug!("store to promotable temp {:?}", index);
282+
debug!("store to promotable temp {:?} ({:?})", index, qualif);
283283
store(&mut self.local_qualif[index]);
284284
}
285285
}
@@ -969,10 +969,7 @@ This does not pose a problem by itself because they can't be accessed directly."
969969
feature: ref feature_name
970970
}),
971971
.. }) = self.tcx.lookup_stability(def_id) {
972-
973-
// We are in a const or static initializer,
974-
if self.mode != Mode::Fn &&
975-
972+
if
976973
// feature-gate is not enabled,
977974
!self.tcx.features()
978975
.declared_lib_features
@@ -985,14 +982,19 @@ This does not pose a problem by itself because they can't be accessed directly."
985982
// this doesn't come from a macro that has #[allow_internal_unstable]
986983
!self.span.allows_unstable()
987984
{
988-
let mut err = self.tcx.sess.struct_span_err(self.span,
989-
&format!("`{}` is not yet stable as a const fn",
990-
self.tcx.item_path_str(def_id)));
991-
help!(&mut err,
992-
"in Nightly builds, add `#![feature({})]` \
993-
to the crate attributes to enable",
994-
feature_name);
995-
err.emit();
985+
self.qualif = Qualif::NOT_CONST;
986+
if self.mode != Mode::Fn {
987+
// inside a constant environment, not having the feature gate is
988+
// an error
989+
let mut err = self.tcx.sess.struct_span_err(self.span,
990+
&format!("`{}` is not yet stable as a const fn",
991+
self.tcx.item_path_str(def_id)));
992+
help!(&mut err,
993+
"in Nightly builds, add `#![feature({})]` \
994+
to the crate attributes to enable",
995+
feature_name);
996+
err.emit();
997+
}
996998
}
997999
}
9981000
} else {

Diff for: src/librustc_passes/rvalue_promotion.rs

+24-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use rustc::util::nodemap::{ItemLocalSet, NodeSet};
3838
use rustc::hir;
3939
use rustc_data_structures::sync::Lrc;
4040
use syntax::ast;
41+
use syntax::attr;
4142
use syntax_pos::{Span, DUMMY_SP};
4243
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
4344

@@ -119,7 +120,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
119120
!ty.needs_drop(self.tcx, self.param_env)
120121
}
121122

122-
fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>) {
123+
fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>, span: Span) {
123124
self.promotable &= self.type_has_only_promotable_values(ret_ty);
124125

125126
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> {
129130
} else {
130131
self.tcx.is_const_fn(def_id)
131132
};
133+
134+
if let Some(&attr::Stability {
135+
rustc_const_unstable: Some(attr::RustcConstUnstable {
136+
feature: ref feature_name
137+
}),
138+
.. }) = self.tcx.lookup_stability(def_id) {
139+
self.promotable &=
140+
// feature-gate is enabled,
141+
self.tcx.features()
142+
.declared_lib_features
143+
.iter()
144+
.any(|&(ref sym, _)| sym == feature_name) ||
145+
146+
// this comes from a crate with the feature-gate enabled,
147+
!def_id.is_local() ||
148+
149+
// this comes from a macro that has #[allow_internal_unstable]
150+
span.allows_unstable();
151+
}
132152
}
133153
}
134154

@@ -359,12 +379,12 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
359379
Def::StructCtor(_, CtorKind::Fn) |
360380
Def::VariantCtor(_, CtorKind::Fn) => {}
361381
Def::Fn(did) => {
362-
v.handle_const_fn_call(did, node_ty)
382+
v.handle_const_fn_call(did, node_ty, e.span)
363383
}
364384
Def::Method(did) => {
365385
match v.tcx.associated_item(did).container {
366386
ty::ImplContainer(_) => {
367-
v.handle_const_fn_call(did, node_ty)
387+
v.handle_const_fn_call(did, node_ty, e.span)
368388
}
369389
ty::TraitContainer(_) => v.promotable = false
370390
}
@@ -376,7 +396,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
376396
if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) {
377397
let def_id = def.def_id();
378398
match v.tcx.associated_item(def_id).container {
379-
ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty),
399+
ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty, e.span),
380400
ty::TraitContainer(_) => v.promotable = false
381401
}
382402
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error: `foo` is not yet stable as a const fn
2+
--> $DIR/dont_promote_unstable_const_fn.rs:25:25
3+
|
4+
LL | const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn
5+
| ^^^^^
6+
|
7+
= help: in Nightly builds, add `#![feature(foo)]` to the crate attributes to enable
8+
9+
error[E0597]: borrowed value does not live long enough
10+
--> $DIR/dont_promote_unstable_const_fn.rs:33:26
11+
|
12+
LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
14+
LL | }
15+
| - temporary value only lives until here
16+
|
17+
= note: borrowed value must be valid for the static lifetime...
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0597`.
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![unstable(feature = "humans",
12+
reason = "who ever let humans program computers,
13+
we're apparently really bad at it",
14+
issue = "0")]
15+
16+
#![feature(rustc_const_unstable, const_fn)]
17+
#![feature(staged_api)]
18+
19+
#[stable(feature = "rust1", since = "1.0.0")]
20+
#[rustc_const_unstable(feature="foo")]
21+
const fn foo() -> u32 { 42 }
22+
23+
fn meh() -> u32 { 42 }
24+
25+
const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn
26+
27+
fn a() {
28+
let _: &'static u32 = &foo(); //~ ERROR does not live long enough
29+
}
30+
31+
fn main() {
32+
let _: &'static u32 = &meh(); //~ ERROR does not live long enough
33+
let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error: `foo` is not yet stable as a const fn
2+
--> $DIR/dont_promote_unstable_const_fn.rs:25:25
3+
|
4+
LL | const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn
5+
| ^^^^^
6+
|
7+
= help: in Nightly builds, add `#![feature(foo)]` to the crate attributes to enable
8+
9+
error[E0597]: borrowed value does not live long enough
10+
--> $DIR/dont_promote_unstable_const_fn.rs:28:28
11+
|
12+
LL | let _: &'static u32 = &foo(); //~ ERROR does not live long enough
13+
| ^^^^^ temporary value does not live long enough
14+
LL | }
15+
| - temporary value only lives until here
16+
|
17+
= note: borrowed value must be valid for the static lifetime...
18+
19+
error[E0597]: borrowed value does not live long enough
20+
--> $DIR/dont_promote_unstable_const_fn.rs:32:28
21+
|
22+
LL | let _: &'static u32 = &meh(); //~ ERROR does not live long enough
23+
| ^^^^^ temporary value does not live long enough
24+
LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
25+
LL | }
26+
| - temporary value only lives until here
27+
|
28+
= note: borrowed value must be valid for the static lifetime...
29+
30+
error: aborting due to 3 previous errors
31+
32+
For more information about this error, try `rustc --explain E0597`.

0 commit comments

Comments
 (0)