1
Fork 0
Simplify match statement

Add multiple tests
- 1 test for checking `N + 1 + 1` does not unify with `N+1`
- 2 tests for checking that a function that uses two parameters only returns the parameter that
  is actually used.
- Check exact repeat predicates
This commit is contained in:
kadmin 2022-12-21 21:53:52 +00:00
parent 7c5cb73735
commit 21c5ffe008
8 changed files with 133 additions and 25 deletions

View file

@ -186,8 +186,9 @@ fn satisfied_from_param_env<'tcx>(
Some(Ok(o)) if o == c => Some(Ok(c)), Some(Ok(o)) if o == c => Some(Ok(c)),
Some(_) => Some(Err(())), Some(_) => Some(Err(())),
}; };
ControlFlow::CONTINUE }
} else if let ty::ConstKind::Expr(e) = c.kind() {
if let ty::ConstKind::Expr(e) = c.kind() {
e.visit_with(self) e.visit_with(self)
} else { } else {
// FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s substs. // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s substs.
@ -208,35 +209,20 @@ fn satisfied_from_param_env<'tcx>(
match pred.kind().skip_binder() { match pred.kind().skip_binder() {
ty::PredicateKind::ConstEvaluatable(ce) => { ty::PredicateKind::ConstEvaluatable(ce) => {
let b_ct = tcx.expand_abstract_consts(ce); let b_ct = tcx.expand_abstract_consts(ce);
let mut v = Visitor { ct, infcx, param_env, single_match: None }; let mut v = Visitor { ct, infcx, param_env, single_match };
let _ = b_ct.visit_with(&mut v); let _ = b_ct.visit_with(&mut v);
if let Some(inner) = v.single_match { single_match = v.single_match;
single_match = if let Ok(inner) = inner {
match single_match {
None => Some(Ok(inner)),
Some(Ok(prev)) if prev == inner => Some(Ok(prev)),
Some(_) => Some(Err(())),
}
} else {
Some(Err(()))
};
}
} }
_ => {} // don't care _ => {} // don't care
} }
} }
if let Some(Ok(c)) = single_match { if let Some(Ok(c)) = single_match {
let is_ok = infcx let ocx = ObligationCtxt::new(infcx);
.commit_if_ok(|_| { assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
let ocx = ObligationCtxt::new_in_snapshot(infcx); assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok()); assert!(ocx.select_all_or_error().is_empty());
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(()) }
})
.is_ok();
assert!(is_ok);
return true; return true;
} }

View 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() {}

View 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

View 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() {}

View file

@ -15,8 +15,8 @@ where
[(); (L - 1) + 1 + L]:, [(); (L - 1) + 1 + L]:,
{ {
foo::<_, L>([(); L + 1 + L]); foo::<_, L>([(); L + 1 + L]);
//~^ ERROR: unconstrained generic constant //~^ ERROR: mismatched types
//~| ERROR: mismatched types //~^^ ERROR: unconstrained generic constant
} }
fn main() {} fn main() {}

View 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() {}

View 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() {}

View 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`.