Skip to content

Commit 3304b62

Browse files
authored
Unrolled build for rust-lang#134638
Rollup merge of rust-lang#134638 - compiler-errors:fx-item-bounds, r=lcnr Fix effect predicates from item bounds in old solver r? lcnr
2 parents f334342 + 535bc78 commit 3304b62

13 files changed

+201
-77
lines changed

compiler/rustc_trait_selection/src/traits/effects.rs

+137-28
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use rustc_hir as hir;
2-
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt};
2+
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
33
use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
44
use rustc_middle::span_bug;
55
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
66
use rustc_middle::ty::{self, TypingMode};
7+
use rustc_type_ir::elaborate::elaborate;
78
use rustc_type_ir::solve::NoSolution;
8-
use thin_vec::ThinVec;
9+
use thin_vec::{ThinVec, thin_vec};
910

1011
use super::SelectionContext;
12+
use super::normalize::normalize_with_depth_to;
1113

1214
pub type HostEffectObligation<'tcx> = Obligation<'tcx, ty::HostEffectPredicate<'tcx>>;
1315

@@ -38,6 +40,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
3840
Err(EvaluationFailure::NoSolution) => {}
3941
}
4042

43+
match evaluate_host_effect_from_item_bounds(selcx, obligation) {
44+
Ok(result) => return Ok(result),
45+
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
46+
Err(EvaluationFailure::NoSolution) => {}
47+
}
48+
4149
match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
4250
Ok(result) => return Ok(result),
4351
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
@@ -48,24 +56,45 @@ pub fn evaluate_host_effect_obligation<'tcx>(
4856
}
4957

5058
fn match_candidate<'tcx>(
51-
infcx: &InferCtxt<'tcx>,
59+
selcx: &mut SelectionContext<'_, 'tcx>,
5260
obligation: &HostEffectObligation<'tcx>,
5361
candidate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
62+
candidate_is_unnormalized: bool,
63+
more_nested: impl FnOnce(&mut SelectionContext<'_, 'tcx>, &mut ThinVec<PredicateObligation<'tcx>>),
5464
) -> Result<ThinVec<PredicateObligation<'tcx>>, NoSolution> {
5565
if !candidate.skip_binder().constness.satisfies(obligation.predicate.constness) {
5666
return Err(NoSolution);
5767
}
5868

59-
let candidate = infcx.instantiate_binder_with_fresh_vars(
69+
let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars(
6070
obligation.cause.span,
6171
BoundRegionConversionTime::HigherRankedType,
6272
candidate,
6373
);
6474

65-
let mut nested = infcx
66-
.at(&obligation.cause, obligation.param_env)
67-
.eq(DefineOpaqueTypes::Yes, obligation.predicate.trait_ref, candidate.trait_ref)?
68-
.into_obligations();
75+
let mut nested = thin_vec![];
76+
77+
// Unlike param-env bounds, item bounds may not be normalized.
78+
if candidate_is_unnormalized {
79+
candidate = normalize_with_depth_to(
80+
selcx,
81+
obligation.param_env,
82+
obligation.cause.clone(),
83+
obligation.recursion_depth,
84+
candidate,
85+
&mut nested,
86+
);
87+
}
88+
89+
nested.extend(
90+
selcx
91+
.infcx
92+
.at(&obligation.cause, obligation.param_env)
93+
.eq(DefineOpaqueTypes::Yes, obligation.predicate.trait_ref, candidate.trait_ref)?
94+
.into_obligations(),
95+
);
96+
97+
more_nested(selcx, &mut nested);
6998

7099
for nested in &mut nested {
71100
nested.set_depth_from_parent(obligation.recursion_depth);
@@ -82,36 +111,116 @@ fn evaluate_host_effect_from_bounds<'tcx>(
82111
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
83112
let mut candidate = None;
84113

85-
for predicate in obligation.param_env.caller_bounds() {
86-
let bound_predicate = predicate.kind();
87-
if let ty::ClauseKind::HostEffect(data) = predicate.kind().skip_binder() {
88-
let data = bound_predicate.rebind(data);
89-
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
90-
continue;
114+
for clause in obligation.param_env.caller_bounds() {
115+
let bound_clause = clause.kind();
116+
let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
117+
continue;
118+
};
119+
let data = bound_clause.rebind(data);
120+
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
121+
continue;
122+
}
123+
124+
if !drcx
125+
.args_may_unify(obligation.predicate.trait_ref.args, data.skip_binder().trait_ref.args)
126+
{
127+
continue;
128+
}
129+
130+
let is_match =
131+
infcx.probe(|_| match_candidate(selcx, obligation, data, false, |_, _| {}).is_ok());
132+
133+
if is_match {
134+
if candidate.is_some() {
135+
return Err(EvaluationFailure::Ambiguous);
136+
} else {
137+
candidate = Some(data);
91138
}
139+
}
140+
}
92141

93-
if !drcx.args_may_unify(
94-
obligation.predicate.trait_ref.args,
95-
data.skip_binder().trait_ref.args,
142+
if let Some(data) = candidate {
143+
Ok(match_candidate(selcx, obligation, data, false, |_, _| {})
144+
.expect("candidate matched before, so it should match again"))
145+
} else {
146+
Err(EvaluationFailure::NoSolution)
147+
}
148+
}
149+
150+
fn evaluate_host_effect_from_item_bounds<'tcx>(
151+
selcx: &mut SelectionContext<'_, 'tcx>,
152+
obligation: &HostEffectObligation<'tcx>,
153+
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
154+
let infcx = selcx.infcx;
155+
let tcx = infcx.tcx;
156+
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
157+
let mut candidate = None;
158+
159+
let mut consider_ty = obligation.predicate.self_ty();
160+
while let ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) = *consider_ty.kind() {
161+
if tcx.is_conditionally_const(alias_ty.def_id) {
162+
for clause in elaborate(
163+
tcx,
164+
tcx.explicit_implied_const_bounds(alias_ty.def_id)
165+
.iter_instantiated_copied(tcx, alias_ty.args)
166+
.map(|(trait_ref, _)| {
167+
trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness)
168+
}),
96169
) {
97-
continue;
98-
}
170+
let bound_clause = clause.kind();
171+
let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
172+
unreachable!("should not elaborate non-HostEffect from HostEffect")
173+
};
174+
let data = bound_clause.rebind(data);
175+
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
176+
continue;
177+
}
99178

100-
let is_match = infcx.probe(|_| match_candidate(infcx, obligation, data).is_ok());
179+
if !drcx.args_may_unify(
180+
obligation.predicate.trait_ref.args,
181+
data.skip_binder().trait_ref.args,
182+
) {
183+
continue;
184+
}
101185

102-
if is_match {
103-
if candidate.is_some() {
104-
return Err(EvaluationFailure::Ambiguous);
105-
} else {
106-
candidate = Some(data);
186+
let is_match = infcx
187+
.probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok());
188+
189+
if is_match {
190+
if candidate.is_some() {
191+
return Err(EvaluationFailure::Ambiguous);
192+
} else {
193+
candidate = Some((data, alias_ty));
194+
}
107195
}
108196
}
109197
}
198+
199+
if kind != ty::Projection {
200+
break;
201+
}
202+
203+
consider_ty = alias_ty.self_ty();
110204
}
111205

112-
if let Some(data) = candidate {
113-
Ok(match_candidate(infcx, obligation, data)
114-
.expect("candidate matched before, so it should match again"))
206+
if let Some((data, alias_ty)) = candidate {
207+
Ok(match_candidate(selcx, obligation, data, true, |selcx, nested| {
208+
// An alias bound only holds if we also check the const conditions
209+
// of the alias, so we need to register those, too.
210+
let const_conditions = normalize_with_depth_to(
211+
selcx,
212+
obligation.param_env,
213+
obligation.cause.clone(),
214+
obligation.recursion_depth,
215+
tcx.const_conditions(alias_ty.def_id).instantiate(tcx, alias_ty.args),
216+
nested,
217+
);
218+
nested.extend(const_conditions.into_iter().map(|(trait_ref, _)| {
219+
obligation
220+
.with(tcx, trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness))
221+
}));
222+
})
223+
.expect("candidate matched before, so it should match again"))
115224
} else {
116225
Err(EvaluationFailure::NoSolution)
117226
}

tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//@ compile-flags: -Znext-solver
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
23
//@ check-pass
34

45
#![feature(const_trait_impl)]

tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
//@ compile-flags: -Znext-solver
2-
//@ known-bug: unknown
1+
//@ check-pass
32

43
#![feature(const_trait_impl, generic_const_exprs)]
54
#![allow(incomplete_features)]

tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr

-35
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `U: ~const Other` is not satisfied
2+
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
3+
|
4+
LL | T::Assoc::<U>::func();
5+
| ^^^^^^^^^^^^^
6+
7+
error[E0277]: the trait bound `U: ~const Other` is not satisfied
8+
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
9+
|
10+
LL | <T as Trait>::Assoc::<U>::func();
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0277`.

tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
2-
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:23:5
2+
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
33
|
44
LL | T::Assoc::<U>::func();
55
| ^^^^^^^^^^^^^
66

77
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
8-
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:25:5
8+
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
99
|
1010
LL | <T as Trait>::Assoc::<U>::func();
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//@ compile-flags: -Znext-solver
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
23

34
// Check that `~const` item bounds only hold if the where clauses on the
45
// associated type are also const.
@@ -21,9 +22,11 @@ trait Other {}
2122

2223
const fn fails<T: ~const Trait, U: Other>() {
2324
T::Assoc::<U>::func();
24-
//~^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
25+
//[current]~^ ERROR the trait bound `U: ~const Other` is not satisfied
26+
//[next]~^^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
2527
<T as Trait>::Assoc::<U>::func();
26-
//~^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
28+
//[current]~^ ERROR the trait bound `U: ~const Other` is not satisfied
29+
//[next]~^^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
2730
}
2831

2932
const fn works<T: ~const Trait, U: ~const Other>() {

tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
2-
--> $DIR/assoc-type-const-bound-usage-fail.rs:16:5
2+
--> $DIR/assoc-type-const-bound-usage-fail.rs:17:5
33
|
44
LL | T::Assoc::func();
55
| ^^^^^^^^
66

77
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
8-
--> $DIR/assoc-type-const-bound-usage-fail.rs:18:5
8+
--> $DIR/assoc-type-const-bound-usage-fail.rs:19:5
99
|
1010
LL | <T as Trait>::Assoc::func();
1111
| ^^^^^^^^^^^^^^^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
2+
--> $DIR/assoc-type-const-bound-usage-fail.rs:17:5
3+
|
4+
LL | T::Assoc::func();
5+
| ^^^^^^^^
6+
7+
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
8+
--> $DIR/assoc-type-const-bound-usage-fail.rs:19:5
9+
|
10+
LL | <T as Trait>::Assoc::func();
11+
| ^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0277`.

tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//@ compile-flags: -Znext-solver
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
23

34
// Check that `~const` item bounds only hold if the parent trait is `~const`.
45
// i.e. check that we validate the const conditions for the associated type

tests/ui/traits/const-traits/assoc-type.stderr tests/ui/traits/const-traits/assoc-type.current.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
2-
--> $DIR/assoc-type.rs:36:16
2+
--> $DIR/assoc-type.rs:37:16
33
|
44
LL | type Bar = NonConstAdd;
55
| ^^^^^^^^^^^
66
|
77
note: required by a bound in `Foo::Bar`
8-
--> $DIR/assoc-type.rs:32:15
8+
--> $DIR/assoc-type.rs:33:15
99
|
1010
LL | type Bar: ~const Add;
1111
| ^^^^^^ required by this bound in `Foo::Bar`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
2+
--> $DIR/assoc-type.rs:37:16
3+
|
4+
LL | type Bar = NonConstAdd;
5+
| ^^^^^^^^^^^
6+
|
7+
note: required by a bound in `Foo::Bar`
8+
--> $DIR/assoc-type.rs:33:15
9+
|
10+
LL | type Bar: ~const Add;
11+
| ^^^^^^ required by this bound in `Foo::Bar`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.

tests/ui/traits/const-traits/assoc-type.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//@ compile-flags: -Znext-solver
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
23

34
#![feature(const_trait_impl)]
45

0 commit comments

Comments
 (0)