Auto merge of #65188 - matthewjasper:stabilize-const-constructor, r=Centril
Stabilize `const_constructor` # Stabilization proposal I propose that we stabilize `#![feature(const_constructor)]`. Tracking issue: https://github.com/rust-lang/rust/issues/61456 Version target: 1.40 (2019-11-05 => beta, 2019-12-19 => stable). ## What is stabilized ### User guide Tuple struct and tuple variant constructors are now considered to be constant functions. As such a call expression where the callee has a tuple struct or variant constructor "function item" type can be called: ```rust const fn make_options() { // These already work because they are special cased: Some(0); (Option::Some)(1); // These also work now: let f = Option::Some; f(2); {Option::Some}(3); <Option<_>>::Some(5); } ``` ### Motivation Consistency with other `const fn`. Consistency between syntactic path forms. This should also ensure that constructors implement `const Fn` traits and can be coerced to `const fn` function pointers, if they are introduced. ## Tests * [ui/consts/const_constructor/const-construct-call.rs](0d75ab2293/src/test/ui/consts/const_constructor/const-construct-call.rs
) - Tests various syntactic forms, use in both `const fn` and `const` items, and constructors in both the current and extern crates. * [ui/consts/const_constructor/const_constructor_qpath.rs](1850dfcdab/src/test/ui/consts/const_constructor/const_constructor_qpath.rs
) - Tests that type qualified paths to enum variants are also considered to be `const fn`.(#64247) r? @oli-obk Closes #61456 Closes #64247
This commit is contained in:
commit
03a50ae9b8
@ -2,7 +2,7 @@
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::hir;
|
||||
use crate::ty::TyCtxt;
|
||||
use syntax_pos::symbol::{sym, Symbol};
|
||||
use syntax_pos::symbol::Symbol;
|
||||
use crate::hir::map::blocks::FnLikeNode;
|
||||
use syntax::attr;
|
||||
|
||||
@ -13,14 +13,11 @@ pub fn is_const_fn(self, def_id: DefId) -> bool {
|
||||
self.is_const_fn_raw(def_id) && match self.is_unstable_const_fn(def_id) {
|
||||
Some(feature_name) => {
|
||||
// has a `rustc_const_unstable` attribute, check whether the user enabled the
|
||||
// corresponding feature gate, const_constructor is not a lib feature, so has
|
||||
// to be checked separately.
|
||||
// corresponding feature gate.
|
||||
self.features()
|
||||
.declared_lib_features
|
||||
.iter()
|
||||
.any(|&(sym, _)| sym == feature_name)
|
||||
|| (feature_name == sym::const_constructor
|
||||
&& self.features().const_constructor)
|
||||
},
|
||||
// functions without const stability are either stable user written
|
||||
// const fn or the user is using feature gates and we thus don't
|
||||
@ -31,9 +28,7 @@ pub fn is_const_fn(self, def_id: DefId) -> bool {
|
||||
|
||||
/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
|
||||
pub fn is_unstable_const_fn(self, def_id: DefId) -> Option<Symbol> {
|
||||
if self.is_constructor(def_id) {
|
||||
Some(sym::const_constructor)
|
||||
} else if self.is_const_fn_raw(def_id) {
|
||||
if self.is_const_fn_raw(def_id) {
|
||||
self.lookup_stability(def_id)?.const_stability
|
||||
} else {
|
||||
None
|
||||
|
@ -249,6 +249,8 @@ macro_rules! declare_features {
|
||||
(accepted, macros_in_extern, "1.40.0", Some(49476), None),
|
||||
/// Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008).
|
||||
(accepted, non_exhaustive, "1.40.0", Some(44109), None),
|
||||
/// Allows calling constructor functions in `const fn`.
|
||||
(accepted, const_constructor, "1.40.0", Some(61456), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: accepted features
|
||||
|
@ -488,9 +488,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
|
||||
/// Allows the user of associated type bounds.
|
||||
(active, associated_type_bounds, "1.34.0", Some(52662), None),
|
||||
|
||||
/// Allows calling constructor functions in `const fn`.
|
||||
(active, const_constructor, "1.37.0", Some(61456), None),
|
||||
|
||||
/// Allows `if/while p && let q = r && ...` chains.
|
||||
(active, let_chains, "1.37.0", Some(53667), None),
|
||||
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
#![cfg_attr(const_fn, feature(const_fn))]
|
||||
|
||||
#![feature(const_constructor)]
|
||||
|
||||
// Ctor(..) is transformed to Ctor { 0: ... } in HAIR lowering, so directly
|
||||
// calling constructors doesn't require them to be const.
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
// revisions: min_const_fn const_fn
|
||||
// run-pass
|
||||
|
||||
#![cfg_attr(const_fn, feature(const_fn))]
|
||||
|
||||
trait ConstDefault {
|
||||
const DEFAULT: Self;
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum E {
|
||||
V(i32),
|
||||
W(usize),
|
||||
}
|
||||
|
||||
impl ConstDefault for E {
|
||||
const DEFAULT: Self = Self::V(23);
|
||||
}
|
||||
|
||||
impl ConstDefault for Option<i32> {
|
||||
const DEFAULT: Self = Self::Some(23);
|
||||
}
|
||||
|
||||
impl E {
|
||||
const NON_DEFAULT: Self = Self::W(12);
|
||||
const fn local_fn() -> Self {
|
||||
Self::V(23)
|
||||
}
|
||||
}
|
||||
|
||||
const fn explicit_qpath() -> E {
|
||||
let _x = <Option<usize>>::Some(23);
|
||||
<E>::W(12)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert!(E::DEFAULT == E::local_fn());
|
||||
assert!(Option::DEFAULT == Some(23));
|
||||
assert!(E::NON_DEFAULT == explicit_qpath());
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
error: `std::prelude::v1::Some` is not yet stable as a const fn
|
||||
--> $DIR/feature-gate-const_constructor.rs:9:37
|
||||
|
|
||||
LL | const EXTERNAL_CONST: Option<i32> = {Some}(1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(const_constructor)]` to the crate attributes to enable
|
||||
|
||||
error: `E::V` is not yet stable as a const fn
|
||||
--> $DIR/feature-gate-const_constructor.rs:12:24
|
||||
|
|
||||
LL | const LOCAL_CONST: E = {E::V}(1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(const_constructor)]` to the crate attributes to enable
|
||||
|
||||
error: `std::prelude::v1::Some` is not yet stable as a const fn
|
||||
--> $DIR/feature-gate-const_constructor.rs:17:13
|
||||
|
|
||||
LL | let _ = {Some}(1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(const_constructor)]` to the crate attributes to enable
|
||||
|
||||
error: `E::V` is not yet stable as a const fn
|
||||
--> $DIR/feature-gate-const_constructor.rs:23:13
|
||||
|
|
||||
LL | let _ = {E::V}(1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(const_constructor)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -1,34 +0,0 @@
|
||||
error: `std::prelude::v1::Some` is not yet stable as a const fn
|
||||
--> $DIR/feature-gate-const_constructor.rs:9:37
|
||||
|
|
||||
LL | const EXTERNAL_CONST: Option<i32> = {Some}(1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(const_constructor)]` to the crate attributes to enable
|
||||
|
||||
error: `E::V` is not yet stable as a const fn
|
||||
--> $DIR/feature-gate-const_constructor.rs:12:24
|
||||
|
|
||||
LL | const LOCAL_CONST: E = {E::V}(1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(const_constructor)]` to the crate attributes to enable
|
||||
|
||||
error: `std::prelude::v1::Some` is not yet stable as a const fn
|
||||
--> $DIR/feature-gate-const_constructor.rs:17:13
|
||||
|
|
||||
LL | let _ = {Some}(1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(const_constructor)]` to the crate attributes to enable
|
||||
|
||||
error: `E::V` is not yet stable as a const fn
|
||||
--> $DIR/feature-gate-const_constructor.rs:23:13
|
||||
|
|
||||
LL | let _ = {E::V}(1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(const_constructor)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -1,28 +0,0 @@
|
||||
// revisions: min_const_fn const_fn
|
||||
|
||||
#![cfg_attr(const_fn, feature(const_fn))]
|
||||
|
||||
enum E {
|
||||
V(i32),
|
||||
}
|
||||
|
||||
const EXTERNAL_CONST: Option<i32> = {Some}(1);
|
||||
//[min_const_fn]~^ ERROR is not yet stable as a const fn
|
||||
//[const_fn]~^^ ERROR is not yet stable as a const fn
|
||||
const LOCAL_CONST: E = {E::V}(1);
|
||||
//[min_const_fn]~^ ERROR is not yet stable as a const fn
|
||||
//[const_fn]~^^ ERROR is not yet stable as a const fn
|
||||
|
||||
const fn external_fn() {
|
||||
let _ = {Some}(1);
|
||||
//[min_const_fn]~^ ERROR is not yet stable as a const fn
|
||||
//[const_fn]~^^ ERROR is not yet stable as a const fn
|
||||
}
|
||||
|
||||
const fn local_fn() {
|
||||
let _ = {E::V}(1);
|
||||
//[min_const_fn]~^ ERROR is not yet stable as a const fn
|
||||
//[const_fn]~^^ ERROR is not yet stable as a const fn
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user