mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #85481 - lcnr:const-equate, r=matthewjasper
deal with `const_evaluatable_checked` in `ConstEquate` Failing to evaluate two constants which do not contain inference variables should not result in ambiguity.
This commit is contained in:
commit
ff2c947c00
@ -6,7 +6,7 @@ use rustc_errors::ErrorReported;
|
|||||||
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
|
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
|
||||||
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
|
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::ty::error::ExpectedFound;
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::ToPredicate;
|
use rustc_middle::ty::ToPredicate;
|
||||||
use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
|
use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
|
||||||
@ -591,7 +591,16 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
|
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
|
||||||
|
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
|
||||||
ProcessResult::Unchanged
|
ProcessResult::Unchanged
|
||||||
|
} else {
|
||||||
|
// Two different constants using generic parameters ~> error.
|
||||||
|
let expected_found = ExpectedFound::new(true, c1, c2);
|
||||||
|
ProcessResult::Error(FulfillmentErrorCode::CodeConstEquateError(
|
||||||
|
expected_found,
|
||||||
|
TypeError::ConstMismatch(expected_found),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,6 +557,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||||
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
|
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
|
||||||
|
|
||||||
|
if self.tcx().features().const_evaluatable_checked {
|
||||||
|
// FIXME: we probably should only try to unify abstract constants
|
||||||
|
// if the constants depend on generic parameters.
|
||||||
|
//
|
||||||
|
// Let's just see where this breaks :shrug:
|
||||||
|
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
|
||||||
|
(c1.val, c2.val)
|
||||||
|
{
|
||||||
|
if self
|
||||||
|
.tcx()
|
||||||
|
.try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs)))
|
||||||
|
{
|
||||||
|
return Ok(EvaluatedToOk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let evaluate = |c: &'tcx ty::Const<'tcx>| {
|
let evaluate = |c: &'tcx ty::Const<'tcx>| {
|
||||||
if let ty::ConstKind::Unevaluated(unevaluated) = c.val {
|
if let ty::ConstKind::Unevaluated(unevaluated) = c.val {
|
||||||
self.infcx
|
self.infcx
|
||||||
@ -591,7 +608,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
|
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
|
||||||
|
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
|
||||||
Ok(EvaluatedToAmbig)
|
Ok(EvaluatedToAmbig)
|
||||||
|
} else {
|
||||||
|
// Two different constants using generic parameters ~> error.
|
||||||
|
Ok(EvaluatedToErr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ struct Foo<T>(PhantomData<T>);
|
|||||||
fn test<T>() -> [u8; size_of::<T>()] {
|
fn test<T>() -> [u8; size_of::<T>()] {
|
||||||
[0; size_of::<Foo<T>>()]
|
[0; size_of::<Foo<T>>()]
|
||||||
//~^ ERROR unconstrained generic constant
|
//~^ ERROR unconstrained generic constant
|
||||||
|
//~| ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/different-fn.rs:10:5
|
||||||
|
|
|
||||||
|
LL | [0; size_of::<Foo<T>>()]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::<T>()`, found `size_of::<Foo<T>>()`
|
||||||
|
|
|
||||||
|
= note: expected type `size_of::<T>()`
|
||||||
|
found type `size_of::<Foo<T>>()`
|
||||||
|
|
||||||
error: unconstrained generic constant
|
error: unconstrained generic constant
|
||||||
--> $DIR/different-fn.rs:10:9
|
--> $DIR/different-fn.rs:10:9
|
||||||
|
|
|
|
||||||
@ -6,5 +15,6 @@ LL | [0; size_of::<Foo<T>>()]
|
|||||||
|
|
|
|
||||||
= help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:`
|
= help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
// check-pass
|
||||||
|
|
||||||
|
// We previously always returned ambiguity when equating generic consts, even if they
|
||||||
|
// only contain generic parameters. This is incorrect as trying to unify `N > 1` with `M > 1`
|
||||||
|
// should fail.
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(const_generics, const_evaluatable_checked)]
|
||||||
|
|
||||||
|
enum Assert<const COND: bool> {}
|
||||||
|
trait IsTrue {}
|
||||||
|
impl IsTrue for Assert<true> {}
|
||||||
|
|
||||||
|
struct Foo<const N: usize, const M: usize>;
|
||||||
|
trait Bar<const N: usize, const M: usize> {}
|
||||||
|
impl<const N: usize, const M: usize> Bar<N, M> for Foo<N, M>
|
||||||
|
where
|
||||||
|
Assert<{ N > 1 }>: IsTrue,
|
||||||
|
Assert<{ M > 1 }>: IsTrue,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -1,3 +1,12 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-62504.rs:18:21
|
||||||
|
|
|
||||||
|
LL | ArrayHolder([0; Self::SIZE])
|
||||||
|
| ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
|
||||||
|
|
|
||||||
|
= note: expected type `X`
|
||||||
|
found type `Self::SIZE`
|
||||||
|
|
||||||
error: constant expression depends on a generic parameter
|
error: constant expression depends on a generic parameter
|
||||||
--> $DIR/issue-62504.rs:18:25
|
--> $DIR/issue-62504.rs:18:25
|
||||||
|
|
|
|
||||||
@ -6,5 +15,6 @@ LL | ArrayHolder([0; Self::SIZE])
|
|||||||
|
|
|
|
||||||
= note: this may fail depending on what value the parameter takes
|
= note: this may fail depending on what value the parameter takes
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
@ -17,7 +17,7 @@ impl<const X: usize> ArrayHolder<X> {
|
|||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
ArrayHolder([0; Self::SIZE])
|
ArrayHolder([0; Self::SIZE])
|
||||||
//~^ ERROR constant expression depends on a generic parameter
|
//~^ ERROR constant expression depends on a generic parameter
|
||||||
//[min]~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user