diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index ec19392450a4b..188ea1a963116 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -74,6 +74,8 @@ #![feature(const_fn)] #![feature(const_fn_union)] #![feature(const_generics)] +#![cfg_attr(not(bootstrap), feature(const_ptr_offset_from))] +#![cfg_attr(not(bootstrap), feature(const_type_name))] #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs index 7095b3fa0aa83..82ffafbedf858 100644 --- a/src/librustc_mir/transform/check_consts/mod.rs +++ b/src/librustc_mir/transform/check_consts/mod.rs @@ -77,7 +77,12 @@ impl ConstKind { let mode = match tcx.hir().body_owner_kind(hir_id) { HirKind::Closure => return None, - HirKind::Fn if tcx.is_const_fn(def_id) => ConstKind::ConstFn, + // Note: this is deliberately checking for `is_const_fn_raw`, as the `is_const_fn` + // checks take into account the `rustc_const_unstable` attribute combined with enabled + // feature gates. Otherwise, const qualification would _not check_ whether this + // function body follows the `const fn` rules, as an unstable `const fn` would + // be considered "not const". More details are available in issue #67053. + HirKind::Fn if tcx.is_const_fn_raw(def_id) => ConstKind::ConstFn, HirKind::Fn => return None, HirKind::Const => ConstKind::Const, diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs new file mode 100644 index 0000000000000..cad1516fc78d0 --- /dev/null +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs @@ -0,0 +1,29 @@ +// This is a non-regression test for const-qualification of unstable items in libcore +// as explained in issue #67053. +// const-qualification could miss some `const fn`s if they were unstable and the feature +// gate was not enabled in libcore. + +#![stable(feature = "core", since = "1.6.0")] +#![feature(const_if_match)] +#![feature(rustc_const_unstable)] +#![feature(staged_api)] + +enum Opt { + Some(T), + None, +} + +impl Opt { + #[rustc_const_unstable(feature = "foo")] + #[stable(feature = "rust1", since = "1.0.0")] + const fn unwrap_or_else T>(self, f: F) -> T { + //~^ ERROR destructors cannot be evaluated at compile-time + //~| ERROR destructors cannot be evaluated at compile-time + match self { + Opt::Some(t) => t, + Opt::None => f(), //~ ERROR E0015 + } + } +} + +fn main() {} diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr new file mode 100644 index 0000000000000..a8455cefd01cf --- /dev/null +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr @@ -0,0 +1,22 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/unstable-const-fn-in-libcore.rs:24:26 + | +LL | Opt::None => f(), + | ^^^ + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:19:53 + | +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^ constant functions cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:19:47 + | +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^^^^ constant functions cannot evaluate destructors + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`.