From 0f12711dd0e51cc839c66407c77c83560019c224 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Thu, 5 Dec 2019 14:59:56 +0100 Subject: [PATCH 1/4] make const-qualif look at more `const fn`s the unstables ones in libcore, with the unstable feature disabled, were not checked --- src/librustc_mir/transform/check_consts/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs index 7095b3fa0aa83..abad622289005 100644 --- a/src/librustc_mir/transform/check_consts/mod.rs +++ b/src/librustc_mir/transform/check_consts/mod.rs @@ -77,7 +77,11 @@ 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. An unstable `const fn` could otherwise be considered "not const" + // by const qualification. See issue #67053 for more details. + HirKind::Fn if tcx.is_const_fn_raw(def_id) => ConstKind::ConstFn, HirKind::Fn => return None, HirKind::Const => ConstKind::Const, From bc0df79db39c00cdb7dae4b6aff62ff9f2efc405 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Thu, 5 Dec 2019 15:01:30 +0100 Subject: [PATCH 2/4] libcore: rnable 2 unstable const fn features So that we can bootstrap successfully --- src/libcore/lib.rs | 2 ++ 1 file changed, 2 insertions(+) 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)] From 4a760c6ea12a1d15334879b40787f6f0a7056d9d Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Thu, 5 Dec 2019 15:02:41 +0100 Subject: [PATCH 3/4] add regression test for issue 67053 --- .../ui/consts/unstable-const-fn-in-libcore.rs | 29 +++++++++++++++++++ .../unstable-const-fn-in-libcore.stderr | 22 ++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/test/ui/consts/unstable-const-fn-in-libcore.rs create mode 100644 src/test/ui/consts/unstable-const-fn-in-libcore.stderr 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`. From 2d83b7608070d6ad250e8cd6d9d5a7d4be628dc4 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Thu, 5 Dec 2019 17:41:25 +0100 Subject: [PATCH 4/4] update comment to explain the importance of this check more clearly --- src/librustc_mir/transform/check_consts/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs index abad622289005..82ffafbedf858 100644 --- a/src/librustc_mir/transform/check_consts/mod.rs +++ b/src/librustc_mir/transform/check_consts/mod.rs @@ -79,8 +79,9 @@ impl ConstKind { // 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. An unstable `const fn` could otherwise be considered "not const" - // by const qualification. See issue #67053 for more details. + // 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,