Skip to content

Commit b7587f1

Browse files
authored
Rollup merge of #105292 - JulianKnodt:no_eager_commit, r=BoxyUwU
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 #105037 r? ```@BoxyUwU```
2 parents 89e0576 + 21c5ffe commit b7587f1

10 files changed

+221
-16
lines changed

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+26-16
Original file line numberDiff line numberDiff line change
@@ -168,24 +168,27 @@ fn satisfied_from_param_env<'tcx>(
168168
param_env: ty::ParamEnv<'tcx>,
169169

170170
infcx: &'a InferCtxt<'tcx>,
171+
single_match: Option<Result<ty::Const<'tcx>, ()>>,
171172
}
173+
172174
impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
173175
type BreakTy = ();
174176
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
175177
debug!("is_const_evaluatable: candidate={:?}", c);
176-
if let Ok(()) = self.infcx.commit_if_ok(|_| {
178+
if self.infcx.probe(|_| {
177179
let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
178-
if let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty())
179-
&& let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct)
180+
ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()).is_ok()
181+
&& ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
180182
&& ocx.select_all_or_error().is_empty()
181-
{
182-
Ok(())
183-
} else {
184-
Err(())
185-
}
186183
}) {
187-
ControlFlow::BREAK
188-
} else if let ty::ConstKind::Expr(e) = c.kind() {
184+
self.single_match = match self.single_match {
185+
None => Some(Ok(c)),
186+
Some(Ok(o)) if o == c => Some(Ok(c)),
187+
Some(_) => Some(Err(())),
188+
};
189+
}
190+
191+
if let ty::ConstKind::Expr(e) = c.kind() {
189192
e.visit_with(self)
190193
} else {
191194
// FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s substs.
@@ -200,22 +203,29 @@ fn satisfied_from_param_env<'tcx>(
200203
}
201204
}
202205

206+
let mut single_match: Option<Result<ty::Const<'tcx>, ()>> = None;
207+
203208
for pred in param_env.caller_bounds() {
204209
match pred.kind().skip_binder() {
205210
ty::PredicateKind::ConstEvaluatable(ce) => {
206211
let b_ct = tcx.expand_abstract_consts(ce);
207-
let mut v = Visitor { ct, infcx, param_env };
208-
let result = b_ct.visit_with(&mut v);
212+
let mut v = Visitor { ct, infcx, param_env, single_match };
213+
let _ = b_ct.visit_with(&mut v);
209214

210-
if let ControlFlow::Break(()) = result {
211-
debug!("is_const_evaluatable: yes");
212-
return true;
213-
}
215+
single_match = v.single_match;
214216
}
215217
_ => {} // don't care
216218
}
217219
}
218220

221+
if let Some(Ok(c)) = single_match {
222+
let ocx = ObligationCtxt::new(infcx);
223+
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
224+
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
225+
assert!(ocx.select_all_or_error().is_empty());
226+
return true;
227+
}
228+
219229
debug!("is_const_evaluatable: no");
220230
false
221231
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![feature(generic_const_exprs)]
2+
#![allow(incomplete_features)]
3+
4+
fn foo<const N: usize, const M: usize>() -> [(); N+2]
5+
where
6+
[(); N + 1]:,
7+
[(); M + 1]:,
8+
{
9+
bar()
10+
//~^ ERROR: unconstrained
11+
}
12+
13+
fn bar<const N: usize>() -> [(); N]
14+
where
15+
[(); N + 1]:,
16+
{
17+
[(); N]
18+
}
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: unconstrained generic constant
2+
--> $DIR/ensure_is_evaluatable.rs:9:5
3+
|
4+
LL | bar()
5+
| ^^^
6+
|
7+
= help: try adding a `where` bound using this expression: `where [(); N + 1]:`
8+
note: required by a bound in `bar`
9+
--> $DIR/ensure_is_evaluatable.rs:15:10
10+
|
11+
LL | fn bar<const N: usize>() -> [(); N]
12+
| --- required by a bound in this
13+
LL | where
14+
LL | [(); N + 1]:,
15+
| ^^^^^ required by this bound in `bar`
16+
17+
error: aborting due to previous error
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![feature(generic_const_exprs)]
2+
#![allow(incomplete_features)]
3+
4+
const fn both(_: usize, b: usize) -> usize {
5+
b
6+
}
7+
8+
fn foo<const N: usize, const M: usize>() -> [(); N + 2]
9+
where
10+
[(); both(N + 1, M + 1)]:,
11+
{
12+
bar()
13+
//~^ ERROR: unconstrained generic constant
14+
}
15+
16+
fn bar<const N: usize>() -> [(); N]
17+
where
18+
[(); N + 1]:,
19+
{
20+
[(); N]
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: unconstrained generic constant
2+
--> $DIR/fn_with_two_const_inputs.rs:12:5
3+
|
4+
LL | bar()
5+
| ^^^
6+
|
7+
= help: try adding a `where` bound using this expression: `where [(); N + 1]:`
8+
note: required by a bound in `bar`
9+
--> $DIR/fn_with_two_const_inputs.rs:18:10
10+
|
11+
LL | fn bar<const N: usize>() -> [(); N]
12+
| --- required by a bound in this
13+
LL | where
14+
LL | [(); N + 1]:,
15+
| ^^^^^ required by this bound in `bar`
16+
17+
error: aborting due to previous error
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// check-pass
2+
#![feature(generic_const_exprs)]
3+
#![allow(incomplete_features)]
4+
5+
const fn both(_: usize, b: usize) -> usize {
6+
b
7+
}
8+
9+
fn foo<const N: usize>()
10+
where
11+
[(); both(N + 1, N + 1)]:,
12+
{
13+
bar::<N>();
14+
}
15+
16+
fn bar<const N: usize>()
17+
where
18+
[(); N + 1]:,
19+
{
20+
}
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// run-pass
2+
#![feature(generic_const_exprs)]
3+
#![allow(incomplete_features)]
4+
#![allow(dead_code)]
5+
6+
trait Table<const D: usize>: Sync {
7+
const COLUMNS: usize;
8+
}
9+
10+
struct Table1<const D: usize>;
11+
impl<const D: usize> Table<D> for Table1<D> {
12+
const COLUMNS: usize = 123;
13+
}
14+
15+
struct Table2<const D: usize>;
16+
impl<const D: usize> Table<D> for Table2<D> {
17+
const COLUMNS: usize = 456;
18+
}
19+
20+
fn process_table<T: Table<D>, const D: usize>(_table: T)
21+
where
22+
[(); T::COLUMNS]:,
23+
{
24+
}
25+
26+
fn process_all_tables<const D: usize>()
27+
where
28+
[(); Table2::<D>::COLUMNS]:,
29+
[(); Table1::<D>::COLUMNS]:,
30+
{
31+
process_table(Table1::<D>);
32+
process_table(Table2::<D>);
33+
}
34+
35+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
#![feature(generic_const_exprs)]
3+
#![allow(incomplete_features)]
4+
5+
fn foo<const N: usize>()
6+
where
7+
[(); N + 1]:,
8+
[(); N + 1]:,
9+
{
10+
bar::<N>();
11+
}
12+
13+
fn bar<const N: usize>()
14+
where
15+
[(); N + 1]:,
16+
{
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(generic_const_exprs)]
2+
#![allow(incomplete_features)]
3+
4+
fn foo<const N: usize>()
5+
where
6+
[(); N + 1 + 1]:,
7+
{
8+
bar();
9+
//~^ ERROR: type annotations
10+
}
11+
12+
fn bar<const N: usize>()
13+
where
14+
[(); N + 1]:,
15+
{
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0284]: type annotations needed
2+
--> $DIR/unify_with_nested_expr.rs:8:5
3+
|
4+
LL | bar();
5+
| ^^^ cannot infer the value of the const parameter `N` declared on the function `bar`
6+
|
7+
note: required by a bound in `bar`
8+
--> $DIR/unify_with_nested_expr.rs:14:10
9+
|
10+
LL | fn bar<const N: usize>()
11+
| --- required by a bound in this
12+
LL | where
13+
LL | [(); N + 1]:,
14+
| ^^^^^ required by this bound in `bar`
15+
help: consider specifying the generic argument
16+
|
17+
LL | bar::<N>();
18+
| +++++
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0284`.

0 commit comments

Comments
 (0)