Skip to content

Commit ff2c947

Browse files
committed
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.
2 parents fbf1b1a + 412e040 commit ff2c947

File tree

7 files changed

+80
-6
lines changed

7 files changed

+80
-6
lines changed

compiler/rustc_trait_selection/src/traits/fulfill.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::ErrorReported;
66
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
77
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
88
use rustc_middle::mir::interpret::ErrorHandled;
9-
use rustc_middle::ty::error::ExpectedFound;
9+
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1010
use rustc_middle::ty::subst::SubstsRef;
1111
use rustc_middle::ty::ToPredicate;
1212
use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
@@ -591,7 +591,16 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
591591
)
592592
}
593593
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
594-
ProcessResult::Unchanged
594+
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
595+
ProcessResult::Unchanged
596+
} else {
597+
// Two different constants using generic parameters ~> error.
598+
let expected_found = ExpectedFound::new(true, c1, c2);
599+
ProcessResult::Error(FulfillmentErrorCode::CodeConstEquateError(
600+
expected_found,
601+
TypeError::ConstMismatch(expected_found),
602+
))
603+
}
595604
}
596605
}
597606
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
557557
ty::PredicateKind::ConstEquate(c1, c2) => {
558558
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
559559

560+
if self.tcx().features().const_evaluatable_checked {
561+
// FIXME: we probably should only try to unify abstract constants
562+
// if the constants depend on generic parameters.
563+
//
564+
// Let's just see where this breaks :shrug:
565+
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
566+
(c1.val, c2.val)
567+
{
568+
if self
569+
.tcx()
570+
.try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs)))
571+
{
572+
return Ok(EvaluatedToOk);
573+
}
574+
}
575+
}
576+
560577
let evaluate = |c: &'tcx ty::Const<'tcx>| {
561578
if let ty::ConstKind::Unevaluated(unevaluated) = c.val {
562579
self.infcx
@@ -591,7 +608,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
591608
)
592609
}
593610
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
594-
Ok(EvaluatedToAmbig)
611+
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
612+
Ok(EvaluatedToAmbig)
613+
} else {
614+
// Two different constants using generic parameters ~> error.
615+
Ok(EvaluatedToErr)
616+
}
595617
}
596618
}
597619
}

src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ struct Foo<T>(PhantomData<T>);
99
fn test<T>() -> [u8; size_of::<T>()] {
1010
[0; size_of::<Foo<T>>()]
1111
//~^ ERROR unconstrained generic constant
12+
//~| ERROR mismatched types
1213
}
1314

1415
fn main() {
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/different-fn.rs:10:5
3+
|
4+
LL | [0; size_of::<Foo<T>>()]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::<T>()`, found `size_of::<Foo<T>>()`
6+
|
7+
= note: expected type `size_of::<T>()`
8+
found type `size_of::<Foo<T>>()`
9+
110
error: unconstrained generic constant
211
--> $DIR/different-fn.rs:10:9
312
|
@@ -6,5 +15,6 @@ LL | [0; size_of::<Foo<T>>()]
615
|
716
= help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:`
817

9-
error: aborting due to previous error
18+
error: aborting due to 2 previous errors
1019

20+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// check-pass
2+
3+
// We previously always returned ambiguity when equating generic consts, even if they
4+
// only contain generic parameters. This is incorrect as trying to unify `N > 1` with `M > 1`
5+
// should fail.
6+
#![allow(incomplete_features)]
7+
#![feature(const_generics, const_evaluatable_checked)]
8+
9+
enum Assert<const COND: bool> {}
10+
trait IsTrue {}
11+
impl IsTrue for Assert<true> {}
12+
13+
struct Foo<const N: usize, const M: usize>;
14+
trait Bar<const N: usize, const M: usize> {}
15+
impl<const N: usize, const M: usize> Bar<N, M> for Foo<N, M>
16+
where
17+
Assert<{ N > 1 }>: IsTrue,
18+
Assert<{ M > 1 }>: IsTrue,
19+
{
20+
}
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-62504.rs:18:21
3+
|
4+
LL | ArrayHolder([0; Self::SIZE])
5+
| ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
6+
|
7+
= note: expected type `X`
8+
found type `Self::SIZE`
9+
110
error: constant expression depends on a generic parameter
211
--> $DIR/issue-62504.rs:18:25
312
|
@@ -6,5 +15,6 @@ LL | ArrayHolder([0; Self::SIZE])
615
|
716
= note: this may fail depending on what value the parameter takes
817

9-
error: aborting due to previous error
18+
error: aborting due to 2 previous errors
1019

20+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/const-generics/issues/issue-62504.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl<const X: usize> ArrayHolder<X> {
1717
pub const fn new() -> Self {
1818
ArrayHolder([0; Self::SIZE])
1919
//~^ ERROR constant expression depends on a generic parameter
20-
//[min]~| ERROR mismatched types
20+
//~| ERROR mismatched types
2121
}
2222
}
2323

0 commit comments

Comments
 (0)