Do not consider traits that have unsatisfied const conditions to be conditionally const
This commit is contained in:
parent
8c39ce5b4f
commit
2669f2a7c7
6 changed files with 34 additions and 26 deletions
|
@ -35,6 +35,12 @@ use crate::errors;
|
||||||
type QualifResults<'mir, 'tcx, Q> =
|
type QualifResults<'mir, 'tcx, Q> =
|
||||||
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
enum ConstConditionsHold {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct Qualifs<'mir, 'tcx> {
|
pub(crate) struct Qualifs<'mir, 'tcx> {
|
||||||
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
|
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
|
||||||
|
@ -376,15 +382,15 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
||||||
callee: DefId,
|
callee: DefId,
|
||||||
callee_args: ty::GenericArgsRef<'tcx>,
|
callee_args: ty::GenericArgsRef<'tcx>,
|
||||||
call_span: Span,
|
call_span: Span,
|
||||||
) -> bool {
|
) -> Option<ConstConditionsHold> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
if !tcx.is_conditionally_const(callee) {
|
if !tcx.is_conditionally_const(callee) {
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
|
let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
|
||||||
if const_conditions.is_empty() {
|
if const_conditions.is_empty() {
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx));
|
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx));
|
||||||
|
@ -413,12 +419,13 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if errors.is_empty() {
|
||||||
|
Some(ConstConditionsHold::Yes)
|
||||||
|
} else {
|
||||||
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");
|
||||||
|
Some(ConstConditionsHold::No)
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_drop_terminator(
|
pub fn check_drop_terminator(
|
||||||
|
@ -706,7 +713,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
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);
|
||||||
|
|
||||||
if trait_is_const {
|
// Only consider a trait to be const if the const conditions hold.
|
||||||
|
// Otherwise, it's really misleading to call something "conditionally"
|
||||||
|
// const when it's very obviously not conditionally const.
|
||||||
|
if trait_is_const && has_const_conditions == Some(ConstConditionsHold::Yes) {
|
||||||
// Trait calls are always conditionally-const.
|
// Trait calls are always conditionally-const.
|
||||||
self.check_op(ops::ConditionallyConstCall {
|
self.check_op(ops::ConditionallyConstCall {
|
||||||
callee,
|
callee,
|
||||||
|
@ -730,7 +740,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even if we know the callee, ensure we can use conditionally-const calls.
|
// Even if we know the callee, ensure we can use conditionally-const calls.
|
||||||
if has_const_conditions {
|
if has_const_conditions.is_some() {
|
||||||
self.check_op(ops::ConditionallyConstCall {
|
self.check_op(ops::ConditionallyConstCall {
|
||||||
callee,
|
callee,
|
||||||
args: fn_args,
|
args: fn_args,
|
||||||
|
|
|
@ -2,7 +2,7 @@ struct A;
|
||||||
struct B;
|
struct B;
|
||||||
|
|
||||||
static S: &'static B = &A;
|
static S: &'static B = &A;
|
||||||
//~^ ERROR cannot perform conditionally-const deref coercion
|
//~^ ERROR cannot perform non-const deref coercion
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0658]: cannot perform conditionally-const deref coercion on `A` in statics
|
error[E0015]: cannot perform non-const deref coercion on `A` in statics
|
||||||
--> $DIR/issue-25901.rs:4:24
|
--> $DIR/issue-25901.rs:4:24
|
||||||
|
|
|
|
||||||
LL | static S: &'static B = &A;
|
LL | static S: &'static B = &A;
|
||||||
|
@ -10,11 +10,14 @@ note: deref defined here
|
||||||
|
|
|
|
||||||
LL | type Target = B;
|
LL | type Target = B;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
note: impl defined here, but it is not `const`
|
||||||
|
--> $DIR/issue-25901.rs:9:1
|
||||||
|
|
|
||||||
|
LL | impl Deref for A {
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
= 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
|
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0015`.
|
||||||
|
|
|
@ -11,7 +11,7 @@ impl Foo {
|
||||||
//~^ ERROR invalid generic `self` parameter type
|
//~^ ERROR invalid generic `self` parameter type
|
||||||
//~| ERROR destructor of `R` cannot be evaluated at compile-time
|
//~| ERROR destructor of `R` cannot be evaluated at compile-time
|
||||||
self.0
|
self.0
|
||||||
//~^ ERROR cannot perform conditionally-const deref coercion on `R` in constant functions
|
//~^ ERROR cannot perform non-const deref coercion on `R` in constant functions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0658]: cannot perform conditionally-const deref coercion on `R` in constant functions
|
error[E0015]: cannot perform non-const deref coercion on `R` in constant functions
|
||||||
--> $DIR/arbitrary-self-from-method-substs-ice.rs:13:9
|
--> $DIR/arbitrary-self-from-method-substs-ice.rs:13:9
|
||||||
|
|
|
|
||||||
LL | self.0
|
LL | self.0
|
||||||
|
@ -6,9 +6,6 @@ LL | self.0
|
||||||
|
|
|
|
||||||
= note: attempting to deref into `Foo`
|
= note: attempting to deref into `Foo`
|
||||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
= 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
|
|
||||||
|
|
||||||
error[E0493]: destructor of `R` cannot be evaluated at compile-time
|
error[E0493]: destructor of `R` cannot be evaluated at compile-time
|
||||||
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:43
|
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:43
|
||||||
|
@ -30,5 +27,5 @@ LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0493, E0658, E0801.
|
Some errors have detailed explanations: E0015, E0493, E0801.
|
||||||
For more information about an error, try `rustc --explain E0493`.
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
error[E0658]: cannot call conditionally-const method `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
|
error[E0015]: cannot call non-const method `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
|
||||||
--> $DIR/cross-crate.rs:19:14
|
--> $DIR/cross-crate.rs:19:14
|
||||||
|
|
|
|
||||||
LL | NonConst.func();
|
LL | NonConst.func();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
= 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
|
|
||||||
|
|
||||||
error[E0658]: cannot call conditionally-const method `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
|
error[E0658]: cannot call conditionally-const method `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
|
||||||
--> $DIR/cross-crate.rs:22:11
|
--> $DIR/cross-crate.rs:22:11
|
||||||
|
@ -22,4 +19,5 @@ LL | Const.func();
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
Some errors have detailed explanations: E0015, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue