Skip to content

Commit 2ce579d

Browse files
authored
Rollup merge of #143235 - compiler-errors:const-item-bound, r=oli-obk
Assemble const bounds via normal item bounds in old solver too Fixes the first example in https://rust-lang.zulipchat.com/#narrow/channel/144729-t-types/topic/elaboration.20of.20const.20bounds.3F/with/526378135 The code duplication here is not that nice, but it's at least very localized. cc `@davidtwco` r? oli-obk
2 parents 383f107 + 4698c92 commit 2ce579d

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

‎compiler/rustc_trait_selection/src/traits/effects.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
4444
Err(EvaluationFailure::NoSolution) => {}
4545
}
4646

47+
match evaluate_host_effect_from_conditionally_const_item_bounds(selcx, obligation) {
48+
Ok(result) => return Ok(result),
49+
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
50+
Err(EvaluationFailure::NoSolution) => {}
51+
}
52+
4753
match evaluate_host_effect_from_item_bounds(selcx, obligation) {
4854
Ok(result) => return Ok(result),
4955
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
@@ -153,7 +159,9 @@ fn evaluate_host_effect_from_bounds<'tcx>(
153159
}
154160
}
155161

156-
fn evaluate_host_effect_from_item_bounds<'tcx>(
162+
/// Assembles constness bounds from `~const` item bounds on alias types, which only
163+
/// hold if the `~const` where bounds also hold and the parent trait is `~const`.
164+
fn evaluate_host_effect_from_conditionally_const_item_bounds<'tcx>(
157165
selcx: &mut SelectionContext<'_, 'tcx>,
158166
obligation: &HostEffectObligation<'tcx>,
159167
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
@@ -232,6 +240,63 @@ fn evaluate_host_effect_from_item_bounds<'tcx>(
232240
}
233241
}
234242

243+
/// Assembles constness bounds "normal" item bounds on aliases, which may include
244+
/// unconditionally `const` bounds that are *not* conditional and thus always hold.
245+
fn evaluate_host_effect_from_item_bounds<'tcx>(
246+
selcx: &mut SelectionContext<'_, 'tcx>,
247+
obligation: &HostEffectObligation<'tcx>,
248+
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
249+
let infcx = selcx.infcx;
250+
let tcx = infcx.tcx;
251+
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
252+
let mut candidate = None;
253+
254+
let mut consider_ty = obligation.predicate.self_ty();
255+
while let ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) = *consider_ty.kind() {
256+
for clause in tcx.item_bounds(alias_ty.def_id).iter_instantiated(tcx, alias_ty.args) {
257+
let bound_clause = clause.kind();
258+
let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
259+
continue;
260+
};
261+
let data = bound_clause.rebind(data);
262+
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
263+
continue;
264+
}
265+
266+
if !drcx.args_may_unify(
267+
obligation.predicate.trait_ref.args,
268+
data.skip_binder().trait_ref.args,
269+
) {
270+
continue;
271+
}
272+
273+
let is_match =
274+
infcx.probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok());
275+
276+
if is_match {
277+
if candidate.is_some() {
278+
return Err(EvaluationFailure::Ambiguous);
279+
} else {
280+
candidate = Some(data);
281+
}
282+
}
283+
}
284+
285+
if kind != ty::Projection {
286+
break;
287+
}
288+
289+
consider_ty = alias_ty.self_ty();
290+
}
291+
292+
if let Some(data) = candidate {
293+
Ok(match_candidate(selcx, obligation, data, true, |_, _| {})
294+
.expect("candidate matched before, so it should match again"))
295+
} else {
296+
Err(EvaluationFailure::NoSolution)
297+
}
298+
}
299+
235300
fn evaluate_host_effect_from_builtin_impls<'tcx>(
236301
selcx: &mut SelectionContext<'_, 'tcx>,
237302
obligation: &HostEffectObligation<'tcx>,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
5+
6+
#![feature(const_trait_impl)]
7+
8+
#[const_trait]
9+
trait Bar {}
10+
11+
trait Baz: const Bar {}
12+
13+
trait Foo {
14+
// Well-formedenss of `Baz` requires `<Self as Foo>::Bar: const Bar`.
15+
// Make sure we assemble a candidate for that via the item bounds.
16+
type Bar: Baz;
17+
}
18+
19+
fn main() {}

0 commit comments

Comments
 (0)