Auto merge of #132276 - compiler-errors:enforce-fx-in-mir, r=fee1-dead
Double-check conditional constness in MIR To prevent any unchecked `~const` bounds from leaking through during MIR lowering. If this check fails, it will eventually just delay a bug, but for now it reports errors. That error reporting may be redundant if we're calling it from code that already doesn't allow `~const` (i.e. when the `effects` and `const_trait_impl` gates are disabled), but I don't think it's that big of a deal. edit: This also makes sure that we issue a const stability error if we encounter *any* function with const conditions when `const_trait_impl` is not enabled. This ensures that that feature remains airtight.
This commit is contained in:
commit
705cfe0e96
@ -11,7 +11,6 @@
|
|||||||
use rustc_hir::{self as hir, LangItem};
|
use rustc_hir::{self as hir, LangItem};
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_infer::traits::ObligationCause;
|
|
||||||
use rustc_middle::mir::visit::Visitor;
|
use rustc_middle::mir::visit::Visitor;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
@ -20,9 +19,11 @@
|
|||||||
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;
|
||||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
use rustc_span::{Span, Symbol, sym};
|
||||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
|
use rustc_trait_selection::traits::{
|
||||||
|
Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
|
||||||
|
};
|
||||||
use tracing::{debug, instrument, trace};
|
use tracing::{debug, instrument, trace};
|
||||||
|
|
||||||
use super::ops::{self, NonConstOp, Status};
|
use super::ops::{self, NonConstOp, Status};
|
||||||
@ -360,6 +361,73 @@ fn place_may_escape(&mut self, place: &Place<'_>) -> bool {
|
|||||||
// end of evaluation.
|
// end of evaluation.
|
||||||
!is_transient
|
!is_transient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn revalidate_conditional_constness(
|
||||||
|
&mut self,
|
||||||
|
callee: DefId,
|
||||||
|
callee_args: ty::GenericArgsRef<'tcx>,
|
||||||
|
call_source: CallSource,
|
||||||
|
call_span: Span,
|
||||||
|
) {
|
||||||
|
let tcx = self.tcx;
|
||||||
|
if !tcx.is_conditionally_const(callee) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
|
||||||
|
// If there are any const conditions on this fn and `const_trait_impl`
|
||||||
|
// is not enabled, simply bail. We shouldn't be able to call conditionally
|
||||||
|
// 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 ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||||
|
|
||||||
|
let body_id = self.body.source.def_id().expect_local();
|
||||||
|
let host_polarity = match self.const_kind() {
|
||||||
|
hir::ConstContext::ConstFn => ty::BoundConstness::Maybe,
|
||||||
|
hir::ConstContext::Static(_) | hir::ConstContext::Const { .. } => {
|
||||||
|
ty::BoundConstness::Const
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let const_conditions = ocx.normalize(
|
||||||
|
&ObligationCause::misc(call_span, body_id),
|
||||||
|
self.param_env,
|
||||||
|
const_conditions,
|
||||||
|
);
|
||||||
|
ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, span)| {
|
||||||
|
Obligation::new(
|
||||||
|
tcx,
|
||||||
|
ObligationCause::new(
|
||||||
|
call_span,
|
||||||
|
body_id,
|
||||||
|
ObligationCauseCode::WhereClause(callee, span),
|
||||||
|
),
|
||||||
|
self.param_env,
|
||||||
|
trait_ref.to_host_effect_clause(tcx, host_polarity),
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
|
||||||
|
let errors = ocx.select_all_or_error();
|
||||||
|
if !errors.is_empty() {
|
||||||
|
// FIXME(effects): Soon this should be unconditionally delaying a bug.
|
||||||
|
if matches!(call_source, CallSource::Normal) && tcx.features().effects() {
|
||||||
|
tcx.dcx()
|
||||||
|
.span_delayed_bug(call_span, "this should have reported a ~const error in HIR");
|
||||||
|
} else {
|
||||||
|
infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
@ -566,7 +634,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
|
|||||||
};
|
};
|
||||||
|
|
||||||
let ConstCx { tcx, body, param_env, .. } = *self.ccx;
|
let ConstCx { tcx, body, param_env, .. } = *self.ccx;
|
||||||
let caller = self.def_id();
|
|
||||||
|
|
||||||
let fn_ty = func.ty(body, tcx);
|
let fn_ty = func.ty(body, tcx);
|
||||||
|
|
||||||
@ -584,31 +651,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check that all trait bounds that are marked as `~const` can be satisfied.
|
self.revalidate_conditional_constness(callee, fn_args, call_source, *fn_span);
|
||||||
//
|
|
||||||
// Typeck only does a "non-const" check since it operates on HIR and cannot distinguish
|
|
||||||
// which path expressions are getting called on and which path expressions are only used
|
|
||||||
// as function pointers. This is required for correctness.
|
|
||||||
let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
|
|
||||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
|
||||||
|
|
||||||
let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
|
|
||||||
let cause = ObligationCause::new(
|
|
||||||
terminator.source_info.span,
|
|
||||||
self.body.source.def_id().expect_local(),
|
|
||||||
ObligationCauseCode::WhereClause(callee, DUMMY_SP),
|
|
||||||
);
|
|
||||||
let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
|
|
||||||
ocx.register_obligations(traits::predicates_for_generics(
|
|
||||||
|_, _| cause.clone(),
|
|
||||||
self.param_env,
|
|
||||||
normalized_predicates,
|
|
||||||
));
|
|
||||||
|
|
||||||
let errors = ocx.select_all_or_error();
|
|
||||||
if !errors.is_empty() {
|
|
||||||
infcx.err_ctxt().report_fulfillment_errors(errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut is_trait = false;
|
let mut is_trait = false;
|
||||||
// Attempting to call a trait method?
|
// Attempting to call a trait method?
|
||||||
@ -648,7 +691,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
self.check_op(ops::FnCallNonConst {
|
self.check_op(ops::FnCallNonConst {
|
||||||
caller,
|
|
||||||
callee,
|
callee,
|
||||||
args: fn_args,
|
args: fn_args,
|
||||||
span: *fn_span,
|
span: *fn_span,
|
||||||
@ -738,7 +780,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
|
|||||||
// Trait functions are not `const fn` so we have to skip them here.
|
// Trait functions are not `const fn` so we have to skip them here.
|
||||||
if !tcx.is_const_fn(callee) && !is_trait {
|
if !tcx.is_const_fn(callee) && !is_trait {
|
||||||
self.check_op(ops::FnCallNonConst {
|
self.check_op(ops::FnCallNonConst {
|
||||||
caller,
|
|
||||||
callee,
|
callee,
|
||||||
args: fn_args,
|
args: fn_args,
|
||||||
span: *fn_span,
|
span: *fn_span,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
//! Concrete error types for all operations which may be invalid in a certain const context.
|
//! 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 hir::{ConstContext, LangItem};
|
||||||
use rustc_errors::Diag;
|
use rustc_errors::Diag;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
@ -74,7 +73,6 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
|||||||
/// 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> {
|
||||||
pub caller: LocalDefId,
|
|
||||||
pub callee: DefId,
|
pub callee: DefId,
|
||||||
pub args: GenericArgsRef<'tcx>,
|
pub args: GenericArgsRef<'tcx>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -87,8 +85,9 @@ 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 { caller, callee, args, span, call_source, feature } = *self;
|
let FnCallNonConst { callee, args, span, call_source, feature } = *self;
|
||||||
let ConstCx { tcx, param_env, body, .. } = *ccx;
|
let ConstCx { tcx, param_env, .. } = *ccx;
|
||||||
|
let caller = ccx.def_id();
|
||||||
|
|
||||||
let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
|
let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
|
||||||
let trait_ref = TraitRef::from_method(tcx, trait_id, args);
|
let trait_ref = TraitRef::from_method(tcx, trait_id, args);
|
||||||
@ -116,7 +115,7 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
|
|||||||
let obligation =
|
let obligation =
|
||||||
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
|
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
|
||||||
|
|
||||||
let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
|
let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx));
|
||||||
let mut selcx = SelectionContext::new(&infcx);
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
let implsrc = selcx.select(&obligation);
|
let implsrc = selcx.select(&obligation);
|
||||||
|
|
||||||
@ -289,7 +288,7 @@ macro_rules! error {
|
|||||||
if let Some(feature) = feature {
|
if let Some(feature) = feature {
|
||||||
ccx.tcx.disabled_nightly_features(
|
ccx.tcx.disabled_nightly_features(
|
||||||
&mut err,
|
&mut err,
|
||||||
body.source.def_id().as_local().map(|local| ccx.tcx.local_def_id_to_hir_id(local)),
|
Some(ccx.tcx.local_def_id_to_hir_id(caller)),
|
||||||
[(String::new(), feature)],
|
[(String::new(), feature)],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,12 @@ LL | const fn check<T: ~const Destruct>(_: T) {}
|
|||||||
| |
|
| |
|
||||||
| the destructor for this type cannot be evaluated in constant functions
|
| the destructor for this type cannot be evaluated in constant functions
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `T: ~const A` is not satisfied
|
||||||
|
--> $DIR/const-drop-fail-2.rs:41:9
|
||||||
|
|
|
||||||
|
LL | T::a();
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
|
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
|
||||||
--> $DIR/const-drop-fail-2.rs:41:9
|
--> $DIR/const-drop-fail-2.rs:41:9
|
||||||
|
|
|
|
||||||
@ -41,7 +47,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
|
|||||||
LL + #![feature(effects)]
|
LL + #![feature(effects)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0015, E0493.
|
Some errors have detailed explanations: E0015, E0277, E0493.
|
||||||
For more information about an error, try `rustc --explain E0015`.
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
@ -78,6 +78,12 @@ error[E0493]: destructor of `T` cannot be evaluated at compile-time
|
|||||||
LL | const fn a<T: ~const Destruct>(_: T) {}
|
LL | const fn a<T: ~const Destruct>(_: T) {}
|
||||||
| ^ the destructor for this type cannot be evaluated in constant functions
|
| ^ the destructor for this type cannot be evaluated in constant functions
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied
|
||||||
|
--> $DIR/const-drop.rs:69:13
|
||||||
|
|
|
||||||
|
LL | T::foo();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
|
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
|
||||||
--> $DIR/const-drop.rs:69:13
|
--> $DIR/const-drop.rs:69:13
|
||||||
|
|
|
|
||||||
@ -90,7 +96,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
|
|||||||
LL + #![feature(effects)]
|
LL + #![feature(effects)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0015, E0277, E0493.
|
Some errors have detailed explanations: E0015, E0277, E0493.
|
||||||
For more information about an error, try `rustc --explain E0015`.
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
@ -80,6 +80,12 @@ LL | const fn a<T: ~const Destruct>(_: T) {}
|
|||||||
| |
|
| |
|
||||||
| the destructor for this type cannot be evaluated in constant functions
|
| the destructor for this type cannot be evaluated in constant functions
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied
|
||||||
|
--> $DIR/const-drop.rs:69:13
|
||||||
|
|
|
||||||
|
LL | T::foo();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
|
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
|
||||||
--> $DIR/const-drop.rs:69:13
|
--> $DIR/const-drop.rs:69:13
|
||||||
|
|
|
|
||||||
@ -92,7 +98,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
|
|||||||
LL + #![feature(effects)]
|
LL + #![feature(effects)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0015, E0277, E0493.
|
Some errors have detailed explanations: E0015, E0277, E0493.
|
||||||
For more information about an error, try `rustc --explain E0015`.
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
@ -18,10 +18,11 @@ const fn const_context() {
|
|||||||
#[cfg(any(stocknc, gatednc))]
|
#[cfg(any(stocknc, gatednc))]
|
||||||
NonConst.func();
|
NonConst.func();
|
||||||
//[stocknc]~^ ERROR: cannot call
|
//[stocknc]~^ ERROR: cannot call
|
||||||
//[gatednc]~^^ ERROR: the trait bound
|
//[stocknc]~| ERROR: cannot call
|
||||||
|
//[gatednc]~^^^ ERROR: the trait bound
|
||||||
Const.func();
|
Const.func();
|
||||||
//[stock]~^ ERROR: cannot call
|
//[stock,stocknc]~^ ERROR: cannot call
|
||||||
//[stocknc]~^^ ERROR: cannot call
|
//[stock,stocknc]~| ERROR: cannot call
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
|
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
|
||||||
--> $DIR/cross-crate.rs:22:11
|
--> $DIR/cross-crate.rs:23:11
|
||||||
|
|
|
|
||||||
LL | Const.func();
|
LL | Const.func();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
@ -10,6 +10,19 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
|||||||
LL + #![feature(const_trait_impl)]
|
LL + #![feature(const_trait_impl)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
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();
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= 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`.
|
For more information about this error, try `rustc --explain E0015`.
|
||||||
|
@ -10,8 +10,21 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
|||||||
LL + #![feature(const_trait_impl)]
|
LL + #![feature(const_trait_impl)]
|
||||||
|
|
|
|
||||||
|
|
||||||
|
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
|
||||||
|
--> $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: 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
|
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
|
||||||
--> $DIR/cross-crate.rs:22:11
|
--> $DIR/cross-crate.rs:23:11
|
||||||
|
|
|
|
||||||
LL | Const.func();
|
LL | Const.func();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
@ -22,6 +35,19 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
|||||||
LL + #![feature(const_trait_impl)]
|
LL + #![feature(const_trait_impl)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
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();
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= 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`.
|
For more information about this error, try `rustc --explain E0015`.
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//@ known-bug: #110395
|
|
||||||
//@ check-pass
|
|
||||||
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
@ -13,7 +10,7 @@ const fn foo<T>() where T: ~const Tr {}
|
|||||||
pub trait Foo {
|
pub trait Foo {
|
||||||
fn foo() {
|
fn foo() {
|
||||||
foo::<()>();
|
foo::<()>();
|
||||||
//FIXME ~^ ERROR the trait bound `(): Tr` is not satisfied
|
//~^ ERROR the trait bound `(): ~const Tr` is not satisfied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
|
||||||
|
--> $DIR/default-method-body-is-const-body-checking.rs:12:9
|
||||||
|
|
|
||||||
|
LL | foo::<()>();
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: required by a bound in `foo`
|
||||||
|
--> $DIR/default-method-body-is-const-body-checking.rs:7:28
|
||||||
|
|
|
||||||
|
LL | const fn foo<T>() where T: ~const Tr {}
|
||||||
|
| ^^^^^^ required by this bound in `foo`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
@ -1,3 +1,9 @@
|
|||||||
|
error[E0277]: the trait bound `T: ~const A` is not satisfied
|
||||||
|
--> $DIR/specializing-constness-2.rs:27:5
|
||||||
|
|
|
||||||
|
LL | <T as A>::a();
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
|
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
|
||||||
--> $DIR/specializing-constness-2.rs:27:5
|
--> $DIR/specializing-constness-2.rs:27:5
|
||||||
|
|
|
|
||||||
@ -10,6 +16,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
|
|||||||
LL + #![feature(effects)]
|
LL + #![feature(effects)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
Some errors have detailed explanations: E0015, E0277.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
@ -11,6 +11,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 non-const fn `<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() {}
|
||||||
|
@ -10,6 +10,19 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
|||||||
LL + #![feature(const_trait_impl)]
|
LL + #![feature(const_trait_impl)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0015]: cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
|
||||||
|
--> $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`.
|
For more information about this error, try `rustc --explain E0015`.
|
||||||
|
Loading…
Reference in New Issue
Block a user