Skip to content

Commit 3c6d34f

Browse files
Rollup merge of #132118 - compiler-errors:tilde-const-item-bounds, r=lcnr
Add support for `~const` item bounds Supports the only missing capability of `~const` associated types that I can think of now (this is obviously excluding `~const` opaques, which I see as an extension to this; I'll probably do that next). r? ``@lcnr`` mostly b/c it changes candidate assembly, or reassign cc ``@fee1-dead``
2 parents 7782b0d + 3bad501 commit 3c6d34f

11 files changed

+191
-25
lines changed

Diff for: compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ where
100100
})
101101
}
102102

103+
/// Assemble additional assumptions for an alias that are not included
104+
/// in the item bounds of the alias. For now, this is limited to the
105+
/// `implied_const_bounds` for an associated type.
106+
fn consider_additional_alias_assumptions(
107+
ecx: &mut EvalCtxt<'_, D>,
108+
goal: Goal<I, Self>,
109+
alias_ty: ty::AliasTy<I>,
110+
) -> Vec<Candidate<I>>;
111+
103112
fn consider_impl_candidate(
104113
ecx: &mut EvalCtxt<'_, D>,
105114
goal: Goal<I, Self>,
@@ -594,6 +603,8 @@ where
594603
));
595604
}
596605

606+
candidates.extend(G::consider_additional_alias_assumptions(self, goal, alias_ty));
607+
597608
if kind != ty::Projection {
598609
return;
599610
}

Diff for: compiler/rustc_next_trait_solver/src/solve/effect_goals.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use rustc_type_ir::fast_reject::DeepRejectCtxt;
55
use rustc_type_ir::inherent::*;
6-
use rustc_type_ir::{self as ty, Interner};
6+
use rustc_type_ir::{self as ty, Interner, elaborate};
77
use tracing::instrument;
88

99
use super::assembly::Candidate;
@@ -70,6 +70,55 @@ where
7070
}
7171
}
7272

73+
/// Register additional assumptions for aliases corresponding to `~const` item bounds.
74+
///
75+
/// Unlike item bounds, they are not simply implied by the well-formedness of the alias.
76+
/// Instead, they only hold if the const conditons on the alias also hold. This is why
77+
/// we also register the const conditions of the alias after matching the goal against
78+
/// the assumption.
79+
fn consider_additional_alias_assumptions(
80+
ecx: &mut EvalCtxt<'_, D>,
81+
goal: Goal<I, Self>,
82+
alias_ty: ty::AliasTy<I>,
83+
) -> Vec<Candidate<I>> {
84+
let cx = ecx.cx();
85+
let mut candidates = vec![];
86+
87+
// FIXME(effects): We elaborate here because the implied const bounds
88+
// aren't necessarily elaborated. We probably should prefix this query
89+
// with `explicit_`...
90+
for clause in elaborate::elaborate(
91+
cx,
92+
cx.implied_const_bounds(alias_ty.def_id)
93+
.iter_instantiated(cx, alias_ty.args)
94+
.map(|trait_ref| trait_ref.to_host_effect_clause(cx, goal.predicate.host)),
95+
) {
96+
candidates.extend(Self::probe_and_match_goal_against_assumption(
97+
ecx,
98+
CandidateSource::AliasBound,
99+
goal,
100+
clause,
101+
|ecx| {
102+
// Const conditions must hold for the implied const bound to hold.
103+
ecx.add_goals(
104+
GoalSource::Misc,
105+
cx.const_conditions(alias_ty.def_id)
106+
.iter_instantiated(cx, alias_ty.args)
107+
.map(|trait_ref| {
108+
goal.with(
109+
cx,
110+
trait_ref.to_host_effect_clause(cx, goal.predicate.host),
111+
)
112+
}),
113+
);
114+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
115+
},
116+
));
117+
}
118+
119+
candidates
120+
}
121+
73122
fn consider_impl_candidate(
74123
ecx: &mut EvalCtxt<'_, D>,
75124
goal: Goal<I, Self>,

Diff for: compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,14 @@ where
193193
}
194194
}
195195

196+
fn consider_additional_alias_assumptions(
197+
_ecx: &mut EvalCtxt<'_, D>,
198+
_goal: Goal<I, Self>,
199+
_alias_ty: ty::AliasTy<I>,
200+
) -> Vec<Candidate<I>> {
201+
vec![]
202+
}
203+
196204
fn consider_impl_candidate(
197205
ecx: &mut EvalCtxt<'_, D>,
198206
goal: Goal<I, NormalizesTo<I>>,

Diff for: compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ where
3939
self.def_id()
4040
}
4141

42+
fn consider_additional_alias_assumptions(
43+
_ecx: &mut EvalCtxt<'_, D>,
44+
_goal: Goal<I, Self>,
45+
_alias_ty: ty::AliasTy<I>,
46+
) -> Vec<Candidate<I>> {
47+
vec![]
48+
}
49+
4250
fn consider_impl_candidate(
4351
ecx: &mut EvalCtxt<'_, D>,
4452
goal: Goal<I, TraitPredicate<I>>,

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

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

44
#![allow(incomplete_features)]
55
#![feature(const_trait_impl, effects)]

Diff for: tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr

-15
This file was deleted.

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

+20-8
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,30 @@ LL | #![feature(const_trait_impl, effects, generic_const_exprs)]
66
|
77
= help: remove one of these features
88

9-
error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
10-
--> $DIR/assoc-type-const-bound-usage-1.rs:15:44
9+
error[E0284]: type annotations needed: cannot normalize `unqualified<T>::{constant#0}`
10+
--> $DIR/assoc-type-const-bound-usage-1.rs:15:37
1111
|
1212
LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
13-
| ^^^^^^^^^^^^^^^^ types differ
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `unqualified<T>::{constant#0}`
1414

15-
error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
16-
--> $DIR/assoc-type-const-bound-usage-1.rs:19:42
15+
error[E0284]: type annotations needed: cannot normalize `qualified<T>::{constant#0}`
16+
--> $DIR/assoc-type-const-bound-usage-1.rs:19:35
1717
|
1818
LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> {
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `qualified<T>::{constant#0}`
2020

21-
error: aborting due to 3 previous errors
21+
error[E0284]: type annotations needed: cannot normalize `unqualified<T>::{constant#0}`
22+
--> $DIR/assoc-type-const-bound-usage-1.rs:16:5
23+
|
24+
LL | Type
25+
| ^^^^ cannot normalize `unqualified<T>::{constant#0}`
26+
27+
error[E0284]: type annotations needed: cannot normalize `qualified<T>::{constant#0}`
28+
--> $DIR/assoc-type-const-bound-usage-1.rs:20:5
29+
|
30+
LL | Type
31+
| ^^^^ cannot normalize `qualified<T>::{constant#0}`
32+
33+
error: aborting due to 5 previous errors
2234

23-
For more information about this error, try `rustc --explain E0271`.
35+
For more information about this error, try `rustc --explain E0284`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//@ compile-flags: -Znext-solver
2+
3+
// Check that `~const` item bounds only hold if the where clauses on the
4+
// associated type are also const.
5+
// i.e. check that we validate the const conditions for the associated type
6+
// when considering one of implied const bounds.
7+
8+
#![allow(incomplete_features)]
9+
#![feature(const_trait_impl, effects)]
10+
11+
#[const_trait]
12+
trait Trait {
13+
type Assoc<U>: ~const Trait
14+
where
15+
U: ~const Other;
16+
17+
fn func();
18+
}
19+
20+
#[const_trait]
21+
trait Other {}
22+
23+
const fn fails<T: ~const Trait, U: Other>() {
24+
T::Assoc::<U>::func();
25+
//~^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
26+
<T as Trait>::Assoc::<U>::func();
27+
//~^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
28+
}
29+
30+
const fn works<T: ~const Trait, U: ~const Other>() {
31+
T::Assoc::<U>::func();
32+
<T as Trait>::Assoc::<U>::func();
33+
}
34+
35+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
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:24:5
3+
|
4+
LL | T::Assoc::<U>::func();
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
7+
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:26: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`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@ compile-flags: -Znext-solver
2+
3+
// Check that `~const` item bounds only hold if the parent trait is `~const`.
4+
// i.e. check that we validate the const conditions for the associated type
5+
// when considering one of implied const bounds.
6+
7+
#![allow(incomplete_features)]
8+
#![feature(const_trait_impl, effects)]
9+
10+
#[const_trait]
11+
trait Trait {
12+
type Assoc: ~const Trait;
13+
fn func();
14+
}
15+
16+
const fn unqualified<T: Trait>() {
17+
T::Assoc::func();
18+
//~^ ERROR the trait bound `T: ~const Trait` is not satisfied
19+
<T as Trait>::Assoc::func();
20+
//~^ ERROR the trait bound `T: ~const Trait` is not satisfied
21+
}
22+
23+
const fn works<T: ~const Trait>() {
24+
T::Assoc::func();
25+
<T as Trait>::Assoc::func();
26+
}
27+
28+
fn main() {}
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`.

0 commit comments

Comments
 (0)