Change based on comments
Instead of just switching to a probe, check for different matches, and see how many there are. If one, unify it, otherwise return true and let it be unified later.
This commit is contained in:
parent
abe040d876
commit
77b61379b6
3 changed files with 38 additions and 8 deletions
|
@ -168,7 +168,9 @@ fn satisfied_from_param_env<'tcx>(
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
||||||
infcx: &'a InferCtxt<'tcx>,
|
infcx: &'a InferCtxt<'tcx>,
|
||||||
|
single_match: Option<Result<ty::Const<'tcx>, ()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
|
impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
|
||||||
type BreakTy = ();
|
type BreakTy = ();
|
||||||
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
@ -179,7 +181,9 @@ fn satisfied_from_param_env<'tcx>(
|
||||||
&& ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
|
&& ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
|
||||||
&& ocx.select_all_or_error().is_empty()
|
&& ocx.select_all_or_error().is_empty()
|
||||||
}) {
|
}) {
|
||||||
ControlFlow::BREAK
|
self.single_match =
|
||||||
|
if self.single_match.is_none() { Some(Ok(c)) } else { Some(Err(())) };
|
||||||
|
ControlFlow::CONTINUE
|
||||||
} else if let ty::ConstKind::Expr(e) = c.kind() {
|
} else if let ty::ConstKind::Expr(e) = c.kind() {
|
||||||
e.visit_with(self)
|
e.visit_with(self)
|
||||||
} else {
|
} else {
|
||||||
|
@ -195,22 +199,37 @@ fn satisfied_from_param_env<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut single_match: Option<Result<ty::Const<'tcx>, ()>> = None;
|
||||||
|
|
||||||
for pred in param_env.caller_bounds() {
|
for pred in param_env.caller_bounds() {
|
||||||
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 };
|
let mut v = Visitor { ct, infcx, param_env, single_match: None };
|
||||||
let result = b_ct.visit_with(&mut v);
|
let _ = b_ct.visit_with(&mut v);
|
||||||
|
if let Some(inner) = v.single_match {
|
||||||
if let ControlFlow::Break(()) = result {
|
single_match = if single_match.is_none() { Some(inner) } else { Some(Err(())) };
|
||||||
debug!("is_const_evaluatable: yes");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {} // don't care
|
_ => {} // don't care
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(c) = single_match {
|
||||||
|
if let Ok(c) = c {
|
||||||
|
let is_ok = infcx
|
||||||
|
.commit_if_ok(|_| {
|
||||||
|
let ocx = ObligationCtxt::new_in_snapshot(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());
|
||||||
|
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(()) }
|
||||||
|
})
|
||||||
|
.is_ok();
|
||||||
|
assert!(is_ok);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
debug!("is_const_evaluatable: no");
|
debug!("is_const_evaluatable: no");
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ where
|
||||||
{
|
{
|
||||||
foo::<_, L>([(); L + 1 + L]);
|
foo::<_, L>([(); L + 1 + L]);
|
||||||
//~^ ERROR: unconstrained generic constant
|
//~^ ERROR: unconstrained generic constant
|
||||||
|
//~| ERROR: mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/wf_obligation.rs:17:17
|
||||||
|
|
|
||||||
|
LL | foo::<_, L>([(); L + 1 + L]);
|
||||||
|
| ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L`
|
||||||
|
|
|
||||||
|
= note: expected constant `N + 1 + M`
|
||||||
|
found constant `L + 1 + L`
|
||||||
|
|
||||||
error: unconstrained generic constant
|
error: unconstrained generic constant
|
||||||
--> $DIR/wf_obligation.rs:17:22
|
--> $DIR/wf_obligation.rs:17:22
|
||||||
|
|
|
|
||||||
|
@ -6,5 +15,6 @@ LL | foo::<_, L>([(); L + 1 + L]);
|
||||||
|
|
|
|
||||||
= help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
|
= help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue