Skip to content

Commit

Permalink
deal with const_evaluatable_checked in ConstEquate
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed May 19, 2021
1 parent 1773f14 commit 412e040
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 6 deletions.
13 changes: 11 additions & 2 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_errors::ErrorReported;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
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::ToPredicate;
use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
Expand Down Expand Up @@ -591,7 +591,16 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
)
}
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
ProcessResult::Unchanged
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
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),
))
}
}
}
}
Expand Down
24 changes: 23 additions & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::PredicateKind::ConstEquate(c1, c2) => {
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>| {
if let ty::ConstKind::Unevaluated(unevaluated) = c.val {
self.infcx
Expand Down Expand Up @@ -591,7 +608,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
}
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
Ok(EvaluatedToAmbig)
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
Ok(EvaluatedToAmbig)
} else {
// Two different constants using generic parameters ~> error.
Ok(EvaluatedToErr)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ struct Foo<T>(PhantomData<T>);
fn test<T>() -> [u8; size_of::<T>()] {
[0; size_of::<Foo<T>>()]
//~^ ERROR unconstrained generic constant
//~| ERROR mismatched types
}

fn main() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
--> $DIR/different-fn.rs:10:9
|
Expand All @@ -6,5 +15,6 @@ LL | [0; 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`.
Original file line number Diff line number Diff line change
@@ -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() {}
12 changes: 11 additions & 1 deletion src/test/ui/const-generics/issues/issue-62504.full.stderr
Original file line number Diff line number Diff line change
@@ -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
--> $DIR/issue-62504.rs:18:25
|
Expand All @@ -6,5 +15,6 @@ LL | ArrayHolder([0; Self::SIZE])
|
= 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`.
2 changes: 1 addition & 1 deletion src/test/ui/const-generics/issues/issue-62504.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl<const X: usize> ArrayHolder<X> {
pub const fn new() -> Self {
ArrayHolder([0; Self::SIZE])
//~^ ERROR constant expression depends on a generic parameter
//[min]~| ERROR mismatched types
//~| ERROR mismatched types
}
}

Expand Down

0 comments on commit 412e040

Please sign in to comment.