Rollup merge of #132823 - RalfJung:conditional-const-calls, r=fee1-dead,compiler-errors

require const_impl_trait gate for all conditional and trait const calls

Alternative to https://github.com/rust-lang/rust/pull/132786.

`@compiler-errors`  this is basically what I meant with my proposals. I found it's easier to express this in code than English. ;)

r? `@compiler-errors`
This commit is contained in:
Jubilee 2024-11-09 20:28:44 -08:00 committed by GitHub
commit d4c81c6987
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 271 additions and 394 deletions

View File

@ -25,6 +25,10 @@ const_eval_closure_fndef_not_const =
function defined here, but it is not `const` function defined here, but it is not `const`
const_eval_closure_non_const = const_eval_closure_non_const =
cannot call non-const closure in {const_eval_const_context}s cannot call non-const closure in {const_eval_const_context}s
const_eval_conditionally_const_call =
cannot call conditionally-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
const_eval_consider_dereferencing = const_eval_consider_dereferencing =
consider dereferencing here consider dereferencing here

View File

@ -15,7 +15,7 @@
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::storage::always_storage_live_locals;
@ -361,31 +361,21 @@ fn place_may_escape(&mut self, place: &Place<'_>) -> bool {
!is_transient !is_transient
} }
/// Returns whether there are const-conditions.
fn revalidate_conditional_constness( fn revalidate_conditional_constness(
&mut self, &mut self,
callee: DefId, callee: DefId,
callee_args: ty::GenericArgsRef<'tcx>, callee_args: ty::GenericArgsRef<'tcx>,
call_source: CallSource,
call_span: Span, call_span: Span,
) { ) -> bool {
let tcx = self.tcx; let tcx = self.tcx;
if !tcx.is_conditionally_const(callee) { if !tcx.is_conditionally_const(callee) {
return; return false;
} }
let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args); let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
// If there are any const conditions on this fn and `const_trait_impl` if const_conditions.is_empty() {
// is not enabled, simply bail. We shouldn't be able to call conditionally return false;
// const functions on stable.
if !const_conditions.is_empty() && !tcx.features().const_trait_impl() {
self.check_op(ops::FnCallNonConst {
callee,
args: callee_args,
span: call_span,
call_source,
feature: Some(sym::const_trait_impl),
});
return;
} }
let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx)); let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx));
@ -421,6 +411,8 @@ fn revalidate_conditional_constness(
tcx.dcx() tcx.dcx()
.span_delayed_bug(call_span, "this should have reported a ~const error in HIR"); .span_delayed_bug(call_span, "this should have reported a ~const error in HIR");
} }
true
} }
} }
@ -627,11 +619,11 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
_ => unreachable!(), _ => unreachable!(),
}; };
let ConstCx { tcx, body, param_env, .. } = *self.ccx; let ConstCx { tcx, body, .. } = *self.ccx;
let fn_ty = func.ty(body, tcx); let fn_ty = func.ty(body, tcx);
let (mut callee, mut fn_args) = match *fn_ty.kind() { let (callee, fn_args) = match *fn_ty.kind() {
ty::FnDef(def_id, fn_args) => (def_id, fn_args), ty::FnDef(def_id, fn_args) => (def_id, fn_args),
ty::FnPtr(..) => { ty::FnPtr(..) => {
@ -645,57 +637,38 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
} }
}; };
self.revalidate_conditional_constness(callee, fn_args, call_source, *fn_span); let has_const_conditions =
self.revalidate_conditional_constness(callee, fn_args, *fn_span);
let mut is_trait = false;
// Attempting to call a trait method? // Attempting to call a trait method?
if let Some(trait_did) = tcx.trait_of_item(callee) { if let Some(trait_did) = tcx.trait_of_item(callee) {
// We can't determine the actual callee here, so we have to do different checks
// than usual.
trace!("attempting to call a trait method"); trace!("attempting to call a trait method");
let trait_is_const = tcx.is_const_trait(trait_did); let trait_is_const = tcx.is_const_trait(trait_did);
// trait method calls are only permitted when `effects` is enabled.
// typeck ensures the conditions for calling a const trait method are met,
// so we only error if the trait isn't const. We try to resolve the trait
// into the concrete method, and uses that for const stability checks.
// FIXME(const_trait_impl) we might consider moving const stability checks
// to typeck as well.
if tcx.features().const_trait_impl() && trait_is_const {
// This skips the check below that ensures we only call `const fn`.
is_trait = true;
if let Ok(Some(instance)) = if trait_is_const {
Instance::try_resolve(tcx, param_env, callee, fn_args) // Trait calls are always conditionally-const.
&& let InstanceKind::Item(def) = instance.def self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
{ // FIXME(const_trait_impl): do a more fine-grained check whether this
// Resolve a trait method call to its concrete implementation, which may be in a // particular trait can be const-stably called.
// `const` trait impl. This is only used for the const stability check below, since
// we want to look at the concrete impl's stability.
fn_args = instance.args;
callee = def;
}
} else { } else {
// if the trait is const but the user has not enabled the feature(s), // Not even a const trait.
// suggest them.
let feature = if trait_is_const {
Some(if tcx.features().const_trait_impl() {
sym::effects
} else {
sym::const_trait_impl
})
} else {
None
};
self.check_op(ops::FnCallNonConst { self.check_op(ops::FnCallNonConst {
callee, callee,
args: fn_args, args: fn_args,
span: *fn_span, span: *fn_span,
call_source, call_source,
feature,
}); });
// If we allowed this, we're in miri-unleashed mode, so we might
// as well skip the remaining checks.
return;
} }
// That's all we can check here.
return;
}
// Even if we know the callee, ensure we can use conditionally-const calls.
if has_const_conditions {
self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
} }
// At this point, we are calling a function, `callee`, whose `DefId` is known... // At this point, we are calling a function, `callee`, whose `DefId` is known...
@ -783,14 +756,12 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
return; return;
} }
// Trait functions are not `const fn` so we have to skip them here. if !tcx.is_const_fn(callee) {
if !tcx.is_const_fn(callee) && !is_trait {
self.check_op(ops::FnCallNonConst { self.check_op(ops::FnCallNonConst {
callee, callee,
args: fn_args, args: fn_args,
span: *fn_span, span: *fn_span,
call_source, call_source,
feature: None,
}); });
// If we allowed this, we're in miri-unleashed mode, so we might // If we allowed this, we're in miri-unleashed mode, so we might
// as well skip the remaining checks. // as well skip the remaining checks.

View File

@ -70,6 +70,37 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
} }
} }
/// A call to a function that is in a trait, or has trait bounds that make it conditionally-const.
#[derive(Debug)]
pub(crate) struct ConditionallyConstCall<'tcx> {
pub callee: DefId,
pub args: GenericArgsRef<'tcx>,
}
impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> {
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
// We use the `const_trait_impl` gate for all conditionally-const calls.
Status::Unstable {
gate: sym::const_trait_impl,
safe_to_expose_on_stable: false,
// We don't want the "mark the callee as `#[rustc_const_stable_indirect]`" hint
is_function_call: false,
}
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
ccx.tcx.sess.create_feature_err(
errors::ConditionallyConstCall {
span,
def_path_str: ccx.tcx.def_path_str_with_args(self.callee, self.args),
def_descr: ccx.tcx.def_descr(self.callee),
kind: ccx.const_kind(),
},
sym::const_trait_impl,
)
}
}
/// A function call where the callee is not marked as `const`. /// A function call where the callee is not marked as `const`.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub(crate) struct FnCallNonConst<'tcx> { pub(crate) struct FnCallNonConst<'tcx> {
@ -77,7 +108,6 @@ pub(crate) struct FnCallNonConst<'tcx> {
pub args: GenericArgsRef<'tcx>, pub args: GenericArgsRef<'tcx>,
pub span: Span, pub span: Span,
pub call_source: CallSource, pub call_source: CallSource,
pub feature: Option<Symbol>,
} }
impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
@ -85,7 +115,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
#[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::untranslatable_diagnostic)]
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
let FnCallNonConst { callee, args, span, call_source, feature } = *self; let FnCallNonConst { callee, args, span, call_source } = *self;
let ConstCx { tcx, param_env, .. } = *ccx; let ConstCx { tcx, param_env, .. } = *ccx;
let caller = ccx.def_id(); let caller = ccx.def_id();
@ -285,14 +315,6 @@ macro_rules! error {
ccx.const_kind(), ccx.const_kind(),
)); ));
if let Some(feature) = feature {
ccx.tcx.disabled_nightly_features(
&mut err,
Some(ccx.tcx.local_def_id_to_hir_id(caller)),
[(String::new(), feature)],
);
}
if let ConstContext::Static(_) = ccx.const_kind() { if let ConstContext::Static(_) = ccx.const_kind() {
err.note(fluent_generated::const_eval_lazy_lock); err.note(fluent_generated::const_eval_lazy_lock);
} }
@ -398,15 +420,8 @@ fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind()); let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind());
if let hir::CoroutineKind::Desugared( if let Status::Unstable { gate, .. } = self.status_in_item(ccx) {
hir::CoroutineDesugaring::Async, ccx.tcx.sess.create_feature_err(errors::UnallowedOpInConstContext { span, msg }, gate)
hir::CoroutineSource::Block,
) = self.0
{
ccx.tcx.sess.create_feature_err(
errors::UnallowedOpInConstContext { span, msg },
sym::const_async_blocks,
)
} else { } else {
ccx.dcx().create_err(errors::UnallowedOpInConstContext { span, msg }) ccx.dcx().create_err(errors::UnallowedOpInConstContext { span, msg })
} }

View File

@ -176,6 +176,16 @@ pub(crate) struct NonConstFmtMacroCall {
pub kind: ConstContext, pub kind: ConstContext,
} }
#[derive(Diagnostic)]
#[diag(const_eval_conditionally_const_call)]
pub(crate) struct ConditionallyConstCall {
#[primary_span]
pub span: Span,
pub def_path_str: String,
pub def_descr: &'static str,
pub kind: ConstContext,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(const_eval_non_const_fn_call, code = E0015)] #[diag(const_eval_non_const_fn_call, code = E0015)]
pub(crate) struct NonConstFnCall { pub(crate) struct NonConstFnCall {

View File

@ -155,6 +155,7 @@ pub fn feature_warn_issue(
} }
/// Adds the diagnostics for a feature to an existing error. /// Adds the diagnostics for a feature to an existing error.
/// Must be a language feature!
pub fn add_feature_diagnostics<G: EmissionGuarantee>( pub fn add_feature_diagnostics<G: EmissionGuarantee>(
err: &mut Diag<'_, G>, err: &mut Diag<'_, G>,
sess: &Session, sess: &Session,

View File

@ -300,6 +300,7 @@ pub fn is_test_crate(&self) -> bool {
self.opts.test self.opts.test
} }
/// `feature` must be a language feature.
#[track_caller] #[track_caller]
pub fn create_feature_err<'a>(&'a self, err: impl Diagnostic<'a>, feature: Symbol) -> Diag<'a> { pub fn create_feature_err<'a>(&'a self, err: impl Diagnostic<'a>, feature: Symbol) -> Diag<'a> {
let mut err = self.dcx().create_err(err); let mut err = self.dcx().create_err(err);

View File

@ -18,11 +18,9 @@ const fn const_context() {
#[cfg(any(stocknc, gatednc))] #[cfg(any(stocknc, gatednc))]
NonConst.func(); NonConst.func();
//[stocknc]~^ ERROR: cannot call //[stocknc]~^ ERROR: cannot call
//[stocknc]~| ERROR: cannot call //[gatednc]~^^ ERROR: the trait bound
//[gatednc]~^^^ ERROR: the trait bound
Const.func(); Const.func();
//[stock,stocknc]~^ ERROR: cannot call //[stock,stocknc]~^ ERROR: cannot call
//[stock,stocknc]~| ERROR: cannot call
} }
fn main() {} fn main() {}

View File

@ -1,28 +1,13 @@
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions error[E0658]: cannot call conditionally-const method `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:23:11 --> $DIR/cross-crate.rs:22:5
| |
LL | Const.func(); LL | Const.func();
| ^^^^^^ | ^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
| |
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions error: aborting due to 1 previous error
--> $DIR/cross-crate.rs:23:11
|
LL | Const.func();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,53 +1,23 @@
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions error[E0658]: cannot call conditionally-const method `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:19:14 --> $DIR/cross-crate.rs:19:5
| |
LL | NonConst.func(); LL | NonConst.func();
| ^^^^^^ | ^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
| |
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions error[E0658]: cannot call conditionally-const method `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:19:14 --> $DIR/cross-crate.rs:22:5
|
LL | NonConst.func();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:23:11
| |
LL | Const.func(); LL | Const.func();
| ^^^^^^ | ^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
| |
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions error: aborting due to 2 previous errors
--> $DIR/cross-crate.rs:23:11
|
LL | Const.func();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -10,8 +10,7 @@ fn non_const_context() {
const fn stable_const_context() { const fn stable_const_context() {
Unstable::func(); Unstable::func();
//~^ ERROR cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions //~^ ERROR cannot call conditionally-const associated function `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
//~| ERROR cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
} }
fn main() {} fn main() {}

View File

@ -1,28 +1,13 @@
error[E0015]: cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions error[E0658]: cannot call conditionally-const associated function `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
--> $DIR/staged-api-user-crate.rs:12:5 --> $DIR/staged-api-user-crate.rs:12:5
| |
LL | Unstable::func(); LL | Unstable::func();
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
| |
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
| = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
LL + #![feature(const_trait_impl)]
|
error[E0015]: cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions error: aborting due to 1 previous error
--> $DIR/staged-api-user-crate.rs:12:5
|
LL | Unstable::func();
| ^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,10 +1,11 @@
//@ revisions: stable unstable //! Checks whether we are properly enforcing recursive const stability for trait calls.
//@ compile-flags: -Znext-solver //@ compile-flags: -Znext-solver
#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. #![feature(unstable)] // The feature from the ./auxiliary/staged-api.rs file.
#![cfg_attr(unstable, feature(local_feature))] #![feature(local_feature)]
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
#![feature(staged_api)] #![feature(staged_api)]
#![feature(rustc_allow_const_fn_unstable)]
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
//@ aux-build: staged-api.rs //@ aux-build: staged-api.rs
@ -16,13 +17,16 @@
pub struct Foo; pub struct Foo;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(unstable, rustc_const_unstable(feature = "local_feature", issue = "none"))] #[rustc_const_unstable(feature = "local_feature", issue = "none")]
#[cfg_attr(stable, rustc_const_stable(feature = "local_feature", since = "1.0.0"))]
impl const MyTrait for Foo { impl const MyTrait for Foo {
//[stable]~^ ERROR trait implementations cannot be const stable yet
fn func() {} fn func() {}
} }
#[rustc_allow_const_fn_unstable(const_trait_impl)]
const fn conditionally_const<T: ~const MyTrait>() {
T::func();
}
// Const stability has no impact on usage in non-const contexts. // Const stability has no impact on usage in non-const contexts.
fn non_const_context() { fn non_const_context() {
Unstable::func(); Unstable::func();
@ -32,43 +36,35 @@ fn non_const_context() {
#[unstable(feature = "none", issue = "none")] #[unstable(feature = "none", issue = "none")]
const fn const_context() { const fn const_context() {
Unstable::func(); Unstable::func();
//[unstable]~^ ERROR cannot use `#[feature(unstable)]` //~^ ERROR cannot use `#[feature(const_trait_impl)]`
//[stable]~^^ ERROR not yet stable as a const fn
Foo::func(); Foo::func();
//[unstable]~^ ERROR cannot use `#[feature(local_feature)]` //~^ ERROR cannot use `#[feature(const_trait_impl)]`
//[stable]~^^ cannot be (indirectly) exposed to stable
// We get the error on `stable` since this is a trait function.
Unstable2::func(); Unstable2::func();
//~^ ERROR not yet stable as a const fn //~^ ERROR cannot use `#[feature(const_trait_impl)]`
// ^ fails, because the `unstable2` feature is not active conditionally_const::<Foo>();
//~^ ERROR cannot use `#[feature(const_trait_impl)]`
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(unstable, rustc_const_unstable(feature = "local_feature", issue = "none"))] #[rustc_const_unstable(feature = "local_feature", issue = "none")]
pub const fn const_context_not_const_stable() { pub const fn const_context_not_const_stable() {
//[stable]~^ ERROR function has missing const stability attribute
Unstable::func(); Unstable::func();
//[stable]~^ ERROR not yet stable as a const fn
Foo::func(); Foo::func();
//[stable]~^ cannot be (indirectly) exposed to stable
// We get the error on `stable` since this is a trait function.
Unstable2::func(); Unstable2::func();
//~^ ERROR not yet stable as a const fn conditionally_const::<Foo>();
// ^ fails, because the `unstable2` feature is not active
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "cheese", since = "1.0.0")] #[rustc_const_stable(feature = "cheese", since = "1.0.0")]
const fn stable_const_context() { const fn stable_const_context() {
Unstable::func(); Unstable::func();
//[unstable]~^ ERROR cannot use `#[feature(unstable)]` //~^ ERROR cannot use `#[feature(const_trait_impl)]`
//[stable]~^^ ERROR not yet stable as a const fn
Foo::func(); Foo::func();
//[unstable]~^ ERROR cannot use `#[feature(local_feature)]` //~^ ERROR cannot use `#[feature(const_trait_impl)]`
//[stable]~^^ cannot be (indirectly) exposed to stable const_context_not_const_stable();
// We get the error on `stable` since this is a trait function. //~^ ERROR cannot use `#[feature(local_feature)]`
const_context_not_const_stable() conditionally_const::<Foo>();
//[unstable]~^ ERROR cannot use `#[feature(local_feature)]` //~^ ERROR cannot use `#[feature(const_trait_impl)]`
} }
fn main() {} fn main() {}

View File

@ -1,89 +0,0 @@
error: trait implementations cannot be const stable yet
--> $DIR/staged-api.rs:21:1
|
LL | / impl const MyTrait for Foo {
LL | |
LL | | fn func() {}
LL | | }
| |_^
|
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
error: function has missing const stability attribute
--> $DIR/staged-api.rs:48:1
|
LL | / pub const fn const_context_not_const_stable() {
LL | |
LL | | Unstable::func();
LL | |
... |
LL | | // ^ fails, because the `unstable2` feature is not active
LL | | }
| |_^
error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
--> $DIR/staged-api.rs:34:5
|
LL | Unstable::func();
| ^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable
--> $DIR/staged-api.rs:37:5
|
LL | Foo::func();
| ^^^^^^^^^^^
|
= help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn
--> $DIR/staged-api.rs:41:5
|
LL | Unstable2::func();
| ^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable2)]` to the crate attributes to enable
error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
--> $DIR/staged-api.rs:50:5
|
LL | Unstable::func();
| ^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable
--> $DIR/staged-api.rs:52:5
|
LL | Foo::func();
| ^^^^^^^^^^^
|
= help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn
--> $DIR/staged-api.rs:55:5
|
LL | Unstable2::func();
| ^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable2)]` to the crate attributes to enable
error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn
--> $DIR/staged-api.rs:63:5
|
LL | Unstable::func();
| ^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable
--> $DIR/staged-api.rs:66:5
|
LL | Foo::func();
| ^^^^^^^^^^^
|
= help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
error: aborting due to 10 previous errors

View File

@ -0,0 +1,139 @@
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
--> $DIR/staged-api.rs:38:5
|
LL | Unstable::func();
| ^^^^^^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
LL | const fn const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
--> $DIR/staged-api.rs:40:5
|
LL | Foo::func();
| ^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
LL | const fn const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
--> $DIR/staged-api.rs:42:5
|
LL | Unstable2::func();
| ^^^^^^^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
LL | const fn const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
--> $DIR/staged-api.rs:44:5
|
LL | conditionally_const::<Foo>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
LL | const fn const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
--> $DIR/staged-api.rs:60:5
|
LL | Unstable::func();
| ^^^^^^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn stable_const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
LL | const fn stable_const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
--> $DIR/staged-api.rs:62:5
|
LL | Foo::func();
| ^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn stable_const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
LL | const fn stable_const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
--> $DIR/staged-api.rs:64:5
|
LL | const_context_not_const_stable();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn stable_const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(local_feature)]
LL | const fn stable_const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
--> $DIR/staged-api.rs:66:5
|
LL | conditionally_const::<Foo>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn stable_const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
LL | const fn stable_const_context() {
|
error: aborting due to 8 previous errors

View File

@ -1,108 +0,0 @@
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
--> $DIR/staged-api.rs:34:5
|
LL | Unstable::func();
| ^^^^^^^^^^^^^^^^
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(unstable)]
LL | const fn const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
--> $DIR/staged-api.rs:37:5
|
LL | Foo::func();
| ^^^^^^^^^^^
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(local_feature)]
LL | const fn const_context() {
|
error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn
--> $DIR/staged-api.rs:41:5
|
LL | Unstable2::func();
| ^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable2)]` to the crate attributes to enable
error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn
--> $DIR/staged-api.rs:55:5
|
LL | Unstable2::func();
| ^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable2)]` to the crate attributes to enable
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
--> $DIR/staged-api.rs:63:5
|
LL | Unstable::func();
| ^^^^^^^^^^^^^^^^
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn stable_const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(unstable)]
LL | const fn stable_const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
--> $DIR/staged-api.rs:66:5
|
LL | Foo::func();
| ^^^^^^^^^^^
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn stable_const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(local_feature)]
LL | const fn stable_const_context() {
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
--> $DIR/staged-api.rs:70:5
|
LL | const_context_not_const_stable()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn stable_const_context() {
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
LL + #[rustc_allow_const_fn_unstable(local_feature)]
LL | const fn stable_const_context() {
|
error: aborting due to 7 previous errors