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```
This commit is contained in:
commit
b7587f1867
10 changed files with 221 additions and 16 deletions
|
@ -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.
|
||||
|
@ -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
src/test/ui/const-generics/ensure_is_evaluatable.rs
Normal file
20
src/test/ui/const-generics/ensure_is_evaluatable.rs
Normal file
|
@ -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
src/test/ui/const-generics/ensure_is_evaluatable.stderr
Normal file
18
src/test/ui/const-generics/ensure_is_evaluatable.stderr
Normal file
|
@ -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
src/test/ui/const-generics/fn_with_two_const_inputs.rs
Normal file
23
src/test/ui/const-generics/fn_with_two_const_inputs.rs
Normal file
|
@ -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
src/test/ui/const-generics/fn_with_two_const_inputs.stderr
Normal file
18
src/test/ui/const-generics/fn_with_two_const_inputs.stderr
Normal file
|
@ -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
src/test/ui/const-generics/fn_with_two_same_const_inputs.rs
Normal file
22
src/test/ui/const-generics/fn_with_two_same_const_inputs.rs
Normal file
|
@ -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
src/test/ui/const-generics/issues/issue-105037.rs
Normal file
35
src/test/ui/const-generics/issues/issue-105037.rs
Normal file
|
@ -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
src/test/ui/const-generics/two_matching_preds.rs
Normal file
19
src/test/ui/const-generics/two_matching_preds.rs
Normal file
|
@ -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
src/test/ui/const-generics/unify_with_nested_expr.rs
Normal file
18
src/test/ui/const-generics/unify_with_nested_expr.rs
Normal file
|
@ -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
src/test/ui/const-generics/unify_with_nested_expr.stderr
Normal file
22
src/test/ui/const-generics/unify_with_nested_expr.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Reference in a new issue