Skip to content

Commit

Permalink
Rollup merge of rust-lang#105292 - JulianKnodt:no_eager_commit, r=Box…
Browse files Browse the repository at this point in the history
…yUwU

Change a commit_if_ok call to probe

Removes an over-eager `commit_if_ok` which makes inference worse.

I'm not entirely sure whether it's ok to remove the check that types are the same, because casting seems to cause equality checks with incorrect types?

Fixes rust-lang#105037

r? `@BoxyUwU`
  • Loading branch information
Yuki Okushi authored Jan 9, 2023
2 parents c54c8cb + 21c5ffe commit 4f8a55c
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 16 deletions.
42 changes: 26 additions & 16 deletions compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,24 +168,27 @@ fn satisfied_from_param_env<'tcx>(
param_env: ty::ParamEnv<'tcx>,

infcx: &'a InferCtxt<'tcx>,
single_match: Option<Result<ty::Const<'tcx>, ()>>,
}

impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
type BreakTy = ();
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("is_const_evaluatable: candidate={:?}", c);
if let Ok(()) = self.infcx.commit_if_ok(|_| {
if self.infcx.probe(|_| {
let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
if let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty())
&& let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct)
ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()).is_ok()
&& ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
&& ocx.select_all_or_error().is_empty()
{
Ok(())
} else {
Err(())
}
}) {
ControlFlow::BREAK
} else if let ty::ConstKind::Expr(e) = c.kind() {
self.single_match = match self.single_match {
None => Some(Ok(c)),
Some(Ok(o)) if o == c => Some(Ok(c)),
Some(_) => Some(Err(())),
};
}

if let ty::ConstKind::Expr(e) = c.kind() {
e.visit_with(self)
} else {
// FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s substs.
Expand All @@ -200,22 +203,29 @@ fn satisfied_from_param_env<'tcx>(
}
}

let mut single_match: Option<Result<ty::Const<'tcx>, ()>> = None;

for pred in param_env.caller_bounds() {
match pred.kind().skip_binder() {
ty::PredicateKind::ConstEvaluatable(ce) => {
let b_ct = tcx.expand_abstract_consts(ce);
let mut v = Visitor { ct, infcx, param_env };
let result = b_ct.visit_with(&mut v);
let mut v = Visitor { ct, infcx, param_env, single_match };
let _ = b_ct.visit_with(&mut v);

if let ControlFlow::Break(()) = result {
debug!("is_const_evaluatable: yes");
return true;
}
single_match = v.single_match;
}
_ => {} // don't care
}
}

if let Some(Ok(c)) = single_match {
let ocx = ObligationCtxt::new(infcx);
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
assert!(ocx.select_all_or_error().is_empty());
return true;
}

debug!("is_const_evaluatable: no");
false
}
20 changes: 20 additions & 0 deletions src/test/ui/const-generics/ensure_is_evaluatable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

fn foo<const N: usize, const M: usize>() -> [(); N+2]
where
[(); N + 1]:,
[(); M + 1]:,
{
bar()
//~^ ERROR: unconstrained
}

fn bar<const N: usize>() -> [(); N]
where
[(); N + 1]:,
{
[(); N]
}

fn main() {}
18 changes: 18 additions & 0 deletions src/test/ui/const-generics/ensure_is_evaluatable.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: unconstrained generic constant
--> $DIR/ensure_is_evaluatable.rs:9:5
|
LL | bar()
| ^^^
|
= help: try adding a `where` bound using this expression: `where [(); N + 1]:`
note: required by a bound in `bar`
--> $DIR/ensure_is_evaluatable.rs:15:10
|
LL | fn bar<const N: usize>() -> [(); N]
| --- required by a bound in this
LL | where
LL | [(); N + 1]:,
| ^^^^^ required by this bound in `bar`

error: aborting due to previous error

23 changes: 23 additions & 0 deletions src/test/ui/const-generics/fn_with_two_const_inputs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

const fn both(_: usize, b: usize) -> usize {
b
}

fn foo<const N: usize, const M: usize>() -> [(); N + 2]
where
[(); both(N + 1, M + 1)]:,
{
bar()
//~^ ERROR: unconstrained generic constant
}

fn bar<const N: usize>() -> [(); N]
where
[(); N + 1]:,
{
[(); N]
}

fn main() {}
18 changes: 18 additions & 0 deletions src/test/ui/const-generics/fn_with_two_const_inputs.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: unconstrained generic constant
--> $DIR/fn_with_two_const_inputs.rs:12:5
|
LL | bar()
| ^^^
|
= help: try adding a `where` bound using this expression: `where [(); N + 1]:`
note: required by a bound in `bar`
--> $DIR/fn_with_two_const_inputs.rs:18:10
|
LL | fn bar<const N: usize>() -> [(); N]
| --- required by a bound in this
LL | where
LL | [(); N + 1]:,
| ^^^^^ required by this bound in `bar`

error: aborting due to previous error

22 changes: 22 additions & 0 deletions src/test/ui/const-generics/fn_with_two_same_const_inputs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

const fn both(_: usize, b: usize) -> usize {
b
}

fn foo<const N: usize>()
where
[(); both(N + 1, N + 1)]:,
{
bar::<N>();
}

fn bar<const N: usize>()
where
[(); N + 1]:,
{
}

fn main() {}
35 changes: 35 additions & 0 deletions src/test/ui/const-generics/issues/issue-105037.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// run-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
#![allow(dead_code)]

trait Table<const D: usize>: Sync {
const COLUMNS: usize;
}

struct Table1<const D: usize>;
impl<const D: usize> Table<D> for Table1<D> {
const COLUMNS: usize = 123;
}

struct Table2<const D: usize>;
impl<const D: usize> Table<D> for Table2<D> {
const COLUMNS: usize = 456;
}

fn process_table<T: Table<D>, const D: usize>(_table: T)
where
[(); T::COLUMNS]:,
{
}

fn process_all_tables<const D: usize>()
where
[(); Table2::<D>::COLUMNS]:,
[(); Table1::<D>::COLUMNS]:,
{
process_table(Table1::<D>);
process_table(Table2::<D>);
}

fn main() {}
19 changes: 19 additions & 0 deletions src/test/ui/const-generics/two_matching_preds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

fn foo<const N: usize>()
where
[(); N + 1]:,
[(); N + 1]:,
{
bar::<N>();
}

fn bar<const N: usize>()
where
[(); N + 1]:,
{
}

fn main() {}
18 changes: 18 additions & 0 deletions src/test/ui/const-generics/unify_with_nested_expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

fn foo<const N: usize>()
where
[(); N + 1 + 1]:,
{
bar();
//~^ ERROR: type annotations
}

fn bar<const N: usize>()
where
[(); N + 1]:,
{
}

fn main() {}
22 changes: 22 additions & 0 deletions src/test/ui/const-generics/unify_with_nested_expr.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0284]: type annotations needed
--> $DIR/unify_with_nested_expr.rs:8:5
|
LL | bar();
| ^^^ cannot infer the value of the const parameter `N` declared on the function `bar`
|
note: required by a bound in `bar`
--> $DIR/unify_with_nested_expr.rs:14:10
|
LL | fn bar<const N: usize>()
| --- required by a bound in this
LL | where
LL | [(); N + 1]:,
| ^^^^^ required by this bound in `bar`
help: consider specifying the generic argument
|
LL | bar::<N>();
| +++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0284`.

0 comments on commit 4f8a55c

Please sign in to comment.