require const_impl_trait gate for all conditional and trait const calls
This commit is contained in:
parent
62bb2ac03e
commit
822762c966
@ -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
|
||||||
|
|
||||||
|
@ -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.
|
// That's all we can check here.
|
||||||
return;
|
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.
|
||||||
|
@ -70,6 +70,34 @@ 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.dcx().create_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(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 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 +105,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 +112,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 +312,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);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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() {}
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
|
error: 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)]
|
|
||||||
|
|
|
||||||
|
|
||||||
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 E0015`.
|
|
||||||
|
@ -1,53 +1,14 @@
|
|||||||
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
|
error: 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)]
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
|
error: 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)]
|
|
||||||
|
|
|
||||||
|
|
||||||
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 E0015`.
|
|
||||||
|
@ -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() {}
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
error[E0015]: 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
|
||||||
--> $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
|
|
||||||
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
|
||||||
|
|
|
||||||
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 E0015`.
|
|
||||||
|
@ -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() {}
|
||||||
|
@ -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
|
|
||||||
|
|
139
tests/ui/traits/const-traits/staged-api.stderr
Normal file
139
tests/ui/traits/const-traits/staged-api.stderr
Normal 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
|
||||||
|
|
@ -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
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user