diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 004fb12419f11..3a237711fa56b 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -570,11 +570,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { }; let ConstCx { tcx, body, param_env, .. } = *self.ccx; - let caller = self.def_id(); let fn_ty = func.ty(body, tcx); - let (mut callee, mut fn_args) = match *fn_ty.kind() { + let (mut callee, fn_args) = match *fn_ty.kind() { ty::FnDef(def_id, fn_args) => (def_id, fn_args), ty::FnPtr(..) => { @@ -614,57 +613,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { infcx.err_ctxt().report_fulfillment_errors(errors); } - let mut is_trait = false; - // Attempting to call a trait method? - if let Some(trait_did) = tcx.trait_of_item(callee) { - trace!("attempting to call a trait method"); - - 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(effects) we might consider moving const stability checks to typeck as well. - if tcx.features().effects() && trait_is_const { - // This skips the check below that ensures we only call `const fn`. - is_trait = true; - - if let Ok(Some(instance)) = - Instance::try_resolve(tcx, param_env, callee, fn_args) - && let InstanceKind::Item(def) = instance.def - { - // Resolve a trait method call to its concrete implementation, which may be in a - // `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 { - // if the trait is const but the user has not enabled the feature(s), - // 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 { - caller, - callee, - args: fn_args, - span: *fn_span, - call_source, - feature, - }); - // If we allowed this, we're in miri-unleashed mode, so we might - // as well skip the remaining checks. - return; - } - } - // At this point, we are calling a function, `callee`, whose `DefId` is known... // `begin_panic` and `#[rustc_const_panic_str]` functions accept generic @@ -740,15 +688,29 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } // Trait functions are not `const fn` so we have to skip them here. - if !tcx.is_const_fn(callee) && !is_trait { - self.check_op(ops::FnCallNonConst { - caller, + if tcx.is_const_fn(callee) { + // Allowed, modulo stability below. + } else if let Some(_) = tcx.trait_of_item(callee) { + self.check_op(ops::TraitCallNonConst { callee, args: fn_args, span: *fn_span, call_source, - feature: None, }); + + // Resolve a trait method call to its concrete implementation, which + // may be in a `const` trait impl. This is only used for the const + // stability check below, since we want to look at the concrete impl's + // stability. + // FIXME(effects): Do we *actually* want to do this? + if let Ok(Some(instance)) = + Instance::try_resolve(tcx, param_env, callee, fn_args) + && let InstanceKind::Item(def) = instance.def + { + callee = def; + } + } else { + self.check_op(ops::FnCallNonConst { callee, args: fn_args, span: *fn_span }); // If we allowed this, we're in miri-unleashed mode, so we might // as well skip the remaining checks. return; diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 3ac06ae64910c..64ff2c4a77f4d 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -1,6 +1,5 @@ //! Concrete error types for all operations which may be invalid in a certain const context. -use hir::def_id::LocalDefId; use hir::{ConstContext, LangItem}; use rustc_errors::Diag; use rustc_errors::codes::*; @@ -71,24 +70,36 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect { } } -/// A function call where the callee is not marked as `const`. -#[derive(Debug, Clone, Copy)] -pub(crate) struct FnCallNonConst<'tcx> { - pub caller: LocalDefId, +#[derive(Debug)] +pub(crate) struct TraitCallNonConst<'tcx> { pub callee: DefId, pub args: GenericArgsRef<'tcx>, pub span: Span, pub call_source: CallSource, - pub feature: Option, } +impl<'tcx> NonConstOp<'tcx> for TraitCallNonConst<'tcx> { + fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status { + if ccx + .tcx + .trait_of_item(self.callee) + .is_some_and(|trait_def_id| ccx.tcx.is_const_trait(trait_def_id)) + { + Status::Unstable { + gate: sym::const_trait_impl, + safe_to_expose_on_stable: false, + is_function_call: true, + } + } else { + Status::Forbidden + } + } -impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { - // FIXME: make this translatable #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { - let FnCallNonConst { caller, callee, args, span, call_source, feature } = *self; - let ConstCx { tcx, param_env, body, .. } = *ccx; + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _span: Span) -> Diag<'tcx> { + let TraitCallNonConst { callee, args, span, call_source } = *self; + let ConstCx { tcx, param_env, .. } = *ccx; + let caller = ccx.def_id(); let diag_trait = |err, self_ty: Ty<'_>, trait_id| { let trait_ref = TraitRef::from_method(tcx, trait_id, args); @@ -113,6 +124,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { } } ty::Adt(..) => { + // FIXME(effects): Don't use select here. let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); @@ -270,9 +282,6 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span))); err } - _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => { - ccx.dcx().create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }) - } _ => ccx.dcx().create_err(errors::NonConstFnCall { span, def_path_str: ccx.tcx.def_path_str_with_args(callee, args), @@ -286,14 +295,56 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { ccx.const_kind(), )); - if let Some(feature) = feature { + if let ConstContext::Static(_) = ccx.const_kind() { + err.note(fluent_generated::const_eval_lazy_lock); + } + + if tcx + .trait_of_item(self.callee) + .is_some_and(|trait_def_id| tcx.is_const_trait(trait_def_id)) + { ccx.tcx.disabled_nightly_features( &mut err, - body.source.def_id().as_local().map(|local| ccx.tcx.local_def_id_to_hir_id(local)), - [(String::new(), feature)], + Some(ccx.tcx.local_def_id_to_hir_id(ccx.def_id())), + [(String::new(), sym::const_trait_impl)], ); } + err + } +} + +/// A function call where the callee is not marked as `const`. +#[derive(Debug, Clone, Copy)] +pub(crate) struct FnCallNonConst<'tcx> { + pub callee: DefId, + pub args: GenericArgsRef<'tcx>, + pub span: Span, +} + +impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { + let FnCallNonConst { callee, args, span } = *self; + let tcx = ccx.tcx; + + let mut err = if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) { + ccx.dcx().create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }) + } else { + ccx.dcx().create_err(errors::NonConstFnCall { + span, + def_path_str: ccx.tcx.def_path_str_with_args(callee, args), + kind: ccx.const_kind(), + }) + }; + + err.note(format!( + "calls in {}s are limited to constant functions, \ + tuple structs and tuple variants", + ccx.const_kind(), + )); + if let ConstContext::Static(_) = ccx.const_kind() { err.note(fluent_generated::const_eval_lazy_lock); } diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index 746b08fa71058..cbf9b6cbea763 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -40,54 +40,5 @@ LL | impl const A for T { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0015]: cannot call non-const fn `<() as A>::a` in constants - --> $DIR/const_trait_impl.rs:52:23 - | -LL | const _: () = assert!(<()>::a() == 42); - | ^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error[E0015]: cannot call non-const fn `::a` in constants - --> $DIR/const_trait_impl.rs:53:23 - | -LL | const _: () = assert!(::a() == 3); - | ^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error[E0015]: cannot call non-const fn `::a` in constants - --> $DIR/const_trait_impl.rs:54:23 - | -LL | const _: () = assert!(::a() == 2); - | ^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error[E0015]: cannot call non-const fn `::foo` in constant functions - --> $DIR/const_trait_impl.rs:48:9 - | -LL | T::foo() - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 10 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr index 32f53137a00e6..9ae1ed18e3511 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr @@ -24,18 +24,6 @@ LL | const ADD_INT: Int = Int(1i32) + Int(2i32); | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `::plus` in constant functions - --> $DIR/call-const-trait-method-pass.rs:11:20 - | -LL | Int(self.0.plus(rhs.0)) - | ^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - error[E0015]: cannot call non-const fn `::eq` in constant functions --> $DIR/call-const-trait-method-pass.rs:20:15 | @@ -44,18 +32,6 @@ LL | !self.eq(other) | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `::plus` in constant functions - --> $DIR/call-const-trait-method-pass.rs:36:7 - | -LL | a.plus(b) - | ^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stderr index 27e8053c9690a..e827f5fab124e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stderr @@ -29,19 +29,6 @@ LL | const fn check(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error[E0015]: cannot call non-const fn `::a` in constant functions - --> $DIR/const-drop-fail-2.rs:41:9 - | -LL | T::a(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0015, E0493. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/const-drop.precise.stderr b/tests/ui/traits/const-traits/const-drop.precise.stderr index 7b6d185c7cc8b..3df5eff541249 100644 --- a/tests/ui/traits/const-traits/const-drop.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop.precise.stderr @@ -54,19 +54,6 @@ error[E0493]: destructor of `T` cannot be evaluated at compile-time LL | const fn a(_: T) {} | ^ the destructor for this type cannot be evaluated in constant functions -error[E0015]: cannot call non-const fn `::foo` in constant functions - --> $DIR/const-drop.rs:69:13 - | -LL | T::foo(); - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0015, E0493. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/const-drop.stock.stderr b/tests/ui/traits/const-traits/const-drop.stock.stderr index b497c39b08aaf..48080d7856fe7 100644 --- a/tests/ui/traits/const-traits/const-drop.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop.stock.stderr @@ -56,19 +56,6 @@ LL | const fn a(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error[E0015]: cannot call non-const fn `::foo` in constant functions - --> $DIR/const-drop.rs:69:13 - | -LL | T::foo(); - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0015, E0493. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/staged-api-user-crate.stderr b/tests/ui/traits/const-traits/staged-api-user-crate.stderr index 781191ec97cd1..2a7542d14f573 100644 --- a/tests/ui/traits/const-traits/staged-api-user-crate.stderr +++ b/tests/ui/traits/const-traits/staged-api-user-crate.stderr @@ -10,6 +10,14 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error: aborting due to 1 previous error +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api-user-crate.rs:12:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/staged-api.stable.stderr b/tests/ui/traits/const-traits/staged-api.stable.stderr index 40045081f93cc..2a0444afabd92 100644 --- a/tests/ui/traits/const-traits/staged-api.stable.stderr +++ b/tests/ui/traits/const-traits/staged-api.stable.stderr @@ -21,6 +21,24 @@ LL | | // ^ fails, because the `unstable2` feature is not active LL | | } | |_^ +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:35: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(const_trait_impl)] +LL | const fn const_context() { + | + error: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:35:5 | @@ -29,6 +47,24 @@ LL | Unstable::func(); | = help: add `#![feature(unstable)]` to the crate attributes to enable +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:38: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(const_trait_impl)] +LL | const fn const_context() { + | + error: `::func` cannot be (indirectly) exposed to stable --> $DIR/staged-api.rs:38:5 | @@ -37,6 +73,24 @@ LL | Foo::func(); | = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` +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: 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(const_trait_impl)] +LL | const fn const_context() { + | + error: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:42:5 | @@ -45,6 +99,24 @@ 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(const_trait_impl)]` + --> $DIR/staged-api.rs:51: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 | pub const fn const_context_not_const_stable() { + | +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 | pub const fn const_context_not_const_stable() { + | + error: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:51:5 | @@ -53,6 +125,24 @@ LL | Unstable::func(); | = help: add `#![feature(unstable)]` to the crate attributes to enable +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:53: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 | pub const fn const_context_not_const_stable() { + | +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 | pub const fn const_context_not_const_stable() { + | + error: `::func` cannot be (indirectly) exposed to stable --> $DIR/staged-api.rs:53:5 | @@ -61,6 +151,24 @@ LL | Foo::func(); | = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:56:5 + | +LL | Unstable2::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 | pub const fn const_context_not_const_stable() { + | +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 | pub const fn const_context_not_const_stable() { + | + error: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:56:5 | @@ -69,6 +177,24 @@ 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(const_trait_impl)]` + --> $DIR/staged-api.rs:64: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(const_trait_impl)] +LL | const fn stable_const_context() { + | + error: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:64:5 | @@ -77,6 +203,24 @@ LL | Unstable::func(); | = help: add `#![feature(unstable)]` to the crate attributes to enable +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:67: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(const_trait_impl)] +LL | const fn stable_const_context() { + | + error: `::func` cannot be (indirectly) exposed to stable --> $DIR/staged-api.rs:67:5 | @@ -85,5 +229,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 +error: aborting due to 18 previous errors diff --git a/tests/ui/traits/const-traits/staged-api.unstable.stderr b/tests/ui/traits/const-traits/staged-api.unstable.stderr index 64b3a8ab19f13..d0eeeab283a48 100644 --- a/tests/ui/traits/const-traits/staged-api.unstable.stderr +++ b/tests/ui/traits/const-traits/staged-api.unstable.stderr @@ -1,3 +1,21 @@ +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:35: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(const_trait_impl)] +LL | const fn const_context() { + | + error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]` --> $DIR/staged-api.rs:35:5 | @@ -16,6 +34,24 @@ 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(const_trait_impl)]` + --> $DIR/staged-api.rs:38: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(const_trait_impl)] +LL | const fn const_context() { + | + error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]` --> $DIR/staged-api.rs:38:5 | @@ -34,6 +70,24 @@ LL + #[rustc_allow_const_fn_unstable(local_feature)] 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: 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(const_trait_impl)] +LL | const fn const_context() { + | + error: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:42:5 | @@ -50,6 +104,24 @@ 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(const_trait_impl)]` + --> $DIR/staged-api.rs:64: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(const_trait_impl)] +LL | const fn stable_const_context() { + | + error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]` --> $DIR/staged-api.rs:64:5 | @@ -68,6 +140,24 @@ 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(const_trait_impl)]` + --> $DIR/staged-api.rs:67: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(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:67:5 | @@ -104,5 +194,5 @@ LL + #[rustc_allow_const_fn_unstable(local_feature)] LL | const fn stable_const_context() { | -error: aborting due to 7 previous errors +error: aborting due to 12 previous errors