Skip to content

Commit 77b6137

Browse files
committed
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.
1 parent abe040d commit 77b6137

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,9 @@ 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> {
@@ -179,7 +181,9 @@ fn satisfied_from_param_env<'tcx>(
179181
&& ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
180182
&& ocx.select_all_or_error().is_empty()
181183
}) {
182-
ControlFlow::BREAK
184+
self.single_match =
185+
if self.single_match.is_none() { Some(Ok(c)) } else { Some(Err(())) };
186+
ControlFlow::CONTINUE
183187
} else if let ty::ConstKind::Expr(e) = c.kind() {
184188
e.visit_with(self)
185189
} else {
@@ -195,22 +199,37 @@ fn satisfied_from_param_env<'tcx>(
195199
}
196200
}
197201

202+
let mut single_match: Option<Result<ty::Const<'tcx>, ()>> = None;
203+
198204
for pred in param_env.caller_bounds() {
199205
match pred.kind().skip_binder() {
200206
ty::PredicateKind::ConstEvaluatable(ce) => {
201207
let b_ct = tcx.expand_abstract_consts(ce);
202-
let mut v = Visitor { ct, infcx, param_env };
203-
let result = b_ct.visit_with(&mut v);
204-
205-
if let ControlFlow::Break(()) = result {
206-
debug!("is_const_evaluatable: yes");
207-
return true;
208+
let mut v = Visitor { ct, infcx, param_env, single_match: None };
209+
let _ = b_ct.visit_with(&mut v);
210+
if let Some(inner) = v.single_match {
211+
single_match = if single_match.is_none() { Some(inner) } else { Some(Err(())) };
208212
}
209213
}
210214
_ => {} // don't care
211215
}
212216
}
213217

218+
if let Some(c) = single_match {
219+
if let Ok(c) = c {
220+
let is_ok = infcx
221+
.commit_if_ok(|_| {
222+
let ocx = ObligationCtxt::new_in_snapshot(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+
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(()) }
226+
})
227+
.is_ok();
228+
assert!(is_ok);
229+
}
230+
return true;
231+
}
232+
214233
debug!("is_const_evaluatable: no");
215234
false
216235
}

src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ where
1616
{
1717
foo::<_, L>([(); L + 1 + L]);
1818
//~^ ERROR: unconstrained generic constant
19+
//~| ERROR: mismatched types
1920
}
2021

2122
fn main() {}
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/wf_obligation.rs:17:17
3+
|
4+
LL | foo::<_, L>([(); L + 1 + L]);
5+
| ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L`
6+
|
7+
= note: expected constant `N + 1 + M`
8+
found constant `L + 1 + L`
9+
110
error: unconstrained generic constant
211
--> $DIR/wf_obligation.rs:17:22
312
|
@@ -6,5 +15,6 @@ LL | foo::<_, L>([(); L + 1 + L]);
615
|
716
= help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
817

9-
error: aborting due to previous error
18+
error: aborting due to 2 previous errors
1019

20+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)