mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +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(
|
fn consider_impl_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
@ -594,6 +603,8 @@ where
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
candidates.extend(G::consider_additional_alias_assumptions(self, goal, alias_ty));
|
||||||
|
|
||||||
if kind != ty::Projection {
|
if kind != ty::Projection {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||||
use rustc_type_ir::inherent::*;
|
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 tracing::instrument;
|
||||||
|
|
||||||
use super::assembly::Candidate;
|
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(
|
fn consider_impl_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, Self>,
|
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(
|
fn consider_impl_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, NormalizesTo<I>>,
|
goal: Goal<I, NormalizesTo<I>>,
|
||||||
|
@ -39,6 +39,14 @@ where
|
|||||||
self.def_id()
|
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(
|
fn consider_impl_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, TraitPredicate<I>>,
|
goal: Goal<I, TraitPredicate<I>>,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//@ compile-flags: -Znext-solver
|
//@ compile-flags: -Znext-solver
|
||||||
//@ known-bug: unknown
|
//@ check-pass
|
||||||
|
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(const_trait_impl, effects)]
|
#![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
|
= help: remove one of these features
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
|
error[E0284]: type annotations needed: cannot normalize `unqualified<T>::{constant#0}`
|
||||||
--> $DIR/assoc-type-const-bound-usage-1.rs:15:44
|
--> $DIR/assoc-type-const-bound-usage-1.rs:15:37
|
||||||
|
|
|
|
||||||
LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
|
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`
|
error[E0284]: type annotations needed: cannot normalize `qualified<T>::{constant#0}`
|
||||||
--> $DIR/assoc-type-const-bound-usage-1.rs:19:42
|
--> $DIR/assoc-type-const-bound-usage-1.rs:19:35
|
||||||
|
|
|
|
||||||
LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> {
|
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