1
Fork 0

Unify conditional and non const call error reporting

This commit is contained in:
Michael Goulet 2024-12-23 21:53:07 +00:00
commit 924000d70e
12 changed files with 300 additions and 261 deletions

View file

@ -21,8 +21,6 @@ const_eval_closure_call =
closures need an RFC before allowed to be called in {const_eval_const_context}s
const_eval_closure_fndef_not_const =
function defined here, but it is not `const`
const_eval_conditionally_const_call =
cannot call conditionally-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
const_eval_consider_dereferencing =
consider dereferencing here
@ -239,18 +237,18 @@ const_eval_non_const_await =
cannot convert `{$ty}` into a future in {const_eval_const_context}s
const_eval_non_const_closure =
cannot call {$non}-const closure in {const_eval_const_context}s
cannot call {$non_or_conditionally}-const closure in {const_eval_const_context}s
const_eval_non_const_deref_coercion =
cannot perform {$non}-const deref coercion on `{$ty}` in {const_eval_const_context}s
cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {const_eval_const_context}s
.note = attempting to deref into `{$target_ty}`
.target_note = deref defined here
const_eval_non_const_fmt_macro_call =
cannot call {$non}-const formatting macro in {const_eval_const_context}s
cannot call {$non_or_conditionally}-const formatting macro in {const_eval_const_context}s
const_eval_non_const_fn_call =
cannot call {$non}-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
const_eval_non_const_for_loop_into_iter =
cannot use `for` loop on `{$ty}` in {const_eval_const_context}s
@ -259,13 +257,13 @@ const_eval_non_const_impl =
impl defined here, but it is not `const`
const_eval_non_const_intrinsic =
cannot call {$non}-const intrinsic `{$name}` in {const_eval_const_context}s
cannot call non-const intrinsic `{$name}` in {const_eval_const_context}s
const_eval_non_const_match_eq = cannot match on `{$ty}` in {const_eval_const_context}s
.note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es
const_eval_non_const_operator =
cannot call {$non}-const operator in {const_eval_const_context}s
cannot call {$non_or_conditionally}-const operator in {const_eval_const_context}s
const_eval_non_const_question_branch =
`?` is not allowed on `{$ty}` in {const_eval_const_context}s

View file

@ -708,7 +708,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
if trait_is_const {
// Trait calls are always conditionally-const.
self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
self.check_op(ops::ConditionallyConstCall {
callee,
args: fn_args,
span: *fn_span,
call_source,
});
// FIXME(const_trait_impl): do a more fine-grained check whether this
// particular trait can be const-stably called.
} else {
@ -726,7 +731,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// 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 });
self.check_op(ops::ConditionallyConstCall {
callee,
args: fn_args,
span: *fn_span,
call_source,
});
}
// At this point, we are calling a function, `callee`, whose `DefId` is known...

View file

@ -15,6 +15,7 @@ use rustc_middle::ty::{
suggest_constraining_type_param,
};
use rustc_middle::util::{CallDesugaringKind, CallKind, call_kind};
use rustc_session::parse::add_feature_diagnostics;
use rustc_span::{BytePos, Pos, Span, Symbol, sym};
use rustc_trait_selection::traits::SelectionContext;
use tracing::debug;
@ -77,6 +78,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
pub(crate) struct ConditionallyConstCall<'tcx> {
pub callee: DefId,
pub args: GenericArgsRef<'tcx>,
pub span: Span,
pub call_source: CallSource,
}
impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> {
@ -91,24 +94,22 @@ impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> {
}
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
let mut err = 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,
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
let mut diag = build_error_for_const_call(
ccx,
self.callee,
self.args,
self.span,
self.call_source,
"conditionally",
|_, _, _| {},
);
err.note(format!(
"calls in {}s are limited to constant functions, \
tuple structs and tuple variants",
ccx.const_kind(),
));
// Override code and mention feature.
diag.code(E0658);
add_feature_diagnostics(&mut diag, ccx.tcx.sess, sym::const_trait_impl);
err
diag
}
}
@ -126,209 +127,59 @@ 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, call_source } = *self;
let ConstCx { tcx, typing_env, .. } = *ccx;
let tcx = ccx.tcx;
let caller = ccx.def_id();
let note_trait_if_possible = |err, self_ty: Ty<'_>, trait_id| {
let trait_ref = TraitRef::from_method(tcx, trait_id, args);
let mut err = build_error_for_const_call(
ccx,
self.callee,
self.args,
self.span,
self.call_source,
"non",
|err, self_ty, trait_id| {
// FIXME(const_trait_impl): Do we need any of this on the non-const codepath?
match self_ty.kind() {
Param(param_ty) => {
debug!(?param_ty);
if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
let constraint = with_no_trimmed_paths!(format!(
"~const {}",
trait_ref.print_trait_sugared(),
));
suggest_constraining_type_param(
tcx,
generics,
err,
param_ty.name.as_str(),
&constraint,
Some(trait_ref.def_id),
None,
);
}
}
ty::Adt(..) => {
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
let mut selcx = SelectionContext::new(&infcx);
let implsrc = selcx.select(&obligation);
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
// FIXME(const_trait_impl) revisit this
if !tcx.is_const_trait_impl(data.impl_def_id) {
let span = tcx.def_span(data.impl_def_id);
err.subdiagnostic(errors::NonConstImplNote { span });
let trait_ref = TraitRef::from_method(tcx, trait_id, self.args);
match self_ty.kind() {
Param(param_ty) => {
debug!(?param_ty);
if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
let constraint = with_no_trimmed_paths!(format!(
"~const {}",
trait_ref.print_trait_sugared(),
));
suggest_constraining_type_param(
tcx,
generics,
err,
param_ty.name.as_str(),
&constraint,
Some(trait_ref.def_id),
None,
);
}
}
}
_ => {}
}
};
let call_kind =
call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None);
debug!(?call_kind);
let mut err = match call_kind {
CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
macro_rules! error {
($err:ident) => {
tcx.dcx().create_err(errors::$err {
span,
ty: self_ty,
kind: ccx.const_kind(),
non: "non",
})
};
}
// Don't point at the trait if this is a desugaring...
// FIXME(const_trait_impl): we could perhaps do this for `Iterator`.
match kind {
CallDesugaringKind::ForLoopIntoIter | CallDesugaringKind::ForLoopNext => {
error!(NonConstForLoopIntoIter)
}
CallDesugaringKind::QuestionBranch => {
error!(NonConstQuestionBranch)
}
CallDesugaringKind::QuestionFromResidual => {
error!(NonConstQuestionFromResidual)
}
CallDesugaringKind::TryBlockFromOutput => {
error!(NonConstTryBlockFromOutput)
}
CallDesugaringKind::Await => {
error!(NonConstAwait)
}
}
}
CallKind::FnCall { fn_trait_id, self_ty } => {
let note = match self_ty.kind() {
FnDef(def_id, ..) => {
let span = tcx.def_span(*def_id);
if ccx.tcx.is_const_fn(*def_id) {
span_bug!(span, "calling const FnDef errored when it shouldn't");
}
Some(errors::NonConstClosureNote::FnDef { span })
}
FnPtr(..) => Some(errors::NonConstClosureNote::FnPtr),
Closure(..) => Some(errors::NonConstClosureNote::Closure),
_ => None,
};
let mut err = tcx.dcx().create_err(errors::NonConstClosure {
span,
kind: ccx.const_kind(),
note,
non: "non",
});
note_trait_if_possible(&mut err, self_ty, fn_trait_id);
err
}
CallKind::Operator { trait_id, self_ty, .. } => {
let mut err = if let CallSource::MatchCmp = call_source {
tcx.dcx().create_err(errors::NonConstMatchEq {
span,
kind: ccx.const_kind(),
ty: self_ty,
non: "non",
})
} else {
let mut sugg = None;
if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
match (args[0].unpack(), args[1].unpack()) {
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
if self_ty == rhs_ty
&& self_ty.is_ref()
&& self_ty.peel_refs().is_primitive() =>
{
let mut num_refs = 0;
let mut tmp_ty = self_ty;
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
num_refs += 1;
tmp_ty = *inner_ty;
}
let deref = "*".repeat(num_refs);
if let Ok(call_str) =
ccx.tcx.sess.source_map().span_to_snippet(span)
{
if let Some(eq_idx) = call_str.find("==") {
if let Some(rhs_idx) = call_str[(eq_idx + 2)..]
.find(|c: char| !c.is_whitespace())
{
let rhs_pos = span.lo()
+ BytePos::from_usize(eq_idx + 2 + rhs_idx);
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
sugg = Some(errors::ConsiderDereferencing {
deref,
span: span.shrink_to_lo(),
rhs_span,
});
}
}
}
ty::Adt(..) => {
let (infcx, param_env) =
tcx.infer_ctxt().build_with_typing_env(ccx.typing_env);
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
let mut selcx = SelectionContext::new(&infcx);
let implsrc = selcx.select(&obligation);
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
// FIXME(const_trait_impl) revisit this
if !tcx.is_const_trait_impl(data.impl_def_id) {
let span = tcx.def_span(data.impl_def_id);
err.subdiagnostic(errors::NonConstImplNote { span });
}
_ => {}
}
}
tcx.dcx().create_err(errors::NonConstOperator {
span,
kind: ccx.const_kind(),
sugg,
non: "non",
})
};
note_trait_if_possible(&mut err, self_ty, trait_id);
err
}
CallKind::DerefCoercion { deref_target, deref_target_ty, self_ty } => {
// Check first whether the source is accessible (issue #87060)
let target = if tcx.sess.source_map().is_span_accessible(deref_target) {
Some(deref_target)
} else {
None
};
let mut err = tcx.dcx().create_err(errors::NonConstDerefCoercion {
span,
ty: self_ty,
kind: ccx.const_kind(),
target_ty: deref_target_ty,
deref_target: target,
non: "non",
});
note_trait_if_possible(&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(), non: "non" })
}
_ => ccx.dcx().create_err(errors::NonConstFnCall {
span,
def_descr: ccx.tcx.def_descr(callee),
def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
kind: ccx.const_kind(),
non: "non",
}),
};
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);
@ -338,6 +189,190 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
}
}
/// Build an error message reporting that a function call is not const (or only
/// conditionally const). In case that this call is desugared (like an operator
/// or sugar from something like a `for` loop), try to build a better error message
/// that doesn't call it a method.
fn build_error_for_const_call<'tcx>(
ccx: &ConstCx<'_, 'tcx>,
callee: DefId,
args: ty::GenericArgsRef<'tcx>,
span: Span,
call_source: CallSource,
non_or_conditionally: &'static str,
note_trait_if_possible: impl FnOnce(&mut Diag<'tcx>, Ty<'tcx>, DefId),
) -> Diag<'tcx> {
let tcx = ccx.tcx;
let call_kind =
call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None);
debug!(?call_kind);
let mut err = match call_kind {
CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
macro_rules! error {
($err:ident) => {
tcx.dcx().create_err(errors::$err {
span,
ty: self_ty,
kind: ccx.const_kind(),
non_or_conditionally,
})
};
}
// Don't point at the trait if this is a desugaring...
// FIXME(const_trait_impl): we could perhaps do this for `Iterator`.
match kind {
CallDesugaringKind::ForLoopIntoIter | CallDesugaringKind::ForLoopNext => {
error!(NonConstForLoopIntoIter)
}
CallDesugaringKind::QuestionBranch => {
error!(NonConstQuestionBranch)
}
CallDesugaringKind::QuestionFromResidual => {
error!(NonConstQuestionFromResidual)
}
CallDesugaringKind::TryBlockFromOutput => {
error!(NonConstTryBlockFromOutput)
}
CallDesugaringKind::Await => {
error!(NonConstAwait)
}
}
}
CallKind::FnCall { fn_trait_id, self_ty } => {
let note = match self_ty.kind() {
FnDef(def_id, ..) => {
let span = tcx.def_span(*def_id);
if ccx.tcx.is_const_fn(*def_id) {
span_bug!(span, "calling const FnDef errored when it shouldn't");
}
Some(errors::NonConstClosureNote::FnDef { span })
}
FnPtr(..) => Some(errors::NonConstClosureNote::FnPtr),
Closure(..) => Some(errors::NonConstClosureNote::Closure),
_ => None,
};
let mut err = tcx.dcx().create_err(errors::NonConstClosure {
span,
kind: ccx.const_kind(),
note,
non_or_conditionally,
});
note_trait_if_possible(&mut err, self_ty, fn_trait_id);
err
}
CallKind::Operator { trait_id, self_ty, .. } => {
let mut err = if let CallSource::MatchCmp = call_source {
tcx.dcx().create_err(errors::NonConstMatchEq {
span,
kind: ccx.const_kind(),
ty: self_ty,
non_or_conditionally,
})
} else {
let mut sugg = None;
if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
match (args[0].unpack(), args[1].unpack()) {
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
if self_ty == rhs_ty
&& self_ty.is_ref()
&& self_ty.peel_refs().is_primitive() =>
{
let mut num_refs = 0;
let mut tmp_ty = self_ty;
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
num_refs += 1;
tmp_ty = *inner_ty;
}
let deref = "*".repeat(num_refs);
if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
if let Some(eq_idx) = call_str.find("==") {
if let Some(rhs_idx) =
call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
{
let rhs_pos =
span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
sugg = Some(errors::ConsiderDereferencing {
deref,
span: span.shrink_to_lo(),
rhs_span,
});
}
}
}
}
_ => {}
}
}
tcx.dcx().create_err(errors::NonConstOperator {
span,
kind: ccx.const_kind(),
sugg,
non_or_conditionally,
})
};
note_trait_if_possible(&mut err, self_ty, trait_id);
err
}
CallKind::DerefCoercion { deref_target, deref_target_ty, self_ty } => {
// Check first whether the source is accessible (issue #87060)
let target = if tcx.sess.source_map().is_span_accessible(deref_target) {
Some(deref_target)
} else {
None
};
let mut err = tcx.dcx().create_err(errors::NonConstDerefCoercion {
span,
ty: self_ty,
kind: ccx.const_kind(),
target_ty: deref_target_ty,
deref_target: target,
non_or_conditionally,
});
note_trait_if_possible(
&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(),
non_or_conditionally,
})
}
_ => ccx.dcx().create_err(errors::NonConstFnCall {
span,
def_descr: ccx.tcx.def_descr(callee),
def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
kind: ccx.const_kind(),
non_or_conditionally,
}),
};
err.note(format!(
"calls in {}s are limited to constant functions, \
tuple structs and tuple variants",
ccx.const_kind(),
));
err
}
/// A call to an `#[unstable]` const fn or `#[rustc_const_unstable]` function.
///
/// Contains the name of the feature that would allow the use of this function.

View file

@ -174,17 +174,7 @@ pub(crate) struct NonConstFmtMacroCall {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
pub non: &'static str,
}
#[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,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -195,7 +185,7 @@ pub(crate) struct NonConstFnCall {
pub def_path_str: String,
pub def_descr: &'static str,
pub kind: ConstContext,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -302,7 +292,7 @@ pub struct NonConstMatchEq<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
pub kind: ConstContext,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -312,7 +302,7 @@ pub struct NonConstForLoopIntoIter<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
pub kind: ConstContext,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -322,7 +312,7 @@ pub struct NonConstQuestionBranch<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
pub kind: ConstContext,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -332,7 +322,7 @@ pub struct NonConstQuestionFromResidual<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
pub kind: ConstContext,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -342,7 +332,7 @@ pub struct NonConstTryBlockFromOutput<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
pub kind: ConstContext,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -352,7 +342,7 @@ pub struct NonConstAwait<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
pub kind: ConstContext,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -363,7 +353,7 @@ pub struct NonConstClosure {
pub kind: ConstContext,
#[subdiagnostic]
pub note: Option<NonConstClosureNote>,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Subdiagnostic)]
@ -397,7 +387,7 @@ pub struct NonConstOperator {
pub kind: ConstContext,
#[subdiagnostic]
pub sugg: Option<ConsiderDereferencing>,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
@ -411,7 +401,7 @@ pub struct NonConstDerefCoercion<'tcx> {
pub target_ty: Ty<'tcx>,
#[note(const_eval_target_note)]
pub deref_target: Option<Span>,
pub non: &'static str,
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]

View file

@ -2,7 +2,7 @@ struct A;
struct B;
static S: &'static B = &A;
//~^ ERROR cannot call conditionally-const method
//~^ ERROR cannot perform conditionally-const deref coercion
use std::ops::Deref;

View file

@ -1,13 +1,19 @@
error[E0658]: cannot call conditionally-const method `<A as Deref>::deref` in statics
error[E0658]: cannot perform conditionally-const deref coercion on `A` in statics
--> $DIR/issue-25901.rs:4:24
|
LL | static S: &'static B = &A;
| ^^
|
= note: attempting to deref into `B`
note: deref defined here
--> $DIR/issue-25901.rs:10:5
|
LL | type Target = B;
| ^^^^^^^^^^^
= note: calls in statics 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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -4,10 +4,10 @@ error[E0658]: cannot call conditionally-const method `<R as Deref>::deref` in co
LL | self.0
| ^^^^^^
|
= 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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0493]: destructor of `R` cannot be evaluated at compile-time
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:43

View file

@ -1,13 +1,13 @@
error[E0658]: cannot call conditionally-const method `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:22:5
--> $DIR/cross-crate.rs:22:11
|
LL | Const.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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -1,24 +1,24 @@
error[E0658]: cannot call conditionally-const method `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:19:5
--> $DIR/cross-crate.rs:19:14
|
LL | NonConst.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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0658]: cannot call conditionally-const method `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:22:5
--> $DIR/cross-crate.rs:22:11
|
LL | Const.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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors

View file

@ -4,10 +4,10 @@ error[E0658]: cannot call conditionally-const associated function `<staged_api::
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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 1 previous error

View file

@ -39,15 +39,15 @@ LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)]
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: cannot call conditionally-const method `<T as Foo>::a` in constant functions
--> $DIR/super-traits-fail-3.rs:36:5
--> $DIR/super-traits-fail-3.rs:36:7
|
LL | x.a();
| ^^^^^
| ^^^
|
= 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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 5 previous errors

View file

@ -39,15 +39,15 @@ LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)]
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: cannot call conditionally-const method `<T as Foo>::a` in constant functions
--> $DIR/super-traits-fail-3.rs:36:5
--> $DIR/super-traits-fail-3.rs:36:7
|
LL | x.a();
| ^^^^^
| ^^^
|
= 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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 5 previous errors