mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Add support for ~const item bounds
This commit is contained in:
parent
1d4a7670d4
commit
3bad5014c9
@ -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>,
|
||||
@ -594,6 +603,8 @@ where
|
||||
));
|
||||
}
|
||||
|
||||
candidates.extend(G::consider_additional_alias_assumptions(self, goal, alias_ty));
|
||||
|
||||
if kind != ty::Projection {
|
||||
return;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -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>,
|
||||
|
@ -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>>,
|
||||
|
@ -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>>,
|
||||
|
@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -Znext-solver
|
||||
//@ known-bug: unknown
|
||||
//@ check-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(const_trait_impl, effects)]
|
||||
|
@ -1,15 +0,0 @@
|
||||
error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
|
||||
--> $DIR/assoc-type-const-bound-usage-0.rs:14:5
|
||||
|
|
||||
LL | T::Assoc::func()
|
||||
| ^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
|
||||
--> $DIR/assoc-type-const-bound-usage-0.rs:18:5
|
||||
|
|
||||
LL | <T as Trait>::Assoc::func()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -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}`
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
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 E0284`.
|
||||
|
@ -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() {}
|
@ -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`.
|
@ -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() {}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user