Skip to content

Commit

Permalink
Rollup merge of #132118 - compiler-errors:tilde-const-item-bounds, r=…
Browse files Browse the repository at this point in the history
…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``
  • Loading branch information
workingjubilee authored Oct 25, 2024
2 parents 7782b0d + 3bad501 commit 3c6d34f
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 25 deletions.
11 changes: 11 additions & 0 deletions compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ where
})
}

/// Assemble additional assumptions for an alias that are not included
/// in the item bounds of the alias. For now, this is limited to the
/// `implied_const_bounds` for an associated type.
fn consider_additional_alias_assumptions(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
alias_ty: ty::AliasTy<I>,
) -> Vec<Candidate<I>>;

fn consider_impl_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
Expand Down Expand Up @@ -594,6 +603,8 @@ where
));
}

candidates.extend(G::consider_additional_alias_assumptions(self, goal, alias_ty));

if kind != ty::Projection {
return;
}
Expand Down
51 changes: 50 additions & 1 deletion compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, Interner};
use rustc_type_ir::{self as ty, Interner, elaborate};
use tracing::instrument;

use super::assembly::Candidate;
Expand Down Expand Up @@ -70,6 +70,55 @@ where
}
}

/// Register additional assumptions for aliases corresponding to `~const` item bounds.
///
/// Unlike item bounds, they are not simply implied by the well-formedness of the alias.
/// Instead, they only hold if the const conditons on the alias also hold. This is why
/// we also register the const conditions of the alias after matching the goal against
/// the assumption.
fn consider_additional_alias_assumptions(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
alias_ty: ty::AliasTy<I>,
) -> Vec<Candidate<I>> {
let cx = ecx.cx();
let mut candidates = vec![];

// FIXME(effects): We elaborate here because the implied const bounds
// aren't necessarily elaborated. We probably should prefix this query
// with `explicit_`...
for clause in elaborate::elaborate(
cx,
cx.implied_const_bounds(alias_ty.def_id)
.iter_instantiated(cx, alias_ty.args)
.map(|trait_ref| trait_ref.to_host_effect_clause(cx, goal.predicate.host)),
) {
candidates.extend(Self::probe_and_match_goal_against_assumption(
ecx,
CandidateSource::AliasBound,
goal,
clause,
|ecx| {
// Const conditions must hold for the implied const bound to hold.
ecx.add_goals(
GoalSource::Misc,
cx.const_conditions(alias_ty.def_id)
.iter_instantiated(cx, alias_ty.args)
.map(|trait_ref| {
goal.with(
cx,
trait_ref.to_host_effect_clause(cx, goal.predicate.host),
)
}),
);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
},
));
}

candidates
}

fn consider_impl_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ where
}
}

fn consider_additional_alias_assumptions(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
_alias_ty: ty::AliasTy<I>,
) -> Vec<Candidate<I>> {
vec![]
}

fn consider_impl_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, NormalizesTo<I>>,
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ where
self.def_id()
}

fn consider_additional_alias_assumptions(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
_alias_ty: ty::AliasTy<I>,
) -> Vec<Candidate<I>> {
vec![]
}

fn consider_impl_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, TraitPredicate<I>>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ compile-flags: -Znext-solver
//@ known-bug: unknown
//@ check-pass

#![allow(incomplete_features)]
#![feature(const_trait_impl, effects)]
Expand Down
15 changes: 0 additions & 15 deletions tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr

This file was deleted.

28 changes: 20 additions & 8 deletions tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,30 @@ LL | #![feature(const_trait_impl, effects, generic_const_exprs)]
|
= help: remove one of these features

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

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

error: aborting due to 3 previous errors
error[E0284]: type annotations needed: cannot normalize `unqualified<T>::{constant#0}`
--> $DIR/assoc-type-const-bound-usage-1.rs:16:5
|
LL | Type
| ^^^^ cannot normalize `unqualified<T>::{constant#0}`

error[E0284]: type annotations needed: cannot normalize `qualified<T>::{constant#0}`
--> $DIR/assoc-type-const-bound-usage-1.rs:20:5
|
LL | Type
| ^^^^ cannot normalize `qualified<T>::{constant#0}`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0284`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//@ compile-flags: -Znext-solver

// Check that `~const` item bounds only hold if the where clauses on the
// associated type are also const.
// i.e. check that we validate the const conditions for the associated type
// when considering one of implied const bounds.

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

#[const_trait]
trait Trait {
type Assoc<U>: ~const Trait
where
U: ~const Other;

fn func();
}

#[const_trait]
trait Other {}

const fn fails<T: ~const Trait, U: Other>() {
T::Assoc::<U>::func();
//~^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
<T as Trait>::Assoc::<U>::func();
//~^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
}

const fn works<T: ~const Trait, U: ~const Other>() {
T::Assoc::<U>::func();
<T as Trait>::Assoc::<U>::func();
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
|
LL | T::Assoc::<U>::func();
| ^^^^^^^^^^^^^^^^^^^^^

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

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
28 changes: 28 additions & 0 deletions tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//@ compile-flags: -Znext-solver

// Check that `~const` item bounds only hold if the parent trait is `~const`.
// i.e. check that we validate the const conditions for the associated type
// when considering one of implied const bounds.

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

#[const_trait]
trait Trait {
type Assoc: ~const Trait;
fn func();
}

const fn unqualified<T: Trait>() {
T::Assoc::func();
//~^ ERROR the trait bound `T: ~const Trait` is not satisfied
<T as Trait>::Assoc::func();
//~^ ERROR the trait bound `T: ~const Trait` is not satisfied
}

const fn works<T: ~const Trait>() {
T::Assoc::func();
<T as Trait>::Assoc::func();
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-fail.rs:17:5
|
LL | T::Assoc::func();
| ^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `T: ~const Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-fail.rs:19:5
|
LL | <T as Trait>::Assoc::func();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.

0 comments on commit 3c6d34f

Please sign in to comment.